Description
In an authorization_code flow, sometimes the access_token we receive from the /token endpoint on node1 is not accepted by the /userinfo endpoint on node2.
We are using a distributed cache based OAuth2AuthorizationService and while the machines clocks are synchronized, sometimes a few milliseconds difference can create validation problems.
The code fails in line 58 of OidcUserInfoAuthenticationProvider - isActive()
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
...
if (!authorizedAccessToken.isActive()) {
throw new OAuth2AuthenticationException("invalid_token");
}
....
}
And the reason it fails is because the isBeforeUse() returns true, i.e the time on the machines is before the "nbf".
Solution:
A precise NBF should never be compared directly with current time in distributed systems. There should be a MAX_TIME_DIFF to be taken into account, either at validation or (preferrably) at JWT creation. Is better to extract a MAX_TIME_DIFF~=2s from the actual time at token creation, because at JWT serialization we lose the accuracy of Instant anyways and only seconds are kept.
In the java-jwt library there is an acceptLeeway() method which "Defines the default window in seconds in which the Not Before, Issued At and Expires At Claims will still be valid." - this can be one strategy to validate such claims, but as mentioned a simpler, more visible, and easier for clients is to simply extract the TIME_DIFF from the notBefore claim. Both have the same goal to somehow take into account inherent clock skews between hosts in distributed solutions