OAuth 2.0 for TV and Limited-Input Device Applications

Important note: This OAuth 2.0 flow supports a limited set of scopes.

This document explains how to implement OAuth 2.0 authorization to access Google APIs via applications running on devices like TVs, game consoles, and printers. More specifically, this flow is designed for devices that either do not have access to a browser or have limited input capabilities.

OAuth 2.0 allows users to share specific data with an application while keeping their usernames, passwords, and other information private. For example, a TV application could use OAuth 2.0 to obtain permission to add items to a user's calendar.

Since the applications that use this flow are distributed to individual devices, it is assumed that the apps cannot keep secrets. They can access Google APIs while the user is present at the app or when the app is running in the background.

Alternatives

If you are writing an app for a platform like Android, iOS, macOS, Linux, or Windows (including the Universal Windows Platform), that has access to the browser and full input capabilities, use the OAuth 2.0 flow for mobile and desktop applications. (You should use that flow even if your app is a command-line tool without a graphical interface.)

Prerequisites

Enable APIs for your project

Any application that calls Google APIs needs to enable those APIs in the API Console. To enable APIs for your project:

  1. Open the Library page in the API Console.
  2. Select the project associated with your application. Create a project if you do not have one already.
  3. Use the Library page to find each API that your application will use. Click on each API and enable it for your project.

Create authorization credentials

Any application that uses OAuth 2.0 to access Google APIs must have authorization credentials that identify the application to Google's OAuth 2.0 server. The following steps explain how to create credentials for your project. Your applications can then use the credentials to access APIs that you have enabled for that project.

  1. Open the Credentials page in the API Console.
  2. Click Create credentials > OAuth client ID.
  3. Complete the form. Set the application type to PlayStation 4 or Other, whichever is appropriate.

Identify access scopes

Scopes enable your application to only request access to the resources that it needs while also enabling users to control the amount of access that they grant to your application. Thus, there may be an inverse relationship between the number of scopes requested and the likelihood of obtaining user consent.

Before you start implementing OAuth 2.0 authorization, we recommend that you identify the scopes that your app will need permission to access.

The OAuth 2.0 API Scopes document contains a full list of scopes that you might use to access Google APIs.

Note: Incremental authorization is not supported for installed apps or devices.

Obtaining OAuth 2.0 access tokens

Even though your application runs on a device with limited input capabilities, users must have separate access to a device with richer input capabilities to complete this authorization flow. The flow has the following steps:

  1. Your application sends a request to Google's authorization server that identifies the scopes that your application will request permission to access.
  2. The server responds with several pieces of information used in subsequent steps, such as a device code and a user code.
  3. You display information that the user can enter on a separate device to authorize your app.
  4. Your application starts polling Google's authorization server to determine whether the user has authorized your app.
  5. The user switches to a device with richer input capabilities, launches a web browser, navigates to the URL displayed in step 3 and enters a code that is also displayed in step 3. The user can then grant (or deny) access to your application.
  6. The next response to your polling request contains the tokens your app needs to authorize requests on the user's behalf. (If the user refused access to your application, the response does not contain tokens.)

The image below illustrates this process:

The user logs in on a separate device that has a browser.

The following sections explain these steps in detail. Given the range of capabilities and runtime environments that devices may have, the examples shown in this document use the curl command line utility. These examples should be easy to port to various languages and runtimes.

Step 1: Request device and user codes

In this step, your device sends an HTTP POST request to Google's authorization server, at https://accounts.google.com/o/oauth2/device/code, that identifies your application as well as the access scopes that your application wants to access on the user's behalf. Include the following HTTP request parameters:

Parameters
client_id Required. The client ID for your application. You can find this value in the API Console.
scope Required. A space-delimited list of scopes that identify the resources that your application could access on the user's behalf. These values inform the consent screen that Google displays to the user.

Scopes enable your application to only request access to the resources that it needs while also enabling users to control the amount of access that they grant to your application. Thus, there is an inverse relationship between the number of scopes requested and the likelihood of obtaining user consent.

The OAuth 2.0 API Scopes document provides a full list of scopes that you might use to access Google APIs.

Examples

The following snippet shows a sample request:

POST /o/oauth2/device/code HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&
scope=email%20profile

This example shows a curl command to send the same request:

curl -d "client_id=client_id&scope=email%20profile" \
     https://accounts.google.com/o/oauth2/device/code

Step 2: Handle the authorization server response

The authorization server returns a JSON object to your device. The response contains the following properties:

Properties
device_code A value that Google uniquely assigns to identify the device that runs the app requesting authorization. The user will be authorizing that device from another device with richer input capabilities. For example, a user might use a laptop or mobile phone to authorize an app running on a TV. In this case, the device_code identifies the TV.

This code lets the device running the app securely determine whether the user has granted or denied access.
user_code A case-sensitive value that identifies to Google the scopes that the application is requesting access to. Your user interface will instruct the user to enter this value on a separate device with richer input capabilities. Google then uses the value to display the correct set of scopes when prompting the user to grant access to your application.
verification_url A URL that the user must navigate to, on a separate device, to enter the user_code and grant or deny access to your application. Your user interface will also display this value.
expires_in The length of time, in seconds, that the device_code and user_code are valid. If, in that time, the user doesn't complete the authorization flow and your device doesn't also poll to retrieve information about the user's decision, you might need to restart this process from step 1.
interval The length of time, in seconds, that your device should wait between polling requests. For example, if the value is 5, your device should send a polling request to Google's authorization server every five seconds. See step 3 for more details.

The following snippet shows a sample response:

{
  "device_code" : "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",
  "user_code" : "GQVQ-JKEC",
  "verification_url" : "https://www.google.com/device",
  "expires_in" : 1800,
  "interval" : 5
}

Step 3: Display the user code

Display the verification_url and user_code obtained in step 2 to the user. Both values can contain any printable character from the US-ASCII character set. The content that you display to the user should instruct the user to navigate to the verification_url on a separate device and enter the user_code.

Design your user interface (UI) with the following rules in mind:

  • user_code
    • The user_code must be displayed in a field that can handle 15 'W' size characters. In other words, if you can display the code WWWWWWWWWWWWWWW correctly, your UI is valid, and we recommend using that string value when testing the way the user_code displays in your UI.
    • The user_code is case-sensitive and should not be modified in any way, such as changing the case or inserting other formatting characters.
  • verification_url
    • The space where you display the verification_url must be wide enough to handle a URL string that is 40 characters long.
    • You should not modify the verification_url in any way, except to optionally remove the scheme for display. If you do plan to strip off the scheme (e.g. https://) from the URL for display reasons, be sure your app can handle both http and https variants.

Both of these values are subject to change, and you should not hardcode either value in your code. Similarly, you should not modify the values in any way other than optionally removing the scheme from the verification_url.

Step 4: Poll Google's authorization server

Since the user will be using a separate device to navigate to the verification_url and grant (or deny) access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll Google's authorization server to determine when the user has responded to the request.

The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the device_code and user_code obtained in step 2 have expired. The interval returned in step 2 specifies the amount of time, in seconds, to wait between requests.

The URL of the endpoint to poll is https://www.googleapis.com/oauth2/v4/token. The polling request contains the following parameters:

Parameters
client_id Your project's client ID. This value is available in the API Console.
client_secret Your project's client secret. This value is available in the API Console.
code The device_code that the authorization server returned in step 2.
grant_type Set this value to http://oauth.net/grant_type/device/1.0.

Examples

The following snippet shows a sample request:

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&
client_secret=client_secret&
code=device_code&
grant_type=http://oauth.net/grant_type/device/1.0

This example shows a curl command to send the same request:

curl -d "client_id=<client_id>&client_secret=<client_secret>& \
         code=<device_code>&grant_type=http://oauth.net/grant_type/device/1.0" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         https://www.googleapis.com/oauth2/v4/token

Step 5: User responds to access request

Note: Your application does not need to do anything at this stage aside from polling the authorization server as described in the previous step.

The following image shows a page similar to what users see when they navigate to the verification_url that you displayed in step 3:

After entering the user_code and, if not already logged-in, logging in to Google, the user sees a consent screen like the one shown below:

Step 6: Handle responses to polling requests

Google's authorization server responds to each polling request with one of the following responses:

  • Access granted

    If the user granted access to the device (by clicking Allow on the consent screen), then the response contains an access token and a refresh token. The tokens enable your device to access Google APIs on the user's behalf. (The scope parameter in step 1 determines which APIs the device can access.)

    In this case, the API response contains the following fields:

    Fields
    access_token The token that your application sends to authorize a Google API request.
    refresh_token A token that you can use to obtain a new access token. Refresh tokens are valid until the user revokes access. Note that refresh tokens are always returned for devices.
    expires_in The remaining lifetime of the access token in seconds.
    token_type The type of token returned. At this time, this field's value is always set to Bearer.

    The following snippet shows a sample response:

    {
      "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in":3920,
      "token_type":"Bearer",
      "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
    }

    Access tokens have a limited lifetime. If your application needs access to an API over a long period of time, it can use the refresh token to obtain a new access token. If your application needs this type of access, then it should store the refresh token for later use.

  • Access denied

    If the user refuses to grant access to the device, then the server response has a 403 HTTP response code (Forbidden). The response contains the following error:

    {
     "error": "access_denied",
     "error_description": "Forbidden"
    }
    
  • Authorization pending

    If the user has not yet completed the authorization flow, then the server returns a 400 HTTP response code (Bad Request). The response contains the following error:

    {
      "error" : "authorization_pending",
      "error_description": "Bad Request"
    }
    
  • Polling too frequently

    If the device sends polling requests too frequently, then the server returns a 429 HTTP response code (unknown). The response contains the following error:

    {
     "error": "slow_down",
     "error_description": "Rate Limit Exceeded"
    }
    
  • Other errors

    The authorization server also returns errors if the polling request is missing any required parameters or has an incorrect parameter value. These requests usually have a 400 (Bad Request) or 401 (Unauthorized) response code. Those errors include:

    • invalid_client (401) - The OAuth client was not found. For example, this error occurs if the client_id parameter value is invalid.
    • invalid_grant (400) - The code parameter value is invalid.
    • invalid_request (400) - The request is missing a parameter.
    • unsupported_grant_type (400) - The grant_type parameter value is invalid.

Calling Google APIs

After your application obtains an access token, you can use the token to make calls to a Google API on behalf of a given user account or service account. To do this, include the access token in a request to the API by including either an access_token query parameter or an Authorization: Bearer HTTP header. When possible, the HTTP header is preferable, because query strings tend to be visible in server logs. In most cases you can use a client library to set up your calls to Google APIs (for example, when calling the Drive API).

You can try out all the Google APIs and view their scopes at the OAuth 2.0 Playground.

HTTP GET examples

A call to the drive.files endpoint (the Drive API) using the Authorization: Bearer HTTP header might look like the following. Note that you need to specify your own access token:

GET /drive/v2/files HTTP/1.1
Authorization: Bearer <access_token>
Host: www.googleapis.com/

Here is a call to the same API for the authenticated user using the access_token query string parameter:

GET https://www.googleapis.com/drive/v2/files?access_token=<access_token>

curl examples

You can test these commands with the curl command-line application. Here's an example that uses the HTTP header option (preferred):

curl -H "Authorization: Bearer <access_token>" https://www.googleapis.com/drive/v2/files

Or, alternatively, the query string parameter option:

curl https://www.googleapis.com/drive/v2/files?access_token=<access_token>

Refreshing an access token

Access tokens periodically expire. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.

To refresh an access token, your application sends an HTTPS POST request to Google's authorization server (https://www.googleapis.com/oauth2/v4/token) that includes the following parameters:

Fields
refresh_token The refresh token returned from the authorization code exchange.
client_id The client ID obtained from the API Console.
client_secret The client secret obtained from the API Console.
grant_type As defined in the OAuth 2.0 specification, this field must contain a value of refresh_token.

The following snippet shows a sample request:

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=<your_client_id>&
client_secret=<your_client_secret>&
refresh_token=<refresh_token>&
grant_type=refresh_token

As long as the user has not revoked the access granted to the application, the token server returns a JSON object that contains a new access token. The following snippet shows a sample response:

{
  "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in":3920,
  "token_type":"Bearer"
}

Note that there are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients. You should save refresh tokens in long-term storage and continue to use them as long as they remain valid. If your application requests too many refresh tokens, it may run into these limits, in which case older refresh tokens will stop working.

Revoking a token

In some cases a user may wish to revoke access given to an application. A user can revoke access by visiting Account Settings. It is also possible for an application to programmatically revoke the access given to it. Programmatic revocation is important in instances where a user unsubscribes or removes an application. In other words, part of the removal process can include an API request to ensure the permissions granted to the application are removed.

To programmatically revoke a token, your application makes a request to https://accounts.google.com/o/oauth2/revoke and includes the token as a parameter:

curl -H "Content-type:application/x-www-form-urlencoded" \
        https://accounts.google.com/o/oauth2/revoke?token={token}

The token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.

If the revocation is successfully processed, then the status code of the response is 200. For error conditions, a status code 400 is returned along with an error code.

Allowed scopes

The OAuth 2.0 flow for devices is supported only for the following scopes:

OpenID Connect, Google Sign-In
profile
openid
email
Analytics Configuration and Reporting APIs
https://www.googleapis.com/auth/analytics
https://www.googleapis.com/auth/analytics.readonly
Calendar API
https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/calendar.readonly
Contacts API
https://www.google.com/m8/feeds
https://www.googleapis.com/auth/contacts.readonly
Cloud Print API
https://www.googleapis.com/auth/cloudprint
Cloud Storage API
https://www.googleapis.com/auth/devstorage.full_control
https://www.googleapis.com/auth/devstorage.read_write
Fitness REST API
https://www.googleapis.com/auth/fitness.activity.read
https://www.googleapis.com/auth/fitness.activity.write
https://www.googleapis.com/auth/fitness.body.read
https://www.googleapis.com/auth/fitness.body.write
https://www.googleapis.com/auth/fitness.location.read
https://www.googleapis.com/auth/fitness.location.write
Fusion Tables API
https://www.googleapis.com/auth/fusiontables
YouTube Data and Live Streaming APIs
https://www.googleapis.com/auth/youtube
https://www.googleapis.com/auth/youtube.readonly
https://www.googleapis.com/auth/youtube.upload