Skip to content
  • Build on Kinde
  • Tokens

Refresh tokens

Refresh tokens are used to request new access tokens.

Access tokens are issued when a user makes an authentication request or a call is made to an API. An access token gives permission to enter and interact with a system.

How refresh tokens work

Link to this section

Access tokens usually have an intentionally short lifetime. However, rather than having a user need to re-authenticate frequently, a refresh token can be used to request a new access token. Refresh tokens operate without user intervention, extending session access without the same security risk as requesting a new access token.

Refresh tokens can be used a finite amount of times before re-authentication is required.

How to get a refresh token

Link to this section

To get a refresh token, you need to include the offline scope when you initiate an authentication request through the https://<your_subdomain>.kinde.com/oauth2/auth endpoint. You also need to initiate Offline Access in your API.

Details on how to do this is provided in our SDKs, but here’s how to do it yourself.

Below is an example using the Authorization Code grant, with the offline scope being one of the scopes passed to the authentication request.

Terminal window
curl -G "https://<your_subdomain>.kinde.com/oauth2/auth" \
-d "response_type=code" \
-d "client_id=<client_id>" \
-d "redirect_uri=<redirect_uri>" \
-d "scope=offline%20email%20openid%20profile"

In a real app you typically redirect the user to this URL in a browser rather than calling it with curl. The response will redirect the user to your redirect_uri with an authorization code in the query string; you then exchange that code for tokens (including a refresh token) via POST to https://<your_subdomain>.kinde.com/oauth2/token with grant_type=authorization_code.

Refresh tokens are stored in sessions. When a session needs to be refreshed (for example, a pre-defined time has passed), the app uses the refresh token on the backend to obtain a new access token, using the https://<your_subdomain>.kinde.com/oauth2/token endpoint with grant_type=refresh_token.

Example: request a new access token using a refresh token

Terminal window
curl -X POST "https://<your_subdomain>.kinde.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=<client_id>" \
-d "client_secret=<client_secret>" \
-d "refresh_token=<refresh_token>"

Use this only from a secure backend. Do not send client_secret from frontend or public clients; use PKCE for SPAs and similar apps.

Example of a refresh token response

{
"access_token": "<access_token>",
"refresh_token": "<refresh_token>",
"token_type": "Bearer"
}

Refresh token rotation

Link to this section

Kinde always rotates refresh tokens. When you use an existing refresh token to request a new access token, a new refresh token is also generated and provided with your new access token. The old refresh token becomes immediately invalid.

Auto-update of refresh tokens

Link to this section

Kinde allows a small overlap period when both a previous and new refresh token is valid. This is to account for retries and bad network connections. You can set the lifetime of a refresh token in Kinde. It needs to be longer than the life of an access token.

Client-specific refresh token cookies

Link to this section

When multiple applications share the same custom domain, they normally share a single refresh_token cookie. That can cause one app’s refresh token to overwrite another’s—for example, signing in to App B may replace the refresh token that App A had set, breaking App A’s session.

To avoid this, Kinde supports client-specific refresh token cookies. When enabled for an application, the refresh token is stored in a cookie named with the application’s client ID prefix (for example, refresh_token_abc123), so each app keeps its own refresh token independently.

  • Where to enable: Settings > Applications > [your app] > Tokens > Refresh token cookies
  • Requirement: A custom domain must be configured; this feature is not available without one.
  • Default: The feature is disabled by default.
  • Cookie naming: Kinde uses the first 6 characters of the application’s client ID to build the cookie name (e.g. refresh_token_abc123).
  • Fallback: If a client-specific cookie is not found, Kinde falls back to the standard refresh_token cookie.

Refresh tokens when you are not using an SDK

Link to this section

You should store the refresh token you get with your initial /token request. Otherwise, your user will need to go through the sign in process again, to get a new access token.

Use the SDK getToken function to silently refresh tokens

Link to this section

If you’re using a front-end SDK like JavaScript or React, the getToken function stores an in-memory cache of the access token, which it returns by default. If the token is about to expire it will use a refresh token to get a new access token from Kinde silently in the background so additional network requests to Kinde are only made when absolutely necessary.

Token security recommendations

Link to this section

Token security can be approached in a number of ways. We recommend at least covering the basics of:

  • keeping the number of refresh tokens within a manageable limit to keep credentials safe and secure.
  • storing refresh tokens securely in the back-end of your application because they essentially allow a user to remain authenticated forever.
  • employing refresh token rotation and automatic reuse detection for added security.