What are refresh tokens?
Refresh tokens are means to grant an application access to a protected resource when the access token expires.
- Refresh tokens contain the information required to obtain a new access_token or Id Token
- They are subjected to strict storage requirements to ensure that they are not leaked
- Since they do not expires, you should consider revoking them if security issues arise
- You can get a refresh token if you are using the following flows:
- AuthorizationCodeFlow
- AuthorizationCodeFlow with PKCE (proof key for code exchange)
Many authorization servers implement the refresh token request mechanism defined in the OpenID Connect specification. In this case, an application must include the offline_access
scope when initiating a request for an authorization code.
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded client_id=s6BhdRkqt3 &client_secret=some_secret12345 &grant_type=refresh_token &refresh_token=8xLOxBtZp8 &scope=openid%20profile
A refresh response may look like:
HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "access_token": "TlBN45jURg", "token_type": "Bearer", "refresh_token": "9yNOxJtZa5", "expires_in": 3600 }
The following example shows how to use HTTPClient to refresh the access token using a refresh token:
- I defined the token response :
In the following method I am using an authorisation flow, where after the user signed in succesfully, the identity server redirects the page to this method and passes the authorization_code.
When we get the code we can exchange it for an access token:
If you remember from Grant Types Article the grant_type targets the token_endpoint and when grant_type=authorization_code using the authorization code received from the authorization endpoint, the token endpoint will exchange it with an access token.
Now we can follow the same approach, and instead of setting the grant to be authorization, we will make it refresh_token. This tells the server to take the refresh token and change if for an access token. (Provided that the refresh token has not expired)
We can do the same thing, alot easier if we use the IdentityModel helpers:
You have to add the package IdentityModel:
To be able to use the IdentityModel helper we first need to initialize the discoveryDocument model. The discovery document takes as an argument the identity server url and it will investigate the available endpoints from the .well-known link.
If our IdentityServer has the URL https://demo.identityserver.io then pass only this url as the argument and it will fill out the rest of the route .
More about discovery document here
We then create the request to exchange the authorization_code for the access_code :
And we can now exchange the refresh_token we received in our original code to get a new access_token: