This is a copy of our question posted at MS community forum, as it didn't get much traction.
The flow has been previously tested with several other registrations and works fine for all our tenants, except for this one specific tenant (tried several app registrations from the tenant, all the registrations have the same issue). The tenant didn't customise token lifetime.
The endpoint used to issue a token is: https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
(Single-tenant app registration)
The flow uses the data from an id token, that needs to be verified first. A popular NodeJS package is used to verify the token. The problem is that the token always fails to be verified. This is due to the lifetime and expiration of the token, which are represented by the iat
and exp
properties within the token payload.
For example, a token with a payload such as:
{
...,
"iat": 1695209618,
"nbf": 1695209618,
"exp": 1695209918,
...,
"auth_time": 1695209915,
...}
The problem with those values is that this token was requested at 1695209915
, which is almost 5 minutes after the iat
. So the first part of the problem is that the endpoint always issues a token which is almost 5 minutes old. The second part of the problem is the fact that by the time the token arrives to the server it's always already expired. So unless you ignore the token expiry, it can never be validated. FYI, the token from the example above was received by 1695209919
, which is exactly after it had expired.
To recap the weird moments:
iat
is always before the auth_timeWe would appreciate directions and suggestions, from more experienced Azure Identity Platform users, about where to look at, to debug and find the cause of the problem.
What we have tried so far:
The problem was in the max_age
query parameter of the authorization URL provided by our client (the one that a client redirects a user to in order to get an authorization code). The max_age
had a value of 0 (e.g. max_age=0
) which for some reason caused Entra to issue an authorization code that would provide a token that was seemingly issued 5 minutes in the past and immediately expired in the present. We fixed it by removing the query parameter altogether. This resulted into getting a token with the default 60-90 minutes lifetime. More about the query parameter can be read in the OIDC specification.