Authentication
Tokens

Tokens

When an username/password, ID token or authorization code is exchanged for a set of Keel access and refresh tokens using the /api/token endpoint, it will always respond with the following data.

HTTP 200
{
  "access_token": "{{access_token}}",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "{{refresh_token}}",
  "identity_created": false
}

Read more about the token endpoint here.

What is an Access token?

The access token is a short-lived token used to access your Keel APIs. After authenticating, proceed to use the access token you have received to perform authenticated requests to your Keel APIs. This is done by including the access token (prefixed with Bearer) in the Authorization header of the request, as shown in the example below.

curl --request POST \
  --url 'http://localhost:8000/web/json/searchAuthors' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ...' \
  --data '{ "where": { "name": { "startsWith": "Bob" } } }'

The access token should be configured to expire quickly because it provides direct access to your application on Keel as a user. If it's stolen, it can be used to access your application as that user and their identity can be compromised.

What is a refresh token?

The refresh token, however, lives much longer and is used to obtain a new access token without involving the user in another round of authentication.

Access tokens can be refreshed using the standard token endpoint with the refresh_token grant.

curl --request POST \
  --url 'http://localhost:8000/auth/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=refresh_token \
  --data subject_token={{refresh_token}}

If the refresh token is still valid, then a new access token will be minted and returned.

HTTP 200
{
  "access_token": "{{keel_access_token}}",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "{{keel_id_token}}",
  "identity_created": false
}

Our default duration for a refresh token is 3 months, which typically means that a user could be "signed in" for 3 months if the client is able to remember this refresh token.

Configuring token expiry

Each token's lifespan is configurable via the keelconfig.yaml file.

Recommended Practices

In your applications, you should always store the refresh token securely and never expose it to the user. If you need to store it in a cookie, make sure it's an HTTP-only cookie that can't be accessed by JavaScript. The access token should ideally live in browser/client memory only and not be stored anywhere. Since the access token is returned to you with an expiry time, you can use that to determine when to request a new access token using the refresh token and silently refresh the access token in the background while your users are using your application. If they close the browser and come back later, then you can silently request a new access token using the refresh token before they begin using the application again.

Refresh Token Rotation

Refresh token rotation is a technique for getting new access tokens using refresh tokens that goes beyond silent authentication. Refresh tokens are typically longer-lived and can be used to request new access tokens after the shorter-lived access tokens expire. Refresh tokens are often used in native applications on mobile devices in conjunction with short-lived access tokens to provide seamless UX without having to issue long-lived access tokens.

With refresh token rotation enabled in Keel, every time an application exchanges a refresh token to get a new access token, a new refresh token is also returned. Therefore, you no longer have a long-lived refresh token that, if compromised, could provide illegitimate access to resources. As refresh tokens are continually exchanged and invalidated, the threat is reduced.

Keel does not yet support a full Proof Key of Code Exchange (PKCE) (opens in a new tab) flow, while this work is planned. By using one-time-only refresh tokens that rotate, you don't need a full PKCE flow because each token rotation inherently adds an extra layer of security, reducing the risk associated with token interception and replay attacks, which PKCE primarily aims to mitigate.

This setting is enabled by default in Keel. You can disable it in the keelconfig.yaml file though we don't recommend it.