Secure API Authentication with NextJs: Access Tokens & Refresh Tokens

Jake Owen
2 min readNov 6, 2021

--

Secure API Authentication with NextJs Series

1. HTTP Only Cookie

2. Set-Cookie from API

3. Development Server

4. Routing Microservice to the Same Port (optional)

5. Client-Side vs Server-Side API Calls

6. Access Token vs Refresh Tokens

Why Refresh Tokens?

The idea of refresh tokens is that if an access token is compromised, because it is short-lived, the attacker has a limited window in which to abuse it. Refresh tokens, if compromised, are useless because the attacker requires the client id and secret in addition to the refresh token in order to gain an access token.

Extending Set-Cookie

Firstly, we need to extend our Set-Cookie header from Set-Cookie from API to also return a refresh token. The lifespan of the accessToken will be much shorter than the refreshToken. The access token is now set to 1hr, whereas the refresh token is set to 30 days. Therefore - a user will only have to login again if they do not use the site for 30 days.

Client-Side

To secure our cookies, the tokens are set with the HttpOnly flag. Therefore, they cannot be accessed using javascript. To check if we need to refresh our access token - we have two options:

  1. Wait until there is a 401 response — and then refresh our tokens.
  2. Return an additional header with the same expiry.

Either option is fine — I prefer option 2 — as with option 1, an extra API call is required every time a token expires.

We’ll extend our set-cookie's header to return a non-HTTP-only token with the same expiry as our access token. Note, we can use the same header keyif we change the casing.

Now, we can extend our post request to check if the new cookie tokenLife exists, only on client-side. If it doesn't, we'll call our refresh token API. The refresh token API should check the validity of the refreshToken - and if it's valid, return the same headers above with new tokens.

Server-Side

On server-side, we can access all cookies, which means we can directly check if accessToken exists. If it doesn’t, we need to call our refresh token API, extract the headers, and set them in the context.

--

--