0
votes

I followed this article to get JWTs issued from .Net Web API http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/

TL;DR

How can I add additional logic to the Authorize attribute to check a database table against a specific claim within the JWT, perhaps within JwtBearerAuthenticationOptions?

Longer version...

It's working fine for generating the JWT and also validating it when firing a request against a controller including the Authorization header...

Basically, what the article doesn't go into is Revocation...

After a lot of googling I see there are several ways of handling Revocation with JWTs.

I have chosen the 'Whitelist' route and so have created a table to store the UserId, ClientId (Audience) and a column containing a JTI value (GUID).

Basically, I want to add additional logic to the [Authorize] attribute to also check this table for a matching JTI for the given User and ClientId...

Is this doable without having to write a custom 'JWTAuthorize' Attribute as I would quite like to use the default...

I suspect it's something that needs specifying within JwtBearerAuthenticationOptions?

Cheers!

1

1 Answers

0
votes

I've managed to get this working using a custom provider on the JwtBearerAuthenticationOptions.

The provider inherits from IOAuthBearerAuthenticationProvider and then I specifically use the ValidateIdentity method to handle the additional logic.

    public Task ApplyChallenge(OAuthChallengeContext context)
    {
        return Task.FromResult<object>(null);
    }

    public Task RequestToken(OAuthRequestTokenContext context)
    {
        return Task.FromResult<object>(null);
    }

    public Task ValidateIdentity(OAuthValidateIdentityContext context)
    {
        string userId = // user id from Token...
        Guid tokenId = // jti from Token...
        string appId = // aud/client id from Token...

        //do the DB check here...
        if (CheckUserToken(userId, tokenId, appId))
        {
            return Task.FromResult<object>(null);
        }
        else
        {
            context.SetError("unauthorized_access", "The supplied security identity for this user is not valid.");
            return Task.FromResult<object>(null);
        }
    }

Then I handle the error on the client side to decide where to redirect the user etc...

If anyone has any better suggestions I'd love to see them :)