Quote of the Day

more Quotes

Categories

Get notified of new posts

Buy me coffee

  • Home>
  • security>

Why you need to register authentication middleware even if your ASP.NET core web API does not handle authentication.

Published February 1, 2020 in .NET core , ASP.NET core , OAuth2 , OpenID Connect , security - 0 Comments

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 UseAuthentication method adds a single authentication middleware component, which is responsible for automatic authentication and the handling of remote authentication requests. 

Authentication Middleware and services

So if my web API does not handle authentication, why do I still need to call UseAuthentication to add the middleware?

Why you need to add the authentication middleware even when your app does not handle authentication.

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();

References

Overview of ASP.NET Core authentication

No comments yet