We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

Refresh Tokens

To allow our users to stay logged in for longer periods, let's add refresh tokens to our authentication system. At the same time, we'll reduce the lifespan of our access tokens to improve security.

Session Store

In our case, a refresh token will just be a random 256-bit string. It's a token, but not a JSON Web Token. It doesn't need to be a JWT because we'll store it in our database and associate it with a user server-side. No point in using stateless JWTs if we're going to store them in a database anyway.

To revoke a refresh token, we'll set a revoked_at timestamp in the database. If revoked_at is not null, the token is revoked and will be considered invalid.

Assignment

    • token: the primary key - it's just a string
    • created_at
    • updated_at
    • user_id: foreign key that deletes the row if the user is deleted
    • expires_at: the timestamp when the token expires
    • revoked_at: the timestamp when the token was revoked (null if not revoked)
    • rand.Read to generate 32 bytes (256 bits) of random data from the crypto/rand package (math/rand's Read function is deprecated).
    • hex.EncodeToString to convert the random data to a hex string
{
  "id": "5a47789c-a617-444a-8a80-b50359247804",
  "created_at": "2021-07-01T00:00:00Z",
  "updated_at": "2021-07-01T00:00:00Z",
  "email": "[email protected]",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "refresh_token": "56aa826d22baab4b5ec2cea41a59ecbba03e542aedbb31d9b80326ac8ffcfa2a"
}

Look up the refresh token in the database. If it doesn't exist, or if it's expired or revoked, respond with a 401 status code. Otherwise, respond with a 200 code and this shape:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

The token field should be a newly created access token for the given user that expires in 1 hour. I wrote a GetUserFromRefreshToken SQL query.

Revoke the refresh token record in the database that matches the refresh token passed in the request header by setting the revoked_at to the current timestamp. Remember that any time you update a record, you should also be updating the updated_at timestamp.

Respond with a 204 status code. A 204 status means the request was successful but no body is returned.

Run and submit the CLI tests.