jtmarmon
jtmarmon

Reputation: 6209

JWT refresh token flow

I'm building a mobile app and am using JWT for authentication.

It seems like the best way to do this is to pair the JWT access token with a refresh token so that I can expire the access token as frequently as I want.

  1. What does a refresh token look like? Is it a random string? Is that string encrypted? Is it another JWT?
  2. The refresh token would be stored in the database on the user model for access, correct? It seems like it should be encrypted in this case
  3. Would I sent the refresh token back after a user login, and then have the client access a separate route to retrieve an access-token?

Upvotes: 334

Views: 288533

Answers (5)

Dennis Meissel
Dennis Meissel

Reputation: 2523

The refresh token flow is described in the OAuth 2.0 specification document.

  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+
  
  
  (A)  The client requests an access token by authenticating with the
       authorization server and presenting an authorization grant.
  
  (B)  The authorization server authenticates the client and validates
       the authorization grant, and if valid, issues an access token
       and a refresh token.
  
  (C)  The client makes a protected resource request to the resource
       server by presenting the access token.
  
  (D)  The resource server validates the access token, and if valid,
       serves the request.
  
  (E)  Steps (C) and (D) repeat until the access token expires.  If the
       client knows the access token expired, it skips to step (G);
       otherwise, it makes another protected resource request.
  
  (F)  Since the access token is invalid, the resource server returns
       an invalid token error.
  
  (G)  The client requests a new access token by authenticating with
       the authorization server and presenting the refresh token.  The
       client authentication requirements are based on the client type
       and on the authorization server policies.
  
  (H)  The authorization server authenticates the client and validates
       the refresh token, and if valid, issues a new access token (and,
       optionally, a new refresh token).

Regarding your questions:

  1. It is another JWT
  2. The refresh token can be stored on the backend of the client‘s side, so that the user can not access it. Otherwise it has to be encrypted.
  3. You get the refresh token as well as the access token after the login. When your access token expires, you send the refresh token to the server to get new refresh and access tokens.

Upvotes: 72

David
David

Reputation: 371

Based in this implementation with Node.js of JWT with refresh token:

  1. In this case they use a uid and it's not a JWT. When they refresh the token they send the refresh token and the user. If you implement it as a JWT, you don't need to send the user, because it would be inside the JWT.

  2. They implement this in a separate document (table). It makes sense to me because a user can be logged in in different client applications and it could have a refresh token by app. If the user lose a device with one app installed, the refresh token of that device could be invalidated without affecting the other logged in devices.

  3. In this implementation, it response to the log in method with both, access token and refresh token. It seems correct to me.

Upvotes: 36

Bhupinder Singh
Bhupinder Singh

Reputation: 3787

Below are the steps to do revoke your JWT access token:

  1. When you do log in, send 2 tokens (Access token, Refresh token) in response to the client.
  2. The access token will have less expiry time and Refresh will have long expiry time.
  3. The client (Front end) will store refresh token in an httponly cookie and access token in local storage.
  4. The client will use an access token for calling APIs. But when it expires, you call auth server API to get the new token (refresh token is automatically added to http request since it's stored in cookies).
  5. Your auth server will have an API exposed which will accept refresh token and checks for its validity and return a new access token.
  6. Once the refresh token is expired, the User will be logged out.

Please let me know if you need more details, I can share the code (Java + Spring boot) as well.

For your questions:

Q1: It's another JWT with fewer claims put in with long expiry time.

Q2: It won't be in a database. The backend will not store anywhere. They will just decrypt the token with private/public key and validate it with its expiry time also.

Q3: Yes, Correct

Upvotes: 321

Yuriy N.
Yuriy N.

Reputation: 6137

JWT has two problems:

  1. lousy standardization

  2. it is hard to revoke (when used for authentication)

The first can be solved by using your own JWT implementation: put in JSON whatever you want, encrypt it with AES - voila - use it for authentication (also for authorization if needed: put roles inside JSON).

Super minimalistic JWT {"id" : "<id>"}

The second problem requires clarification. With regular sessions which are stored on the server side, there is no revocation problem: the session can be invalidated by the server anytime. But regular sessions have problems with scalability and performance, hence JWT.

A common solution to the revocation problem is to use a refresh-token.

Here is how it can be done:

  1. The refresh token can be the exactly same JWT as the access-token: custom JSON encrypted and base64 encoded. The result string can be just duplicated. If the access-token contains a lot of data (for example roles), the refresh token may be different as it needs only the user id. Both access and refresh tokens don't have any expiry hardcoded inside.
  2. They are both stored in https_only cookies but the expiration time for the access-token cookie is 2 min and for the refresh-token cookie is 30 min.
  3. Refresh-token stored in DB (User table) and can be easily revoked/invalidated by deleting from DB.
  4. Server looks for access-token in request: if presents and valid (can be decrypted) - OK process request;
  5. if the access-token does not present (cookie expired), the server looks for a refresh-token: if presents - validate by comparing it to one stored in DB and generate a new access-token (based on information from the refresh-token and DB) and process the request.
  6. If the refresh-token is not there, then the server looks for one of the following: username-password pair, third-party identity provider token (Google, Facebook, etc.), third-party identity management system token (Cognito, Okta, JumpCloud). If any are found: process the request and generate new access and refresh tokens.
  7. If nothing is found, then the server sends an authentication error and forces the client to relogin the user.

Upvotes: 8

Hans Z.
Hans Z.

Reputation: 54088

Assuming that this is about OAuth 2.0 since it is about JWTs and refresh tokens...:

  1. just like an access token, in principle a refresh token can be anything including all of the options you describe; a JWT could be used when the Authorization Server wants to be stateless or wants to enforce some sort of "proof-of-possession" semantics on to the client presenting it; note that a refresh token differs from an access token in that it is not presented to a Resource Server but only to the Authorization Server that issued it in the first place, so the self-contained validation optimization for JWTs-as-access-tokens does not hold for refresh tokens

  2. that depends on the security/access of the database; if the database can be accessed by other parties/servers/applications/users, then yes (but your mileage may vary with where and how you store the encryption key...)

  3. an Authorization Server may issue both access tokens and refresh tokens at the same time, depending on the grant that is used by the client to obtain them; the spec contains the details and options on each of the standardized grants

Upvotes: 88

Related Questions