Using OAuth 2.0 with offline access

// By Dropbox Platform Team • Oct 19, 2022

The Dropbox API now returns short-lived access tokens, and optionally returns refresh tokens. This post will cover how and when to retrieve and use refresh tokens. We suggest checking out the OAuth Guide for background first, if you haven’t already.

We recommend using one of the official Dropbox SDKs whenever possible, as they’ll handle most of the work of using the OAuth app authorization flow for you. If you’re using one of the official Dropbox SDKs, refer to its documentation for information on how to use it to process the authorization flow.

Otherwise, read on for information on how to implement the OAuth app authorization flow using the Dropbox OAuth authorization endpoints directly.  

Choosing online or offline access

If your app only needs access for a short period of time, or only needs to operate when the user is present, then you only need to use “online” access.  For example, a web app that only interacts with a user’s Dropbox files when the user is actively interacting with the app would only need “online” access.

In that case, the app receives a short-lived access token when the user processes the authorization flow. If the app needs further access after the short-lived access token expires, the app can send the user through the app authorization flow again. If a user has previously authorized an app, re-authorization is typically a single click or automatically redirected.

Here’s an example of what the “online” flow looks like:

Step 1: Begin authorization

Construct the /oauth2/authorize URL like the following and direct the user there:
https://www.dropbox.com/oauth2/authorize?client_id=<APP KEY>&response_type=code&token_access_type=online&state=<STATE>&redirect_uri=<REDIRECT URI>

After the user has authorized your app, they’ll be sent to your redirect URI, with a few query parameters:
<REDIRECT URI>?code=<AUTHORIZATION CODE>&state=<STATE>

Step 2: Obtain an access token

Exchange the resulting authorization code for an access token, by calling the /oauth2/token endpoint. Here’s an example of calling this endpoint using curl:

curl https://api.dropbox.com/oauth2/token \
    -d code=<AUTHORIZATION CODE> \
    -d grant_type=authorization_code \
    -d client_id=<APP KEY> \
    -d client_secret=<APP SECRET> \
    -d redirect_uri=<REDIRECT URI>

The response will look like this:
{"access_token": "<ACCESS TOKEN>", "expires_in": "<EXPIRATION>", "token_type": "bearer", "scope": "<SCOPES>", "account_id": "<ACCOUNT ID>", "uid": "<USER ID>"}


Step 3: Call the API

Use the resulting access token to call the API, with the access token as a “Bearer” token in the “Authorization” header, like this:

curl -X POST https://api.dropboxapi.com/2/users/get_current_account \
    --header "Authorization: Bearer <ACCESS TOKEN>"

If your app needs to be able to operate long-term without the user present, continue reading to see how to use “offline” access instead. For example, an app that operates in the background to receive status updates or automatically perform operations on a user’s Dropbox account over long periods of time even when the user isn’t actively interacting with the app would need “offline” access.

Using offline access

Here’s an example of what the “offline” flow looks like:

Step 1: Begin authorization

Construct the /oauth2/authorize URL like the following, with token_access_type=offline , and direct the user there:
https://www.dropbox.com/oauth2/authorize?client_id=<APP KEY>&response_type=code&token_access_type=offline&state=<STATE>&redirect_uri=<REDIRECT URI>

After the user has authorized your app, they’ll be sent to your redirect URI, with a few query parameters:
<REDIRECT URI>?code=<AUTHORIZATION CODE>&state=<STATE>

Step 2: Obtain an access token and refresh token

Exchange the resulting authorization code for an access token and refresh token, by calling the /oauth2/token endpoint. Here’s an example of calling this endpoint using curl:

curl https://api.dropbox.com/oauth2/token \
    -d code=<AUTHORIZATION CODE> \
    -d grant_type=authorization_code \
    -d client_id=<APP KEY> \
    -d client_secret=<APP SECRET> \
    -d redirect_uri=<REDIRECT URI>

The response will look like this:
{"access_token": "<ACCESS TOKEN>", "expires_in": "<EXPIRATION>", "token_type": "bearer", "scope": "<SCOPES>", "refresh_token": "<REFRESH TOKEN>", "account_id": "<ACCOUNT ID>", "uid": "<USER ID>"}

Step 3: Store the returned refresh token

The refresh token can be repeatedly re-used and doesn't expire automatically (though it can be revoked on demand). Securely store the refresh token for later use.

Step 4. Call the API

Use the resulting access token to call the API, with the access token as a “Bearer” token in the “Authorization” header, like this:

curl -X POST https://api.dropboxapi.com/2/users/get_current_account \
    --header "Authorization: Bearer <ACCESS TOKEN>"

The short-lived access token can be used until it expires (or is revoked).

Step 5: Retrieve a new short-lived access token

Once the current short-lived access token expires, call the /oauth2/token endpoint with the refresh token to get a new short-lived access token, like this: 

curl https://api.dropbox.com/oauth2/token \
   -d refresh_token=<REFRESH TOKEN> \
   -d grant_type=refresh_token \
   -d client_id=<APP KEY> \
   -d client_secret=<APP SECRET>

The response will look like this:
{"access_token": "<NEW ACCESS TOKEN>", "expires_in": "<EXPIRATION>", "token_type": "bearer"}

Repeat steps 4 and 5 programmatically as needed.

Tips and pointers

  • Dropbox supports both response_type=code and response_type=token. However, response_type=token is considered legacy and no longer recommended. The use of response_type=code is necessary for offline access; response_type=token does not support offline access.
  • Server-side apps should use response_type=code and client-side apps should use response_type=code with PKCE. Either can use offline access.
  • When using response_type=code, a redirect URI is optional, regardless of using offline access or not (or using PKCE or not).
  • While the use of a redirect URI is optional, apps must be consistent in specifying or not specifying it during a given authorization flow. If the app sets redirect_uri when configuring the /oauth2/authorize URL, it must also set the same redirect_uri when calling /oauth2/token with grant_type=authorization_code to exchange the resulting authorization code. If the app does not set redirect_uri on the /oauth2/authorize URL, it must not set redirect_uri when calling /oauth2/token with grant_type=authorization_code to exchange the resulting authorization code. In either case, setting redirect_uri is not expected when calling /oauth2/token with grant_type=refresh_token.
  • The terms “app key”, “app secret”, "authorization code”, “access token”, and “refresh token” describe distinct objects which are not interchangeable.
  • Authorization codes can only be used once each and expire after a very short period of time. New access tokens are short-lived, meaning they expire after a short period of time. Refresh tokens are long-lived and do not expire automatically. Access tokens and refresh tokens can be revoked on demand though, by the app or user. For example, users can unlink apps from their account using the Connected apps page, and team admins can unlink apps from their teams using the Team apps page. Apps can revoke an access token (and corresponding refresh token, if any) using the /2/auth/token/revoke endpoint.
  • Refresh tokens are app- and user-specific. Developers with multiple app registrations will need to keep track of which app each refresh token is for. Attempting to use the wrong app key/secret when using a refresh token will fail.

// Copy link