I have a question about light-oauth2 refresh tokens. It appears that they never expire so must be manually revoked, which IMO causes maintenance and security issues, and also seems to contradict the light-oauth2 docs.
(Note: My ears are open to explanations about this behaviour, as there may be very good reasons behind it. It is simply (at the moment) counterintuitive to me.)
More Details
The refresh tokens accumulate indefinitely in the refresh_token table. There does not appear to be any code in CacheStartupHookProvider that gives them a TTL. As you can see, the code that would seem to evict refresh tokens after 1 day has been commented out (lines 108-119):
// fresh token map with near cache and evict. A new refresh token will
// be generated each time refresh token is used. This token only lives
// for 1 day and it will be removed from the cache automatically.
MapConfig tokenConfig = new MapConfig();
tokenConfig.setName("tokens");
NearCacheConfig tokenCacheConfig = new NearCacheConfig();
/*
tokenCacheConfig.setTimeToLiveSeconds(24 * 60 * 60 * 1000); // 1 hour TTL
tokenCacheConfig.setMaxIdleSeconds(24 * 60 * 60 * 1000); // 30 minutes max idle seconds
tokenCacheConfig.setInMemoryFormat(InMemoryFormat.OBJECT);
tokenCacheConfig.setCacheLocalEntries(true); // this enables the local
*/
Also, the light-oauth2 docs state that:
"The authorization server issues a new refresh token and the client MUST discard the old refresh token and replace it with the new refresh token. The authorization server revoke the old refresh token after issuing a new refresh token to the client." (emphasis mine)
But my own tests show that this isn't happening. For example:
Step 4 seems to contradict the docs, which say that The authorization server revoke the old refresh token after issuing a new refresh token to the client. From step 4 above, however, it does not appear that refresh token R1 has been revoked even after the new refresh token R2 has been issued. R1 is still able to get new authorization tokens.
So now, R1, R2, and R3 can all be used to get new authorization tokens, and the set of useable refresh tokens keeps growing indefinitely.
My question is whether this is an omission or by design (and perhaps the docs should be updated). And if it is by design, what is the rationale for this? It would seem to me that
Thanks for any help
These are all good questions and I think you have identified a defect in the implementation.
First, let me explain why we issue a new refresh token every time the old refresh token is used.
As we all know, the access token we issued is a JWT token and it cannot be revoked once it is issued. To mitigate the risk of the stolen access token, we have to make sure that the access will be expired within a short period. Normally, itis between 5 minutes to 15 minutes depending on the implementation. This is where the refresh token has emerged. It can be last longer and most OAuth 2.0 implementation provides an API to revoke it upon the report that the refresh token is stolen from the user. Depending on the security level of the web application, sometimes, the refresh token needs to last 24 hours to several months. We don't want to limit it so we remove the TTL for the refresh token so that it will never expire. To maximize the security, we don't want to reuse the refresh token again and again, so a new refresh token is issued along with the access token. This makes the refresh token a one-time token so it won't last long enough once it is stolen as the active session will have to renew the access token every 5 to 15 minutes unless the application is closed.
What you found that the previous refresh token still can be used to get access token is strange and it might be a defect. If you look at this line of the code https://github.com/networknt/light-oauth2/blob/master/token/src/main/java/com/networknt/oauth/token/handler/Oauth2TokenPostHandler.java#L393
The old refresh token is removed from the database and cache. I don't know if the Hazelcast will cache the data longer or not. We need more testing and investigation for this issue. Would you be able to open an issue on the light-oauth2 repo?
As this is about security, we need to pay more attention to all the details. Let's figure this out and get it fixed together. Thanks a lot for raising the issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With