[Bug]: Token doesn't get validated due to a clock skew
Version
12.03
Please provide the exception or error you saw
The problem happens when the client time (the clock) is not synchronized with the server time or better said real-time. When client time is out of sync more than 2 minutes the issue happens.
I have tried to extend the TokenValidationService and override the validateIdTokenIatMaxOffset() method, but this is not possible due to the bug reported here: https://github.com/damienbod/angular-auth-oidc-client/issues/1370
Also, increasing the value of maxIdTokenIatOffsetAllowedInSeconds would not be a solution, since we don't know how much the client clock could be out of the sync.
Steps to reproduce the behavior
Change the client time to be for example 5 minutes backwards or ahead of the real-time.
A clear and concise description of what you expected to happen.
Since it is impossible to force every client to turn on the system time sync on their devices, would it be possible to use the server time instead of the client time to calculate the diff between the current time and the iat token time?
validateIdTokenIatMaxOffset(dataIdToken, maxOffsetAllowedInSeconds, disableIatOffsetValidation, configId) {
if (disableIatOffsetValidation) {
return true;
}
if (!dataIdToken.hasOwnProperty('iat')) {
return false;
}
const dateTimeIatIdToken = new Date(0); // The 0 here is the key, which sets the date to the epoch
dateTimeIatIdToken.setUTCSeconds(dataIdToken.iat);
maxOffsetAllowedInSeconds = maxOffsetAllowedInSeconds || 0;
const nowInUtc = new Date(new Date().toUTCString());
const diff = nowInUtc.valueOf() - dateTimeIatIdToken.valueOf();
const maxOffsetAllowedInMilliseconds = maxOffsetAllowedInSeconds * 1000;
this.loggerService.logDebug(configId, `validate id token iat max offset ${diff} < ${maxOffsetAllowedInMilliseconds}`);
if (diff > 0) {
return diff < maxOffsetAllowedInMilliseconds;
}
return -diff < maxOffsetAllowedInMilliseconds;
}
That's not an error, that's a security feature. If you cannot guarantee the client has an accurate time, many defences against replay attacks are gone.
As a practical solution to your conundrum, you can set the maxIdTokenIatOffsetAllowedInSeconds to 300 (five minutes) instead of the default 120 (two minutes).
This is the recommended value for Kerberos (which serves an authentication role similar to OAuth). Additionally it is unlikely that people are even capable of browsing the web when their clock view exceeds such values, because HTTPS websites stop working as TLS encrypted connections cannot be established.
EDIT: Actually the TLS protocol doesn't put any hard demands on clock skew limits, so it must be defined at an application (maybe browser) level.
Obviously using the server time is not an option when you use the time offset to defend against replay attacks.