Refresh Tokens
On this page
Issuing and Using Refresh Tokens
Refresh tokens allow the client to obtain more access tokens without needing the user to re-authenticate. The refresh tokens is a longer lived token that may have a lifetime up to many years.
Pre-requisites
This tutorial builds on the configuration setup described in the steps First Configuration and Configure an Authenticator under the menu Getting Started. If you have not gone through those steps yet, you can visit the guides by clicking on the links.
You may run this tutorial on a custom setup also, but keep in mind that names and URLs may be different, as well as the capabilities configured in the profiles.
You will also need a client capable of refresh. If you follow the code flow tutorial, you will have obtained a refresh token.
Overview
Token Endpoint
- The client sends the refresh token along with credentials to the token endpoint
- The server responds with new a new access token and a new refresh token
This is a POST request to the token endpoint. The client uses HTTP basic authentication to identify itself in this example; other mechanisms are also possible (e.g., sending the client ID and secret in the body, using the JWT assertion grant type, mutual TLS, etc.). The payload is URL encoded. The contents of which include at least grant_type
and refresh_token
. The grant_type
parameter should always have a value of refresh_token
in this flow and the value of the refresh_token
parameter should be the actual refresh token obtained by the client after some other flow, like the code flow, which included a refresh token.
Setup in Curity
No additional setup is needed from the previous steps.
Making Requests with the Client
With the default configuration from the initial setup, use the code flow to obtain an access token and a refresh token. Take the refresh token and form the following request:
POST /oauth/v2/oauth-token HTTP/1.1Host: localhostContent-Type: application/x-www-form-urlencodedgrant_type=refresh_token&client_id=www&client_secret=THE_SECRET&refresh_token=THE_REFRESH_TOKEN
The same request using cURL:
curl -X POST \https://localhost:8443/oauth/v2/oauth-token \-H 'Content-Type: application/x-www-form-urlencoded' \-d 'grant_type=refresh_token&client_id=www&client_secret=Secr3t!&refresh_token=THE_REFRESH_TOKEN'
The response will be either an success or error; both will be an object encoded as JSON. A successful result will produce a response like this:
{"access_token": "79ed4e85-954d-4044-9362-99ac9695d7e0","refresh_token": "ff8cfad8-9888-44c7-afb2-8c597cf96037","scope" : "","token_type": "bearer","expires_in": 300}
In such a case, the response will have access_token
, refresh_token
, scope
, token_type
, and expires_in
fields.1
Note how the refresh_token
in the response is not the same as the one that was sent. This is Curity's default behavior -- it creates a new refresh token with each redemption of an existing refresh token. This means that the client will have to store the refresh token from each response and use that in the next request. This is an extra security measure that is in place but can be relaxed.
Controlling Refresh Tokens
Reusing refresh tokens
To reuse the same refresh token, in the admin UI:
Visit the Profiles screen and click the Token Service. On the General page scroll down to Reuse Refresh Tokens
If you toggle this on, the refresh token presented in the request will be the same one that is echoed in the response. This will alleviate the client from having to update its stored refresh token and allow it to use the same one with each request.
Disabling Access Token Issuance
There are times when a client should not be issued a refresh token even if it performs a flow that allows for one. This is often done to manage the risk associated with a distrusted client. To disable the issuance of a refresh token in the admin UI, find the OAuth profile and client which should not be issued a refresh token. Then, toggle off the control labeled Refresh Token Time to Live
.
Changing Scope of Access Token on Refresh
One of the request parameters that can sent is scope
. This indicates to the OAuth server the scope of access that the refreshed token should have. If excluded, the scope will not change. If this parameter is included though, it should be a space-separated value, as is normal for indicating scope in OAuth. As an example, suppose the client performed the code flow and got an access token with the scope shown in the following listing:
{..."access_token": "aebc4798-9a2c-4c4a-a39f-c31eeb6409e6","refresh_token": "4dc21b27-b1ef-4e68-98b4-055d215fa5e2","scope": "read openid profile"}
With this refresh token, the client could refresh the access token with lesser scope by making a request like this:
POST /token HTTP/1.1Host: localhost:8443Content-Type: application/x-www-form-urlencodedAuthorization: basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==grant_type=refresh_token&refresh_token=4dc21b27-b1ef-4e68-98b4-055d215fa5e2&scope=read+profile
The response shows that the new, refreshed access token has less scope than the original:
{..."access_token": "2a44b422-f2c2-4fd8-bfcb-1ea6140cea87","refresh_token": "daa38700-ba96-4ef1-8b30-5cb3527aae19","scope": "read profile"}
The scope was originally read openid profile
and after refresh the access was reduced to read profile
(i.e., the access_token
now only has read profile
scope and any new tokens obtained using the refresh token daa38700-ba96-4ef1-8b30-5cb3527aae19
will have the same, reduced scope). Note that increasing the scope of access cannot be done in this way unless first reduced and increased back to the original scope.
Changing scope
It is only possible to remove the scopes during refresh, not add new scopes.
Footnotes
-
Some of these are recommended or optional in the OAuth specification, but Curity always includes them. ↩
Join our Newsletter
Get the latest on identity management, API Security and authentication straight to your inbox.
Start Free Trial
Try the Curity Identity Server for Free. Get up and running in 10 minutes.
Start Free Trial