UseCookieAuthentication vs. UseExternalSignInCookie

asp.net MvcOwin

asp.net Mvc Problem Overview


I use Owin to authorize through Google oAuth. Here is how my cookies are configured:

// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Authentication/Login")
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

So am using both UseCookieAuthentication and UseExternalSignInCookie and it seems redundant. Which of these two AuthenticationTypes should I specify for IAuthenticationManager methods (SignIn, SingOUt, etc.)? Or should I keep just one of them?

Update. What confuses me most is SignIn method:

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

So signsout from ExternalCookie, but signs in ApplicationCookie.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

You need all of them, if you want Google sign in to work. This is how it works. In the OWIN pipeline, you have three middleware components: (1) the cookie authentication middleware running in active mode, (2) another instance of cookie authentication middleware but running in passive mode, and (3) Google authentication middleware. That will be like so.

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    ...
}); // Active

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // Passive

app.UseGoogleAuthentication(...);

When there is a 401, your user gets redirected to Google. There, your user logs in and Google validates the credential. Google then redirects the user back to your app. At this point, Google authentication middleware gets the login info, applies a grant (read external cookie) and short circuits the OWIN pipeline and redirects to the external callback URL, which corresponds to ExternalLoginCallback action method of AccountController. So, at this point when the request comes to your app as a result of redirect, you get the external cookie with the user name and email claims.

In order to read this cookie and retrieve the data (user name, etc) from Google, you use the cookie authentication middleware running in passive mode. Since this middleware runs in passive mode, it must be told to read the cookie. That's what happens when call to AuthenticationManager.GetExternalLoginInfoAsync() is made in the ExternalLoginCallback action method. At that point, identity from the external cookie has been established and this identity contains only the name and email claims from Google.

Typically, at this point you will need to retrieve user specific information from your application data store and add more claims to the identity. So, you call Signout on the external cookie middleware, which will also ensure the external cookie gets no longer sent back by expiring it. So, using the identity information available at that time, UserManager.FindAsync is called in the ExternalLoginCallback action method, which should return the user with all application specific claims. Using that new identity, you call SignIn on the cookie authentication middleware running in active mode. This ensures a new cookie is created. Compared to the external cookie, this new cookie contains all the application specific claims. Subsequently, you get this cookie back and the cookie authentication middleware running in active mode actively reads the cookie and establishes identity with complete list of all application specific claims.

So, if you do not call Signin, you will not be creating that cookie containing all application specific claims. But then it is up to you to use some other mechanism. The out of box behavior is that a local cookie containing all the application specific claims is created through that call to SignIn and subsequently read by the cookie middleware running in active mode.

UPDATE: I have created a blog post to explain how you can get away without using two cookie middleware instances. http://lbadri.wordpress.com/2014/10/14/barebones-asp-net-mvc-google-signin-through-owin-middleware/

Solution 2 - asp.net Mvc

"SignOut(DefaultAuthenticationTypes.ExternalCookie)" is to "cleanup, the external cookie" as per Hao Kung's answer https://stackoverflow.com/a/20575643/2710179

There is a nice implementation in the Microsoft.aspnet.identity.samples project which you can download from nuget. In this implementation they use:-

    var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

"ExternalCookie" is the "Default value used for the ExternalSignInAuthenticationType configured" I believe this means it is used as temporary cookie use to verify the user against an external sight

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSiberianGuyView Question on Stackoverflow
Solution 1 - asp.net MvcBadriView Answer on Stackoverflow
Solution 2 - asp.net MvcJonathan JansenView Answer on Stackoverflow