3

I have been doing multiple tutorials trying to understand how authentication works in ASP.NET Core. I understand the general concept of how middleware processes a request; however, I'm confused on how the CookieAuthenticationMiddleware exactly works. I understand that it looks for a cookie, which is basically your encrypted identity, and if it is there, it sets your current identity to the values in the cookie.

How does the original cookie get created for the actual CookieAuthenticationMiddleware. It seems to me that this middleware is only helpful if there has been a cookie already generated for it to read. To me you would need another authenticator, like a social login, to set the initial cookie. Something like:

app.UseCookieAuthenticationMiddleware(...)
app.UseFacebookAuthentication(...)

Additionally, how would the Facebook authentication set a cookie that the cookie authentication middleware would recognize? The docs says that once you have created a principal (presumably from the Facebook middleware), you can call:

await HttpContext.Authentication.SignInAsync(
    "MyCookieMiddlewareInstance", 
    principal);

Maybe the Facebook middleware calls this to set the cookie, but I don't really understand what this method does.

My question basically comes down to two points: How does the initial cookie get created for cookie auth middleware, and how does HttpContext.Authentication.SignInAsync(...) trigger the cookie middleware to go create a cookie?

Thanks!

1
  • one great thing about asp.net being open source is you can study the source code. if you want to know more about the internals of the cookie middleware and other security components, you can find the code here github.com/aspnet/Security Commented Oct 29, 2016 at 17:02

1 Answer 1

5

How does the original cookie get created for the actual CookieAuthenticationMiddleware.

The cookie authentication middleware signs in the user and creates the cookie. The cookie authorization middleware looks for the cookie values.

To illustrate, here are a few lines from the CookieAuthenticationHandler, which show the cookie authentication middleware setting a cookie.

Options.CookieManager.AppendResponseCookie(
    Context,
    Options.CookieName,
    cookieValue,
    cookieOptions);

And here are a few lines from the DenyAnonymousAuthorizationRequirement : IAuthorizationHandler that show the authorization middleware looking for a cookie value that has been added to the context.

var user = context.User;
var userIsAnonymous =
    user?.Identity == null ||
    !user.Identities.Any(i => i.IsAuthenticated);
if (!userIsAnonymous)
{
    context.Succeed(requirement);
}

You also asked this:

...how would the Facebook authentication set a cookie that the cookie authentication middleware would recognize?

Facebook authentication is OAuth authentication, which means that it is at the bottom of the following inheritance hierarchy.

IAuthenticationHandler
└── AuthenticationHandler
    └── CookieAuthenticationHandler
    └── RemoteAuthenticationHandler
        └── OAuthHandler
            └── FacebookHandler 

In Facebook OAuth, RemoteAuthenticationHander.HandleRemoteCallbackAsync handles Facebook's response and then makes a call to SignInAsync.

Context.Authentication.SignInAsync(
    Options.SignInScheme, 
    context.Principal, 
    context.Properties);

That call to SignInAsync is what you hypothesized in your question.

...the Facebook middleware calls [SignInAsync] to set the cookie, but I don't really understand what this method does.

What SignInAsync does is complicated. The call to SignInAsync happens on the instance of AuthenticationManager that lives inside the Context.Authentication property. That instance is usually the DefaultAuthenticationManager. You can see the full SignInAsync call here, and here is a snippet from it.

public override async Task SignInAsync(
    string authenticationScheme, 
    ClaimsPrincipal principal, 
    AuthenticationProperties properties)
{
    ...

        var handler = HttpAuthenticationFeature.Handler;

        var signInContext = new SignInContext(
            authenticationScheme, 
            principal, 
            properties?.Items);

        if (handler != null)
        {
            await handler.SignInAsync(signInContext);
        }

    ...
}

In other words, SignInAsync calls SignInAsync on an authentication handler, which happens to be an instance of an IAuthenticationHandler from the inheritance hierarchy.

We eventually arrive at CookieAuthenticationHandler.HandleSigninAsync, which will append the cookie to the response. This cookie handler contains the only two calls to AppendResponseCookie in the Security repository.

protected override async Task HandleSignInAsync(SignInContext signin)
{
    ...

    Options.CookieManager.AppendResponseCookie(
        Context,
        Options.CookieName,
        cookieValue,
        signInContext.CookieOptions);

    ...
}

There are a lot of moving parts. Hopefully this answer gives enough of an overview to fill in the missing pieces yourself.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.