OAuth 2.0

Apps connect to Box using OAuth 2.0, the standard used by most APIs for authenticating and authorizing users. The following walkthrough will show you how to authenticate a user. There are also Box SDKs that include implementations of the OAuth2 grants used by Box, or client libraries available in a number of languages that you might find useful.

If you just need OAuth tokens for your own account for testing, we recommend you use the developer token available inside your application configuration page, or check out this Heroku app or it’s github repo for generating tokens.

Customer using Active Directory, LDAP, Siteminder or ‘SSO’?

Is your customer asking that you make your application work with an Identity Provider or Single Signon system that sounds like alphabet soup? Googled it and it’s for SSO on a mainframe, or something from the dark ages of computing? No problem: Box has you covered! If you authenticate your application via Box’s OAuth 2.0, your application with automatically let the customer sign-on with their company credentials, just like they do with every other Box application. This also applies to popular commercial services like Okta, One Login, and Ping.

Initial Setup

Testing: When your app is set to ‘Development’ mode, you can set your redirect_uri to the following local http endpoints: http://127.0.0.1, http://0.0.0.0, and http://localhost.

Before you can start using OAuth2 with your application, you’ll need to tell Box a bit of information about your application

  1. Register your application here.
  2. Set your redirect url
  3. Select your scope
  4. Make a note of both your client_id and client_secret.
Redirect URI: The redirect URI is the URL within your application that will receive the OAuth2 credentials.
Scopes: Select the “Read and write all files and folders” scope if your application needs to perform operations on files and folders, such as creating, downloading, editing, and deleting files and folders. Select the “Manage an enterprise” scope if your application needs to perform enterprise management, such as creating, editing, and deleting users and groups, viewing admin logs, and creating collaborations for groups.

The First Leg

First, direct your user to https://app.box.com/api/oauth2/authorize through either a POST or a GET request with the following parameters:

Parameters: For POST, include the parameters in the POST body. For GET, include them as query parameters. In both cases, URL encode the parameters.
response_type
required
Whether the endpoint returns an authorization code. For web applications, a value of code should be used.
client_id
required
The client_id you obtained in the Initial Setup.
redirect_uri An HTTPS URI or custom URL scheme where the response will be redirected. Optional if the redirect URI is registered with Box already.
state An arbitrary string of your choosing that will be included in the response to your application. Box recommends that you use an anti-forgery state token to prevent CSRF attacks to your users

A sample GET request could therefore look like:

GET https://app.box.com/api/oauth2/authorize?response_type=code&client_id=MY_CLIENT_ID&state=security_token%3DKnhMJatFipTAnM0nHlZA

The User Experience

At this point, you’ve forwarded the user to Box’s authorization page:

Box login authorization
Your application doesn’t need to do anything here; Box handles authenticating the user and giving them feedback on any errors:

Box login error
After successfully entering their credentials, the user will be taken to a consent page, to authorize your application to access their account.

Box authorization success

After clicking either Grant or Deny, you’ll receive a response from Box, as outlined in the next section.

Handling the Response from Box

If the user clicked Grant in the previous screen, Box will redirect to the URI you specified earlier with a code parameter and a state parameter, if you included one. For example, if your redirect URI was https://www.sean.com/rose, Box would redirect to:

https://www.sean.com/rose?code=123456abcdef&state=YOUR_CSRF_PREVENTION_CODE
Authorization Code: The authorization code is only valid for 30 seconds.

However, if the user clicked Deny, you will receive a request with an error and error_description parameter, such as:

GET https://www.sean.com/rose?error=access_denied&error_description=The+user+denied+access+to+your+application

Assuming you got a Grant response, At this point you should verify that the CSRF security_token you received back is the same one you gave the user back in the First Leg. This will help make sure that it really is your user, and not a malicious script. If the code doesn’t match you should reject with a 401 code.

The following conditions may also cause an error:

invalid_request The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
unsupported_response_type The authorization server does not support obtaining an authorization code using this method.
Check the value of the code param in your request.
access_denied The resource owner or authorization server denied the request.
server_error The device the user is trying to log in from is not authorized to access the user’s account.
temporarily_unavailable Your device is being rate limited, you need to either decrease your rate of authorization requests, or wait a bit.
Error Handling: The error parameter will always be present, while the human readable error_description may not. Your code should rely on error.

Getting the Access Token

Once your application has completed the above section and gotten an authorization code, it’ll now need to exchange the authorization code for an access token from Box.

Access Token: The access token is what’s needed to sign your API requests to Box. You’re almost done!

To get the access_token, you’ll need to make a POST request to https://app.box.com/api/oauth2/token with the following parameters:

grant_type
required
Must be authorization_code
code
required
The authorization code you retrieved previously
client_id
required
client_id gotten from Box in Initial Setup
client_secret
required
client_secret gotten from Box in Initial Setup
redirect_uri Required only if a redirect URI is not configured at box.com/developers/services
Request: The requests must be over HTTPS and the parameters must be URL encoded.

An example request in cURL looks like:

curl https://app.box.com/api/oauth2/token \
-d 'grant_type=authorization_code&code={your_code}&client_id={your_client_id}&client_secret={your_client_secret}' \
-X POST

If everything goes right and the request is successful, you’ll receive a 200 response containing a JSON body like this:

{
    "access_token": "T9cE5asGnuyYCCqIZFoWjFHvNbvVqHjl",
    "expires_in": 3600,
    "restricted_to": [],
    "token_type": "bearer",
    "refresh_token": "J7rxTiWOHMoSC1isKZKBZWizoRXjkQzig5C6jFgCVJ9bUnsUfGMinKBDLZWP9BgR"
}

However, if the response is not successful, you’ll receive an error response, such as this:

{
    "error": "invalid_grant",
    "error_description": "Invalid user credentials"
}

Box supports the full set of error codes in the OAuth 2.0 spec:

The last four (redirect_uri_mismatch,, internal_server_error, insecure_redirect_uri, invalid_redirect_uri) are not returned to the application. Instead, they are shown to the end user in a Box-generated error page, like this:Using the Access and Refresh TokensThe access_token is the actual string needed to make API requests. Each access_token is valid for 1 hour. In order to get a new, valid token, you can use the accompanying refresh_token. Each refresh_token is valid for one use in 60 days. Every time you get a new access_token by using a refresh_token, we reset your timer for the 60 day period and hand you a new refresh_token. This means that as long as your users use your application once every 60 days, their login is valid forever. To use the refresh_token to get a new access_token, make a POST request to https://app.box.com/api/oauth2/token with the following, URL encoded parameters:A sample cURL request would look like:

curl https://app.box.com/api/oauth2/token \ -d 'grant_type=refresh_token&refresh_token={valid refresh token}&client_id={your_client_id}&client_secret={your_client_secret}' \ -X POST
If the request is successful, you’ll see a response like this:
{ "access_token": "T9cE5asGnuyYCCqIZFoWjFHvNbvVqHjl", "expires_in": 3600, "restricted_to": [], "token_type": "bearer", "refresh_token": "J7rxTiWOHMoSC1isKZKBZWizoRXjkQzig5C6jFgCVJ9bUnsUfGMinKBDLZWP9BgR" }
In this response, you’ll receive both a new access_token and refresh_token. The refresh_token you used to make this request is no longer valid. If an error occurs, you’ll receive a 400 Bad Request, along with of the errors listed in the Getting the Access Token section.Using Your Access Token with API V2Once you have a valid access_token, you can use it to make requests to API V2. All you need to do is set it in the Authorization header like this:
Authorization: Bearer {a valid access token}
If you were, for example, trying to get a user’s folder in V2, a full cURL request would look like this:
curl https://www.box.com/api/2.0/folders/0 \ -H "Authorization: Bearer T9cE5asGnuyYCCqIZFoWjFHvNbvVqHjl"
If the protected resource request does not include authentication credentials or does not contain an access token that enabled access to the protected resource, Box sets the WWW-Authenticate response header field. If the protected resource request included an access token and failed authentication, Box sets the “error” attribute to provide the client with the reason why the access request was declined. Box also includes the error-description attribute to provide developers a human-readable explanation that is not meant to be displayed to end users. The following codes can be returned as a value for the WWW-Authenticate header.Destroying TokensIf you would like to get rid of tokens for a user (e.g. if you have a ‘logout of Box’ button in your app), make a POST request to https://www.box.com/api/oauth2/revoke with the following URL encoded parameters:

For example, to destroy access_token 1234 and its associated refresh_token, you would issue this request:

curl https://www.box.com/api/oauth2/revoke \ -d 'client_id=CLIENT_ID&client_secret=CLIENT_SECRET&token=1234' \ -X POST
Success: Upon success, both the access_token and refresh_token will be destroyed.

Error Error Description(s) What happened
invalid_request Invalid grant_type parameter or parameter missing.
Missing parameter. “code” is required
Invalid refresh token
Your request did not contain a grant type.
The code parameter is missing for the authorization code grant type.
The refresh token has expired or is malformed.
unauthorized_client The grant type is unauthorized for this client_id Your application is not authorized to use this grant type
invalid_grant Auth code doesn’t exist or is invalid for the client.
The authorization code has expired
Verify the authorization code is set correctly in your request.
Your application likely needs to get a new authorization code.
invalid_client The client credentials are invalid Verify that the client ID and secret are correct.
redirect_uri_mismatch The redirect URI is missing or do not match Either a redirect URI is not configured for your application or the URI in the request does not match the configured URI.
insecure_redirect_uri The URI is either not a custom protocol or not HTTPS. Your application sent a bad redirect URI i.e. HTTP instead of HTTPS
invalid_redirect_uri The redirect_uri scheme is invalid per the RFC. A common problem is the first character being something besides a letter. Your application sent an invalid URI.
HTTP Status Error Code What happened
400 invalid_request The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed
401 invalid_token The access token provided is expired, revoked, malformed or invalid for other reasons. The client may request a new access token and retry the protected resource request
403 insufficient_scope The request requires higher privileges than provided by the access token