While building a React App I came across OAuth2.0 user authentication using JWT access tokens and refresh tokens. I understand why an access token should only be short-lived, but assuming that both a access- and refresh tokens can be compromised, I don't understand why a refresh token is necessary.
The usual access/refresh token procedure (as far as I understood) is:
- When the client logs in, send both a short-lived access token and long-lived refresh token to client and save refresh token details in a server-side database.
- Once the access token expires, the client sends a "refresh" request using both the expired access token and the refresh token. The server then updates the database and sends back the new access token.
- If the refresh token is compromised, both the hacker and the actual client will try to request a new access token using the compromised refresh token. The hack is detected and both the user and the hacker will be logged out.
However, I don't understand, why the refresh token is necessary. The auth-flow could also work similar to this Stackoverflow reply:
- When the client logs in, only send a single, short-lived access token to the client and save access token details in a server-side database. The token includes user-id and the
update_time - For every request, the client sends the access token.
- The server always checks, if the access token has expired. If it has:
- Check in the database if
update_timeequals to the expired JWT token. - If it does (you could add other requirements like a maximum until it completely expires, user agent etc.), update the
update_timeand send back a new JWT.
- Check in the database if
- The client app always needs to check wether a new JWT was sent with the original request and has to update it accordingly.
This way, the access token would be valid only once after its expiry time and then be updated accordingly. Trying to refresh the same expired access token twice (=compromised token) would result in the same error as explained above.
In my opinion, this has the same benefits as two tokens. The only main difference is that a "refresh" would not be sent to an Auth server by the client itself (like in many cases and the official ietf documentation) but instead to the resource server, which would then redirect the refresh to the Auth server and handle all that for the client... So, what am I missing?