Sometimes ago, I was confused about the role of the Authentication middleware in an ASP.NET core web API that does not authenticate an user. It makes sense to me that you need to use the Authentication middleware if your web application handles the authentication. Specifically, I did not understand why you need to use Authentication middleware if your app is a web API that does not handle authentication. For instance, my web API performs token validation but it does not authenticate a user. Authentication handling is part of the client application which implements OpenID implicit flow to authenticate the user and obtains authorization to access the web API. I believed I only needed the Authorization middleware so that I can annotate the endpoints I want to protect with the [Authorized]
attribute. The document states
The
Authentication Middleware and servicesUseAuthentication
method adds a single authentication middleware component, which is responsible for automatic authentication and the handling of remote authentication requests.
So if my web API does not handle authentication, why do I still need to call UseAuthentication to add the middleware?
One thing the built-in authentication middleware does for you is setting the User
object and thus effectively making the app aware that the user has authenticated. In my ASP.NET core web API, I register authentication services and call the AddJwtBearer
extension method to perform token validation.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(jwtOptions => { jwtOptions.Authority = adb2cOptions.Authority; jwtOptions.Events = new JwtBearerEvents { }; jwtOptions.TokenValidationParameters.ValidateTokenReplay = true; jwtOptions.TokenValidationParameters.ValidateIssuer = true; jwtOptions.TokenValidationParameters.ValidateAudience = true; jwtOptions.TokenValidationParameters.ValidateLifetime = true; jwtOptions.TokenValidationParameters.ValidateIssuerSigningKey = true; jwtOptions.TokenValidationParameters.ValidAudiences = adb2cOptions.ValidAudiencs; // if you want to debug, or just understand the JwtBearer events, // uncomment the following line of code. jwtOptions.Events = JwtBearerMiddlewareDiagnostics.Subscribe(jwtOptions.Events); });
I also register the authorization middleware by calling app.UseAuthorization()
. Adding the authorization middleware and registering the authentication services, I am able to execute the token validation logic for an incoming request that hits a protected endpoint. However, without registering the authentication middleware by calling app.AddAuthentication()
, my app keeps throwing 401 error even when the JWT token is valid. This is because without the authentication middleware, my codes just validate the token but does set the User object. So when the request hits the controller, the app does not know that the token has been validated and the user is authenticated.
Besides needing to call UseAuthentication()
, the ordering of the calls is also important. In your app, you should register the authentication middleware first, before registering the authorization middleware so the User object is set before authorization takes place.
// Register authentication middleware first app.UseAuthentication(); // then the authorization middleware app.UseAuthorization();
Supporting Multiple Microsoft Teams Bots in One ASP.NET Core Application
Enhancing ASP.NET Core/Blazor App Security and Reusability with HttpMessageHandler and Named HttpClient
About integrated windows authentication and how to implement it in ASP.NET core running on IIS.
Web scraping in C# using HtmlAgilityPack
Building multitenant application – Part 2: Storing value into database session context from ASP.NET core web API
Common frameworks, libraries and design patterns I use
Build and deploy a WebJob alongside web app using azure pipelines
Authenticate against azure ad using certificate in a client credentials flow