I can suggest that the WsFederation parameter in OWIN is good, but requires cookies ... and they are a different kind of cookie than local auth with cookies. ADFS 2.0 / WsFederation uses AuthenticationType = "Cookies", and local authentication uses AuthenticationType = "ApplicationCookie". As far as I know, they are apparently incompatible. I think you will have to use tokens for ADFS, but I believe that ADFS 3.0 requires 2012R2. Use OWIN OAuth for this.
UPDATE: after some time, I figured out how to make these two types of authentication coexist peacefully in the same web application. Using OWIN, configure the CallCookieAuthentication TWICE call once to enable the new WsFederationAuthentication middleware and enable local cookie authentication again. This is not intuitive, but behind the scenes, by specifying different types of authentication for each, they set them up as different “engines”. Here's what it looks like in my startup:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { OnResponseSignIn = ctx => { ctx.Identity = TransformClaims(ctx, app); } } }); app.UseCookieAuthentication(new CookieAuthenticationOptions { Provider = new CookieAuthenticationProvider { OnResponseSignIn = ctx => { ctx.Identity = TransformClaims(ctx, app); } } }); app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions { Wtrealm = Realm, MetadataAddress = Metadata, Caption = "Active Directory", SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType });
This allows users to authenticate both in local SQL tables and in ADFS 2.0. The TransformClaims callout allows me to normalize my claims between the two providers so that they are consistent.
EDIT: Here are very rudimentary TransformClaims. You can do many things inside this: get a user from your database, configure navigation requirements, user permissions, role collections, whatever. I just built this smaller version from a much larger implementation, so I did not run it, but I hope you get an idea of how to use the OnResponseSignIn event.
private static ClaimsIdentity TransformClaims(CookieResponseSignInContext ctx, IAppBuilder app) { var ident = ctx.Identity; var claimEmail = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Email); var claimName = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Name); //normalize my string identifier var loginString = (claimEmail != null) ? claimEmail.Value : (claimName != null) ? claimName.Value : null; var efctx = ctx.OwinContext.Get<DBEntities>(); var user = UserBL.GetActiveUserByEmailOrName(efctx, loginString); if (user == null) { //user was auth'd by ADFS but hasn't been auth'd by this app ident.AddClaim(new Claim(ClaimTypesCustom.Unauthorized, "true")); return ident; } if (ident.Claims.First().Issuer == "LOCAL AUTHORITY") { //Local //local already has claim type "Name" //local didn't have claim type "Email" - adding it ident.AddClaim(new Claim(ClaimTypes.Email, user.Email)); } else { //ADFS //ADFS already has claim type "Email" //ADFS didn't have claim type "Name" - adding it ident.SetClaim(ClaimTypes.Name, user.UserName); } //now ident has "Name" and "Email", regardless of where it came from return ident; }