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.