aspnet / AspNetKatana

Microsoft's OWIN implementation, the Katana project
Apache License 2.0
959 stars 331 forks source link

ClockSkew Ignored by OAuthBearerAuthenticationHandler #507

Open DwayneNickels-tyler opened 12 months ago

DwayneNickels-tyler commented 12 months ago

This is a duplicate of https://github.com/aspnet/AspNetKatana/issues/219, but that issue was closed and there didn't seem to be a fix for the issue.

I am using a custom JwtSecurityTokenHandler class. The ValidateToken method is overridden in the custom class. The custom JwtSecurityTokenHandler class uses a TokenValidationParameters.ClockSkew value of 5 minutes. The custom JwtSecurityTokenHandler class calls base.ValidateToken(...).

If I receive a bearer token at 9:01:00 with an expiration datetime of 9:00:00, the call to base.ValidateToken returns a ClaimsPrincipal and doesn't throw any exceptions because 9:01:00 is within the ClockSkew grace period (the ValidateToken call is successful up until 9:05:00). In that regard, the code in the custom JwtSecurityTokenHandler is working as expected. However, I'm finding that once the control flow leaves the custom JwtSecurityTokenHandler class, then something unexpected happens. The call fails with a 401 HTTP response code. OWIN logging captures the log event below:

Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Warning: 0 : expired bearer token received

The issue appears to be that the OAuthBearerAuthenticationHandler doesn't take into account the ClockSkew setting.

// Validate expiration time if present
DateTimeOffset currentUtc = Options.SystemClock.UtcNow;

if (ticket.Properties.ExpiresUtc.HasValue &&
    ticket.Properties.ExpiresUtc.Value < currentUtc)
{
    _logger.WriteWarning("expired bearer token received");
    return null;
}

Is this a bug in the OAuthBearerAuthenticationHandler class or a misunderstanding on my part of how JwtSecurityTokenHandler / TokenValidationParameters.ClockSkew / OAuthBearerAuthenticationHandler are supposed to collectively work together?

Tratcher commented 12 months ago

The problem is that it doesn't know about the ClockSkew option, that's coming from an external component. At best you could skew the SystemClock abstraction by 5 minutes.

DwayneNickels-tyler commented 12 months ago

I'm not finding an easy way to override the SystemClock implementation. It looks like UseJwtBearerAuthentication creates the OAuthBearerAuthenticationOptions instance internally. That OAuthBearerAuthenticationOptions instance contains the SystemClock property. Once the OAuthBearerAuthenticationOptions instance is built and added to the middleware collection of AppBuilder, it's not obvious to me how to obtain a reference to it in order to alter the SystemClock property. Is there an accepted way of doing such a thing?