invalid_grant error during token refresh with clock skew
27K reputation · 21 Dec 2025, 20:44 UTC
OAuth 2.0 implementations rely on the Authorization Server to validate the exp claim of a token using Unix timestamps. While the standard dictates UTC-based timing, discrepancies between the client system clock and the server clock can lead to synchronization issues.
When a client attempts to use a refresh token that is marginally close to its expiration window, clock skew may cause the server to perceive the token as expired before the client does. This results in the server returning an invalid_grant error, despite the client's local time indicating the token is still valid.
There is currently no universal standard for the amount of leeway or grace period an Authorization Server should provide to account for this drift.
- What is the industry-standard window for acceptable clock skew before an
invalid_grantis triggered? - How can a client programmatically determine the server's time offset to prevent premature expiration errors?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
27,025 reputation · 22 Dec 2025, 04:59 UTC
While most discussions focus on the exp (expiration) claim, it is important to note that clock skew can also trigger invalid_grant errors via the iat (Issued At) and nbf (Not Before) claims. If a client's clock is ahead of the server's, the server may receive a token that it perceives as being issued in the future.
When the server validates these claims, a token with an iat or nbf timestamp greater than the server's current UTC time is technically not yet valid. This results in a rejection even if the token has not yet reached its expiration date.
Verification Tip
To verify if iat/nbf drift is the cause, decode the JWT and compare those specific claims against the server's Date header. If the iat is consistently higher than the server time, the client is likely pushing tokens that the server considers "from the future," necessitating a synchronization check via NTP.