简体   繁体   中英

Optional authorization with multiple JWT authentication schemes in ASP.NET 5.0

I'm using multiple JWT Bearer authentication as documented by Microsoft It all works fine, up until the point where I put it into an application that has controller methods that need optional authentication (a property in appsettings.json controls whether the request needs to be authenticated or not)

I'm doing the optional authentication using my own attribute that implements IAsyncAuthorizationFilter

public class OptionalAuthorizationAttribute: Attribute, IAsyncAuthorizationFilter
{

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        SetUnauthorized(context);
    }

    public Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        SetUnauthorized(context);
        return Task.CompletedTask;
    }

    private void SetUnauthorized(AuthorizationFilterContext context)
    {
        var configService = (IConfiguration)context.HttpContext.RequestServices.GetService(typeof(IConfiguration));
        if (configService != null)
        {
            var enableAuth = configService.GetValue<bool>("AppSettings:EnableAuthentication");
            if (enableAuth)
            {
                if (user?.Identity?.IsAuthenticated != true)
                {
                    context.Result = new UnauthorizedResult();
                }
            }
        }
        else
        {
            context.Result = new UnauthorizedResult();
        }
    }

}

When I use a single authentication scheme, this works like a charm. When I use two schemes, it works for the default scheme ('Bearer', but not my second scheme). Looking at the logs, I see this

2021-07-19 14:50:41.616 +02:00 [Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Failed to validate the token. Microsoft.IdentityModel.Tokens.SecurityTokenUnableToValidateException: IDX10516: Signature validation failed. Unable to match key:

Now, as I understand that's normal when the first jwt scheme cannot validate the token.. the second can. But, in my OptionalAuthorizationAttribute context.HttpContext.User.Identity is now unauthenticated, so the request is still rejected. I'm guessing that the User.Identity is being populated by what is gotten from the token after it goes through the default scheme (which cannot validate the token so it's an empty ClaimsIdentity and unauthorized.

Any chance I can get the Identity from the second authentication scheme instead? (and make this generic in case I ever need to add additional auth schemes).

Things to work just fine if I swap out my [OptionalAuthorization] tag on the controller and replace it with [Authorize] so I know that my setup is complete.. it's just that my attribute gets triggered before the token has been validated using the second scheme.

Here's a controller showing how I'm using my OptionalAuthorizationAttribute

[Route("[controller]")]
[ApiController]
public class WebDirectoryController:ControllerBase 
{

    [HttpGet]
    [OptionalAuthorization]
    [Route("Sources")]
    public IActionResult GetPlugins()
    {
        ... implementation
    }

}

I have been digging into this topic and after reading through this wanted to respond with my perspective of how to handle authenticating with multiple JWT tokens.

I assume the code you are sharing is a class that defines a custom auth policy. Through my research I see official documentation using AuthorizationPolicyBuilder : Use multiple authentication schemes

I dont see why you cant just determine if you want to add the optional auth policy using the configuration value at startup following the microsoft doc linked above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM