JWT replay validation based on jti claim rather than on expiration time

Viewed 1813

In my Asp.net Core based Web API I would like to use jti (JWT ID) claim to prevent replay attacks while working with JWT (JSON Web Tokens).

As suggested I configured JWT Bearer authentication:

services.AddAuthentication(o =>
{
    o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateTokenReplay = true,
        IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
        {
            // Resolving decryption key
        },
        TokenReplayValidator = (expirationTime, /*string*/ token, validationParameters) =>
        {
            // I can check expiration time, but there is no way to check jti
        },
    };
    o.SaveToken = true;
});

In replay validator I can access an expiration time, but there is no way to get jti somehow.

I find it a bit confusing. What common might have a replay attack and an expiration time?

Moreover we have another validator:

bool LifetimeValidator(DateTime? notBefore, DateTime? expires, 
                       SecurityToken securityToken, 
                       TokenValidationParameters validationParameters);

Here I can access the SecurityToken data including jti, but I can't believe that this is a right place for jti-based replay attack validation.

So the question is: how could I get SecurityToken data inside TokenReplayValidator?

UPDATE:

After the @orhtej2 comment, I checked the possibility which he suggested. That works indeed:

TokenReplayValidator = (expirationTime, token, validationParameters) =>
{
    var handler = o.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().First();
    var securityToken = handler.ReadJwtToken(token);
    var jti = securityToken.Id;
    // check replay attack
},

Well, it is a solution, but requires additional token parsing (which cannot be good - unnecessary calculations required on the each HTTP call).

I would like to keep the question unanswered until some better solution found.

0 Answers
Related