Refresh Token

Web Applications (Server)Single Page ApplicationsMobile Applications
SupportedDiscouragedSupported

The Refresh Token grant type is used by clients to exchange a refresh token for an access token when the access token has expired. This allows clients to continue to have a valid access token without further interaction with the user. The user does not need to be present at the time of the new access token request. This allows you to request a new access token without prompting the user to authenticate again.

A Refresh Token can be optained by using the Authorization Code Flow with PKCE or the Authorization Code Flow. To receive a Refresh Token, you must request the offline_access scope.

The Refresh Token grant type is available for all types of applications. However, it is discouraged to use this grant type for single page applications. Instead, you should use the Authorization Code Flow with PKCE for single page applications and refresh the access token using a hidden iframe. This is called Silent Authentication and is the recommended way to refresh access tokens for single page applications.

Handle refresh tokens with care! Refresh tokens are long-lived and for public clients (such as single page applications and mobile applications) they can be used to obtain a new access token without further authentication of the client.

Refreshing an access token

To request an access token, make a POST request to the token endpoint with the following parameters:

Body ParameterDescription
grant_typerequired Must be set to refresh_token.
refresh_tokenrequired The refresh token you want to use to obtain a new access token.
client_idrequired for public clients The client ID of your application. Confidential clients have to authenticate themselves by including their client ID and secret in the Authorization header (see below).

In addition to the body parameters, you must also send the following HTTP headers:

HeaderValue
Content-Typerequired Set to application/x-www-form-urlencoded. This will most likely be set automatically by your HTTP client.
Authorizationrequired for confidential clients Set to Basic <base64(client_id:client_secret)>. Never include the client secret in a request from a public client like a single page application or a mobile application.
POST /oauth2/token HTTP/1.1
Host: auth.eduplaces.io
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=ory_rt_M_L5nZqFRRNut9HyXM1pcnw5KnYRC5bxvTwUwmpYKf8.gm4rtGzGrpk_1Qnv4THrfPt0HFCtDq1v9EXVsSBQEOc
POST /oauth2/token HTTP/1.1
Host: auth.eduplaces.io
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=ory_rt_M_L5nZqFRRNut9HyXM1pcnw5KnYRC5bxvTwUwmpYKf8.gm4rtGzGrpk_1Qnv4THrfPt0HFCtDq1v9EXVsSBQEOc
&client_id=YOUR_CLIENT_ID

Successful Response

If the request was successful, we will respond with a 200 OK status code and a JSON body containing the following parameters:

KeyValue
access_tokenA new access token your application can use to make API requests on behalf of the user.
token_typeThe type of the access token. Always set to bearer. Note: It should be Bearer but unfortunately, our OAuth 2.0 server returns it in lowercase. Make sure to be able to handle both as this might change.
expires_inThe remaining lifetime of the access token in seconds.
scopeThe scopes the user authorized your application to access.
id_tokenA new ID token your application can use to identify the user. Requires the openid scope to have been requested.
refresh_tokenA new refresh token your application can use. The old refresh token will be invalidated.
HTTP/1.1 200
Content-Type: application/json
{
  "access_token": "ory_at_FYfL9jJTZO15HI6EQCO-0uZg8W_KMTJHunpmXTLp8lg.uGGOCQEGOlunY9mdsWrZA3uGT03JYWdTTj8iar5MIvs",
  "token_type": "bearer"
  "expires_in": 3599,
  "scope": "openid offline_access",
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg4MzIwZjlmLTBhZjQtNDFjMC1iMzAwLTczMGFmZmRjYjVhMCIsInR5cCI6IkpXVCJ9.eyJhdF9oYXNoIjoiSXdDQmFTc0tEZTI3R1JQQS12NG1JUSIsImF1ZCI6WyJkYzYxZjk5ZC1hZGZlLTQ1OGEtODZiZi0zYTMxNmYyYTc4OWMiXSwiYXV0aF90aW1lIjoxNjkzMzAyNzAwLCJleHAiOjE2OTMzMDYzMTQsImlhdCI6MTY5MzMwMjcxNCwiaXNzIjoiaHR0cHM6Ly9zaWxseS1lbGlvbi13ZWN4dHhtY2c1LnByb2plY3RzLm9yeWFwaXMuY29tIiwianRpIjoiMWMyZDUzMmQtMWUzNi00ZmFiLTkwMjgtMjc1MDcwM2FiMTczIiwicmF0IjoxNjkzMzAyNjkzLCJzaWQiOiIzM2RiOWU3Ny1iNGRiLTQ2M2YtOTc4My1kZmY3NmU5NDQxNDciLCJzdWIiOiI3NGQ3YjYyNS01YzA4LTRjYmItOWQwZC1lZWQxZTgzNjQ2YzMifQ.EPWFwVioQZYxmaZVy_3drs2-3jr2DIszkrI9TZpz6dJluDPQ6F6M2Kq7q-zKthnHM7rWvb-bfBJh6Olo1UF6TG0F93WXQIdI7HgIhtQH5a9Cfwbv-h8GQieVc2cQmxzqyiqIxa4e0Z3VoLvsqCE76JVfdo0tmI1SfnauYx3BSxlu6LeVzYWWclQU9fJg1pfurvw6hzVdtJTjdyUvh45bNMAb_QWFDMhkF36yMX7CqzVd8eHX5jnMuk2e1WDLKS6qZxJ3oGux_VDqKg9Qu0x8rb1e4WPAJJ35n2AcqmsO0ex14yxUfhCZDRM31MMC11MfIH1wiTrZKTF9EqZ0yys_vZoQ8DBoHvnDA7cjYZ-0FXO1cirDflzo0jMxihwFaES-_E1pAr4vkiInIigSc4YmTMfOyTttlT-U31zlOh5tiaLhzLO9ImmyLenj9CGCi_GYPqoLf0JTbeSKA9J7DkrO-ed_xMYn-fHt1oqukJmEVg7KJz3Ey5G4h_mL8wMR2Vj-wopFC01RIYpo3a-KjEPdFUktyNB678-iY-n0JuEdDLJ743RfWsR4zQOKpfy3XMK3jIfcE_sAg5Yz3rgUWtVdZ_NSy1rvOCzbJ3-PoxzGNS1qbp6Ma0aK-FU_ZHyUnLRoRa5O6q1vwLe-DX5nfsfIX9S2FapS6nTC_hPITyq9YRI",
  "refresh_token": "ory_rt_XfPjrVDSXtVXK-WA9rbjAp5g7ZkAG-hXR76nN38VIAM.disRRBbHn71r2JfpLKuiq3F5EyJPKg7dmWQZdsFm-rw",
}

Error Response

If the request was not successful, we will respond with an error. The authorization server will respond with a 400 Bad Request status code and a JSON body containing the following parameters:

KeyValue
errorThe error code.
error_descriptionA human-readable text providing additional information.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
  "error": "invalid_request",
  "error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
}

Refer to the OAuth 2.0 specification for a list of error codes. The error_description is optional and might not be included in the response. We will try to include it if possible, but you should not rely on its presence.