How does ASP.NET Core Authentication Work?

How does ASP.NET Core Authentication Work?

One of the key features of an application is knowing who the current user is. This is called authentication. ASP.NET Core includes authentication middleware to allow a user to be identified before the main application code starts executing.

This is important as it allows authorisation checks to be carried out to ensure that the identified user has the appropriate permissions for the resource they are attempting to access, or the actions they are attempting to complete.

Understanding the ASP.NET Core Authentication

The ASP.NET Core authentication system consists of several components that work together to authenticate and authorise incoming requests. These components include middleware, authentication handlers, authentication schemes, and options.

Middleware

Middleware processes incoming requests in an ASP.NET Core application and can be used to modify the request or the response. They can also carry out their own functions and then pass the request to the next middleware component in the pipeline for further processing.

The authentication middleware is a special type of middleware that handles authenticating incoming requests. The authentication middleware sits at the beginning of the pipeline and intercepts all incoming requests before they reach the controllers and action methods or minimal API endpoints.

Authentication Handlers

Authentication handlers are responsible for performing the actual authentication of incoming requests. Each authentication handler implements a specific authentication scheme, such as cookie, JWT, or API key authentication.

Authentication handlers implement the IAuthenticationHandler interface (or the AuthenticationHandler<TOptions> class), which defines methods for handling authentication challenges and processing authentication requests. The AuthenticateAsync method is the most important method of an authentication handler, as it performs the actual authentication of the request.

Authentication Schemes

Authentication schemes are named collections of authentication handlers. Each authentication scheme is given a unique name and has one or more authentication handlers that implement the same authentication scheme.

For example, the cookies authentication scheme might have a handler that reads cookies from the request and a handler that writes cookies to the response. Similarly, the JWT authentication scheme might have a handler that reads JWT tokens from the request and a handler that validates the tokens and extracts the claims.

Options

Options are configuration settings that control the behaviour of the authentication system. Options are defined in classes that inherit from the AuthenticationSchemeOptions class.

Authentication handlers access options through a variation of the IOptions interface, which allows them to retrieve and modify the authentication options at runtime.

Authentication Flow

Since it is typically important to have identified a user before other ASP.NET Core middleware or application logic executes, authentication middleware should be registered early in the middleware pipeline.

The authentication flow that takes place in ASP.NET Core follows these steps:

  1. The authentication middleware intercepts an incoming request.
  2. The middleware determines which authentication scheme to use based on the options specified in the configuration.
  3. The middleware invokes the authentication handler associated with the selected authentication scheme.
  4. The authentication handler performs the actual authentication by examining the request headers, cookies, or other authentication tokens.
  5. If the authentication is successful, the authentication handler creates a ClaimsIdentity object that contains information about the authenticated user, such as their username or email address.
  6. The authentication handler creates a ClaimsPrincipal object that contains the ClaimsIdentity object and any associated claims.
  7. The authentication handler creates an AuthenticationTicket object that contains the ClaimsPrincipal object and any authentication properties.
  8. The authentication handler returns an AuthenticateResult object that contains the authentication ticket and a success status.
  9. If the authentication is unsuccessful, the authentication handler returns an AuthenticateResult object with a failure status and an error message.
  10. If the authentication is successful, the middleware sets the User property of the HttpContext object to the ClaimsPrincipal object created by the authentication handler.
  11. The request is then passed to the next middleware component in the pipeline, which can access the User property to authorize the request based on the authenticated user's claims.

After all the middleware has completed execution, the ASP.NET Core MVC controller, Razor Page or Minimal API action is then executed with all the appropriate authentication information available.

At this point, checks can take place to ensure that the authenticated user has the appropriate authorisation to access the specified resource or perform the requested action.

Summary

ASP.NET Core has a highly extensible middleware system which is leverages for performing authentication. Authentication middleware can support a wide variety of authentication schemes (methods of authentication) and allows developers to add their own implementations for authentication schemes as required.

As the authentication middleware can identify a user through any of the registered authentication schemes, the same user could be identified through an authentication cookie, a JWT or an API key and then have the same authorisation logic applied to the user.

This makes the ASP.NET authentication and authorisation system highly flexible, but also very verbose and not as easy to implement for simple use cases.