This project has moved and is read-only. For the latest updates, please go here.

connect MVC 5 app to ADFS 2.0

Dec 15, 2014 at 1:05 PM
Edited Dec 15, 2014 at 1:07 PM
Hi,
I have created fresh MVC 5 app and installed microsoft.owin.security.wsfederation nuget package.
WsFederation in Startup.Auth is configured as follows:
app.UseWsFederationAuthentication(wtrealm: "MyRealm",
               metadataAddress: "https://myADFSInstanceHost/FederationMetadata/2007-06/FederationMetadata.xml");  
Federation button at login page works fine. ADFS login page is achievable, i can log in there. But when callback to mvc app is performed, in ExternalLoginCallback controller AuthenticationManager.GetExternalLoginInfoAsync() returns null.
Adfs itself works ok, i can authenticate against it using pure WIF VS template.
Please suggest what could be wrong.. Thanks
Dec 15, 2014 at 6:20 PM
i am totally confused.. What needs to be used in order to connect mvc5 web app to ADFS 2.0 via OWIN/Katana? UseWsFederationAuthentication or UseActiveDirectoryFederationServicesBearerAuthentication ( from microsoft.owin.security.activedirectory )? Could some one route me to a working sample of such integration?
Dec 15, 2014 at 6:43 PM
UseWsFederationAuthentication is for interactive web pages (redirects to a login page, etc.). UseActiveDirectoryFederationServicesBearerAuthentication is for API access.

You can use Fiddler, Netmon, etc., to look at the request and response headers to see what happens. You're primarily looking for Set-Cookie and Cookie headers that preserve the identity across requests.
Dec 15, 2014 at 7:48 PM
OK, i am using UseWsFederationAuthentication, as i need to be redirected to adfs login and then redirected back to my app.
Here is sequence of request/response i have:
0)"Federation button" does postback to my app, ExternalLogin controller: https://localhost/Account/ExternalLogin.
Controller sends to browser Transport header. Location is
https://myadfshost/adfs/ls/?wtrealm=http%3a%2f%2flocalhost%3a8099%2f&wctx=WsFedOwinState%3dMBvRAJio3ujFUvpOjAUprOyfqVy5jX0XXMtQPj26d42xKJpGJAIjpZAmuULCGNJWy03w0NbRjpWLd7elcdlu1lroKfAaWAkWY_ZfDaIZhNbudRqwEcwxVD46kCujm1VYCIDzCMSsJYu57ZeNU7JVSw&wa=wsignin1.0
1)After successful authentication at adfs login page, it sets several cookies:
MSISAuth,
MSISAuth1,
MSISAuthenticated,
MSISIPSelectionPersistent,
MSISLoopDetectionCookie,
MSISSignOut
and does POST to https://localhost/ (as it is configured at ADFS as WS-Federation end point).
POST contains 3 hidden fields: wa, wresult, wctx.
3) https://localhost/ returns to browser Transport header: Location: /Account/ExternalLoginCallback.
4) In ExternalLoginCallback controller AuthenticationManager.GetExternalLoginInfoAsync() returns null.

According to this, i guess, 3) is wrong. Data posted from adfs page are getting lost between transport from localhost to localhost/Account/ExternalLoginCallback.
If it is really wrong, how to configure properly callback URL?
Dec 15, 2014 at 10:30 PM
There should be new Set-Cookie headers with step 3. Sharing your Startup may help identify what's wrong with your cookie setup.
Dec 15, 2014 at 10:52 PM
here it is:
public void ConfigureAuth(IAppBuilder app)
        {            
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
           
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {                   
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });            
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
         
            app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

            app.UseWsFederationAuthentication(wtrealm: "http://localhost:8099/",
              metadataAddress: "https://myadfsendpoint/FederationMetadata/2007-06/FederationMetadata.xml");             
        }
Dec 16, 2014 at 10:13 AM
update: step 3 sends this cookie
__RequestVerificationToken: wMNR8w7aO8ei3bT-ZiSiKWd8y4FG6qaMjEiGrRoFWXonCIkLs_nLYMQLIEv3368X9jgwXKxaT8Kz8AsNf_qlqZxZkTtShhJL_ne1aU4fv_o1
is this what is required at step 4 (callback controller)?
Dec 16, 2014 at 10:22 AM
Edited Dec 16, 2014 at 10:23 AM
update2: steps 3 and 4 sends .AspNet.ExternalCookie. Tratcher, according to another your post it's generated by Katana.
But still i can't get login info from GetExternalLoginInfoAsync()
Dec 19, 2014 at 1:58 PM
up ? pls
Jan 14, 2015 at 2:56 AM
I have similar situation as well Any chance you have the solution?
Jan 14, 2015 at 9:18 AM
I have found a solution for my case. It was my fault, one of relying party at ADFS was configured wrong. And of cause this party i was trying to use for MVC app authentication. In particular, claims rules were not set well. Would be nice to have more detailed exceptions from Katana/Ws-Federation Plug in. When GetExternalLoginInfoAsync just return null, there is no way to debug.
Jan 14, 2015 at 9:37 AM
Woahh its seem very hard to debug:( I am using Azure Active Directory so i am not sure if i can find out what config can be done:(
Jan 14, 2015 at 5:29 PM
Edited Jan 14, 2015 at 5:30 PM
Finally with lots of try and debug. I can use my now and the solution is to remove this line out of StartUp. This allow me to login using Microsoft Account and OpenID at the same time. In my chase OpenID is Azure Active Directory.
Hope this helps
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);