Search code examples
asp.net-coreauthorizationidentityserver4access-tokenopenid-connect

expires_in or expires_at used for access tokens in OpenId connect?


I'm confused as to why the OpenId connect specifications (source: https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) refer to an 'expires_in' key in the JWT, while in ASP.NET Core 2, when using IdentityServer4, expires_at is used, but if you wish to manipulate it, you refer to it as "expires_in". Am I missing something here?

Below is a snippet showing what I'm refering to exactly - tokenResult holds the newly refreshed tokens, by passing in the needed client information + secret (defined in tokenClient), as well as the current refresh token (stored in currentRefreshToken). Why does tokenResult have a property "ExpiresIn", when the one displayed/stored in the access token is named "expires_at"? Shouldn't they both be unified, even though specifications clearly state it should be named "expires_in" (which the property follows, but actual implementation in the JWT doesn't)?

var tokenResult = await tokenClient.RequestRefreshTokenAsync(currentRefreshToken)
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn)
updatedTokens.Add(new AuthenticationToken
{
    Name = "expires_at"
    Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
}

EDIT: I just realized that 'expires_at' might not refer to the access token, but the whole authentication ticket? Please correct me on this, I'm really confused.


Solution

  • The JWT uses iat and exp as claim names, I'm not aware of an expires_at in the spec.

    expires_in is a value that comes back in the token response and that refers to the lifetime of the access_token returned. I suspect the thinking behind it was to allow scheduling of refresh without having to inspect the exp claim in the token.

    The topic you linked to (https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) shows the token endpoint response and not the contents of the JWT.

    Where are you seeing expires_at surfaced? AuthenticationToken is I think an ASP.Net Identity thing so it may well be a calculated value that library stores and is nothing to do with identityserver4 or OpenID Connect at all.

    Based on your comment, it’ll be the OIDC middleware adding those properties to the sign in scheme. Check out the code here on line 138:

    https://github.com/aspnet/Security/blob/7e14b052ea9cb935ec4f5cb0485b4edb5d41297a/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthHandler.cs

    So basically it’s an implementation detail specific to ASP.Net Core’s implementation of OIDC and not part of the protocol itself.