Closed thoo1 closed 3 years ago
@thoo1 Are we talking about access tokens or refresh tokens? If it's access tokens, the token expiration date returned in the response should be calculated based on the client's time. Tokens are valid by default for 1 hour from when they are issued. When you call acquireTokenSilent, it will check the current expiration time based on the client side calculation and renew the token if it is past this time.
We see evidence of this happening in our current application, where the client side log's show the request being made at an incorrect time like 18:36 UTC (the timestamp is from client side clock) but when we search up the request in backend logs, the time is 19:32 UTC and the client had passed a token that is valid until 19:00 UTC
This shouldn't be the case. So lets say the client's clock is skewed 1 hr before the server's clock (using your example). If the client acquired a token at 18:00, the token should have a exp claim, assuming 1hr token lifetime, based on the server's clock of 20:00 in its claims (19:00 + 1hr) (double checking this, but pretty sure that this is how it works), but MSAL will set the expiration date to 19:00. When the token is validated, it should be based on the time of the server's clock.
Are you seeing different behavior? Check the exp claim of the token.
In the above image you can see there is a slight difference in the expiration times - this is because the expiration used by MSAL is calculated separately than the one from the auth server.
There is a tokenRenewalOffsetSeconds
configuration option but this is usually to offset seconds or minutes, not an entire hour.
The client app then makes an api call using the cached token since it thinks it is still valid
How does this happen? The client should be using acquireTokenSilent to retrieve a new token to make sure that the token is still valid. If it isn't valid, acquireTokenSilent should be renewing the token. acquireTokenSilent does this based on the client clock, not the exp claim in the token.
the server rejects the request with a 401
By "the server" do you mean the resource server? How does the token validation happen?
Hi @pkanher617 thanks for taking your time to look into this. I can answer some of your questions
The client app then makes an api call using the cached token since it thinks it is still valid How does this happen? The client should be using acquireTokenSilent to retrieve a new token to make sure that the token is still valid. If it isn't valid, acquireTokenSilent should be renewing the token. acquireTokenSilent does this based on the client clock, not the exp claim in the token.
Sorry for the confusion in my wording, when I said client app I meant the msal-library, we do just use acquireTokenSilent
and don't do anything special on top. I meant to express that msal-browser library thought the token was still valid (as it looks at the client clock, not the exp claim) and our code sent the request with the token. Since the client clock was about an hour behind, the token in reality was expired and the server had rejected it.
This shouldn't be the case. So lets say the client's clock is skewed 1 hr before the server's clock (using your example). If the client acquired a token at 18:00, the token should have a exp claim, assuming 1hr token lifetime, based on the server's clock of 20:00 in its claims (19:00 + 1hr) (double checking this, but pretty sure that this is how it works), but MSAL will set the expiration date to 19:00. When the token is validated, it should be based on the time of the server's clock.
I understand what you're saying, and I agree. If the client clock is consistently 1 hour behind the server, that is fine as long as long as the server validates the token using the exp claim (which will be based on server time). Let me validate this with the backend team, that they are using the exp claim (I don't see any other claim that could be used).
There is one small nuance. What happens if the client clock is not consistently 1 hour behind? I'll see if I can validate this in the logs first before I raise this topic further
Thanks for your answer! I'll do a bit more digging
I think we need to be really clear here about which actors are performing specific actions. There is a client, which calls ATS to get tokens. This client should never be sending expired tokens. ATS always calculates lifetimes based on the client's clock, so it should never return a token that has passed the lifetime.
There is a resource server, which validates the access token. If this service is out of sync, there are going to be issues no matter what.
Finally, there is the auth server which is the one that accepts the login credentials and issues tokens.
Since the client clock was about an hour behind, the token in reality was expired and the server had rejected it.
If the token was used within an hour of when it was issued, the only way it would be expired on the service but not the client would be if the client clock is somehow moving slower than the server's clock, or the resource service is also skewed. Expiration for ATS is calculated based on lifetime, not exact timestamps.
There is one small nuance. What happens if the client clock is not consistently 1 hour behind? I'll see if I can validate this in the logs first before I raise this topic further
Again, the expiration timestamp claim of the token is always based on the auth server's clock, not the client. It depends on the resource service validating the token. If that resource service is out of sync, there isn't much we can do. As I said above, the only way the client would be sending expired tokens is if the clock is somehow moving at a different rate than the auth server's clock. Meaning, 1hr on the service is >1hr on the client.
Closing as this doesn't appear to be a problem with the library. Please open a new issue if you determine there is any action we need to take, thanks!
Library
msal@1.x.x
or@azure/msal@1.x.x
@azure/msal-browser@2.11.1
@azure/msal-node@1.x.x
@azure/msal-react@1.x.x
@azure/msal-angular@0.x.x
@azure/msal-angular@1.x.x
@azure/msal-angular@2.x.x
@azure/msal-angularjs@1.x.x
Description
Is there any guidance on how to deal with client clock being skewed. Eg imagine a scenario where the client's clock thinks it is currently 18:00 UTC and has a cached token that is valid until 19:00 UTC. The client app then makes an api call using the cached token since it thinks it is still valid. However, the actual time is 20:00 UTC, and the server rejects the request with a 401 because the token is expired (the token expires around 19:00 UTC, and the current time is 20:00 UTC)
We see evidence of this happening in our current application, where the client side log's show the request being made at an incorrect time like 18:36 UTC (the timestamp is from client side clock) but when we search up the request in backend logs, the time is 19:32 UTC and the client had passed a token that is valid until 19:00 UTC.
I was wondering if this scenario has been encountered before, if so, is there any guidance on how to handle such situations? In my opinion, it looks like the solution boils down to the client app being aware that the time is incorrect and should react to that (display some error message or force fetch a new token)
Thanks!
Source