Hide

Using OAuth 2.0 for Web Server Applications

You can use the Google API Client Libraries or Google OAuth 2.0 endpoints to create web server applications that use OAuth 2.0 authorization to access Google APIs. OAuth 2.0 allows users to share specific data with an application while keeping their usernames, passwords, and other information private. For example, a web application can use OAuth 2.0 to obtain permission from users to store files in their Google Drives.

This document describes using OAuth 2.0 for user authorization. Web applications frequently also use service accounts when making API calls, particularly when calling Cloud APIs to access project-based data rather than user-specific data. These mechanisms can be used in conjunction with user authorization in a web server application.

Overview

To use OAuth 2.0 in a web application, first create web application credentials for your project in the Developers Console.

Then, when your application needs to access a user's data with a Google API, your application redirects the user to Google's OAuth 2.0 server. The OAuth 2.0 server authenticates the user and obtains consent from the user for your application to access the user's data.

Next, Google's OAuth 2.0 server redirects the user back to your application along with a single-use authorization code. Your application exchanges this authorization code for an access token.

Finally, your application can use the access token to call Google APIs.

When you use a Google API Client Library to handle your application's OAuth 2.0 flow, the client library keeps track of when a stored access token can be used and when the application must re-acquire consent, generates correct redirect URLs, and helps to implement redirect handlers that exchange authorization codes for access tokens. An application that carries out the OAuth 2.0 flow without using a client library must correctly complete the same steps.

Client libraries

The language-specific examples on this page make use of the Google API Client Libraries, which make API authorization with OAuth 2.0 simpler. To run the example code, you must first install the client library for your language.

Client libraries are available for the following languages:

Creating web application credentials

All web applications that use OAuth 2.0 must have credentials that identify the application to the OAuth 2.0 server. Applications that have these credentials can access the APIs that you enabled for your project.

To obtain web application credentials for your project, complete these steps:

  1. Go to the Google Developers Console.
  2. Select a project, or create a new one.
  3. In the sidebar on the left, expand APIs & auth. Next, click APIs. Select the Enabled APIs link in the API section to see a list of all your enabled APIs. Make sure that the API is on the list of enabled APIs. If you have not enabled it, select the API from the list of APIs, then select the Enable API button for the API.
  4. In the sidebar on the left, select Credentials.
  5. If you haven't done so already, create your OAuth 2.0 credentials by clicking Create new Client ID under the OAuth heading. Next, look for your application's client ID and client secret in the relevant table.
  6. You can also create and edit redirect URIs from this page. Redirect URIs are the URIs to your application's auth endpoints, which handle responses from the OAuth 2.0 server. You must change this value from the default example to the URI of your application's auth endpoint before you can use OAuth 2.0. For testing, you can specify URIs that refer to the local machine, such as http://localhost:8080. You should design your app's auth endpoints in a way that doesn't expose authorization codes to other resources on the page.

Download the client_secrets.json file and securely store it in a location that only your application can access.

Preparing to start the OAuth 2.0 flow

If you are using a Google API client library to handle the OAuth 2.0 flow, configure the client object, which you will use to make OAuth 2.0 requests. If you are handling the flow by directly accessing the OAuth 2.0 endpoints, just take note of the client ID that you created in the previous step and the scopes you need to request.

To configure the client object:

PHP

Use the client_secrets.json file that you created to configure a client object in your application. When you configure a client object, you specify the scopes your application needs to access, along with the URL to your application's auth endpoint, which will handle the response from the OAuth 2.0 server.

For example, to request read-only access to a user's Google Drive:

$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');

Your application uses the client object to perform OAuth 2.0 operations, such as generating authorization request URLs and applying access tokens to HTTP requests.

Python

Use the client_secrets.json file that you created to configure a client object in your application. When you configure a client object, you specify the scopes your application needs to access, along with the URL to your application's auth endpoint, which will handle the response from the OAuth 2.0 server.

For example, to request read-only access to a user's Google Drive:

from oauth2client import client

flow = client.flow_from_clientsecrets(
    'client_secrets.json',
    scope='https://www.googleapis.com/auth/drive.metadata.readonly',
    redirect_uri='http://www.example.com/oauth2callback')

Your application uses the client object to perform OAuth 2.0 operations, such as generating authorization request URLs and applying access tokens to HTTP requests.

Ruby

Use the client_secrets.json file that you created to configure a client object in your application. When you configure a client object, you specify the scopes your application needs to access, along with the URL to your application's auth endpoint, which will handle the response from the OAuth 2.0 server.

For example, to request read-only access to a user's Google Drive:

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'http://www.example.com/oauth2callback'
)

Your application uses the client object to perform OAuth 2.0 operations, such as generating authorization request URLs and applying access tokens to HTTP requests.

HTTP/REST

Take note of the following values:

  • Your app's client ID and client secret, which you created in Creating web application credentials.
  • The scopes that your app needs to request. See the documentation for the APIs your app uses for the required scopes.

Redirecting to Google's OAuth 2.0 server

When your application needs to access a user's data, redirect the user to Google's OAuth 2.0 server.

PHP

  1. Generate a URL to request access from Google's OAuth 2.0 server:
    $auth_url = $client->createAuthUrl();
  2. Redirect the user to $auth_url:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

  1. Generate a URL to request access from Google's OAuth 2.0 server:
    auth_uri = flow.step1_get_authorize_url()
  2. Redirect the user to auth_uri.

Ruby

  1. Generate a URL to request access from Google's OAuth 2.0 server:
    auth_uri = auth_client.authorization_uri.to_s
  2. Redirect the user to auth_uri.

HTTP/REST

Generate a URL to request access from Google's OAuth 2.0 endpoint at https://accounts.google.com/o/oauth2/auth. This endpoint is accessible over HTTPS; plain HTTP connections are refused.

The set of query string parameters supported by the Google Authorization Server for web server applications are:

Parameter Values Description
response_type code Determines whether the Google OAuth 2.0 endpoint returns an authorization code. Web server applications should use code.
client_id The client ID you obtain from the Developers Console. Identifies the client that is making the request. The value passed in this parameter must exactly match the value shown in the Google Developers Console.
redirect_uri One of the redirect_uri values listed for this project in the Developers Console. Determines where the response is sent. The value of this parameter must exactly match one of the values listed for this project in the Google Developers Console (including the http or https scheme, case, and trailing '/').
scope Space-delimited set of permissions that the application requests. Identifies the Google API access that your application is requesting. The values passed in this parameter inform the consent screen that is shown to the user. There is an inverse relationship between the number of permissions requested and the likelihood of obtaining user consent. For information about available login scopes, see Login scopes. To see the available scopes for all Google APIs, visit the APIs Explorer. It is generally a best practice to request scopes incrementally, at the time access is required, rather than up front. For example, an app that wants to support purchases should not request Google Wallet access until the user presses the “buy” button; see Incremental authorization.
state Any string Provides any state that might be useful to your application upon receipt of the response. The Google Authorization Server roundtrips this parameter, so your application receives the same value it sent. To mitigate against cross-site request forgery (CSRF), it is strongly recommended to include an anti-forgery token in the state, and confirm it in the response. See OpenID Connect for an example of how to do this.
access_type online or offline Indicates whether your application needs to access a Google API when the user is not present at the browser. This parameter defaults to online. If your application needs to refresh access tokens when the user is not present at the browser, then use offline. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code for a user.
approval_prompt force or auto Indicates whether the user should be re-prompted for consent. The default is auto, so a given user should only see the consent page for a given set of scopes the first time through the sequence. If the value is force, then the user sees a consent page even if they previously gave consent to your application for a given set of scopes.
login_hint email address or sub identifier When your application knows which user it is trying to authenticate, it can provide this parameter as a hint to the Authentication Server. Passing this hint will either pre-fill the email box on the sign-in form or select the proper multi-login session, thereby simplifying the login flow.
include_granted_scopes true or false If this is provided with the value true, and the authorization request is granted, the authorization will include any previous authorizations granted to this user/application combination for other scopes; see Incremental Authorization.

An example URL is shown below, with line breaks and spaces for readability.

https://accounts.google.com/o/oauth2/auth?
 scope=email%20profile&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps://oa2cb.example.com/myHome&
 redirect_uri=https%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&,
 response_type=code&
 client_id=812741506391.apps.googleusercontent.com&
 approval_prompt=force

After you create the request URL, redirect the user to it.

Google's OAuth 2.0 server will authenticate the user and obtain consent from the user for your application to access the requested scopes. The response will be sent back to your application using the redirect URL you specified.

Handling the OAuth 2.0 server response

The OAuth 2.0 server responds to your application's access request by using the URL specified in the request.

If the user approves the access request, then the response contains an authorization code. If the user does not approve the request, the response contains an error message. All responses are returned to the web server on the query string, as shown below:

An error response:

https://oauth2-login-demo.appspot.com/auth?error=access_denied

An authorization code response:

https://oauth2-login-demo.appspot.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

Important: If your response endpoint renders an HTML page, any resources on that page will be able to see the authorization code in the URL. Scripts can read the URL directly, and all resources may be sent the URL in the Referer HTTP header. Carefully consider if you want to send authorization credentials to all resources on that page (especially third-party scripts such as social plugins and analytics). To avoid this issue, we recommend that the server first handle the request, then redirect to another URL that doesn't include the response parameters.

After the web server receives the authorization code, it can exchange the authorization code for an access token.

PHP

To exchange an authorization code for an access token, use the authenticate method:

$client->authenticate($_GET['code']);

You can retrieve the access token with the getAccessToken method:

$access_token = $client->getAccessToken();

Python

To exchange an authorization code for an access token, use the step2_exchange method:

credentials = flow.step2_exchange(auth_code)

Then, use the Credentials object that the step2_exchange method returns to apply the access token to an Http object:

http_auth = credentials.authorize(httplib2.Http())

Ruby

To exchange an authorization code for an access token, use the fetch_access_token! method:

auth_client.code = auth_code
auth_client.fetch_access_token!

HTTP/REST

To exchange an authorization code for an access token, use the https://www.googleapis.com/oauth2/v3/token endpoint, which includes the following parameters:

Field Description
code The authorization code returned from the initial request.
client_id The client ID obtained from the Developers Console.
client_secret The client secret obtained from the Developers Console.
redirect_uri One of the redirect URIs listed for this project in the Developers Console.
grant_type As defined in the OAuth 2.0 specification, this field must contain a value of authorization_code.

The actual request might look like the following:

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

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code

A successful response to this request contains the following fields:

Field Description
access_token The token that can be sent to a Google API.
refresh_token A token that may be used to obtain a new access token. Refresh tokens are valid until the user revokes access. This field is only present if access_type=offline is included in the authorization code request.
expires_in The remaining lifetime of the access token.
token_type Identifies the type of token returned. At this time, this field will always have the value Bearer.

A successful response is returned as a JSON array, similar to the following:

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

Calling Google APIs

PHP

Use the access token to call Google APIs by completing the following steps:

  1. If you need to apply an access token to a new Google_Client object—for example, if you stored the access token in a user session—use the setAccessToken method:
    $client->setAccessToken($access_token);
  2. Build a service object for the API that you want to call. You build a a service object by providing an authorized Google_Client object to the constructor for the API you want to call. For example, to call the Drive API:
    $drive_service = new Google_Service_Drive($client);
  3. Make requests to the API service using the interface provided by the service object. For example, to list the files in the authenticated user's Google Drive:
    $files_list = $drive_service->files->listFiles(array())->getItems();

Python

Use the authorized Http object to call Google APIs by completing the following steps:

  1. Build a service object for the API that you want to call. You build a a service object by calling the build function with the name and version of the API and the authorized Http object. For example, to call version 2 of the Drive API:
    from apiclient.discovery import build
    
    drive_service = build('drive', 'v2', http=http_auth)
  2. Make requests to the API service using the interface provided by the service object. For example, to list the files in the authenticated user's Google Drive:
    files = drive_service.files().list().execute()

Ruby

Use the auth_client object to call Google APIs by completing the following steps:

  1. Build a service object for the API that you want to call. For example, to call version 2 of the Drive API:
    drive = Google::Apis::DriveV2::DriveService.new
  2. Set the credentials on the service:
    drive.authorization = auth_client
  3. Make requests to the API service using the interface provided by the service object. For example, to list the files in the authenticated user's Google Drive:
    files = drive.list_files

Alternately, authorization can be provided on a per-method basis by supplying the options parameter to a method:

files = drive.list_files(options: { authorization: auth_client })

HTTP/REST

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.

Examples

A call to the drive.files endpoint (the Drive API) using the access_token query string parameter might look like the following, though you'll need to specify your own access token:

GET https://www.googleapis.com/drive/v2/files?access_token=1/fFBGRNJru1FQd44AzqT3Zg

Here is a call to the same API for the authenticated user (me) using the Authorization: Bearer HTTP header:

GET /drive/v2/files HTTP/1.1
Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg
Host: googleapis.com

You can try out with the curl command-line application. Here's an example using the HTTP header option (preferred):

curl -H "Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg" https://www.googleapis.com/drive/v2/files

Or, alternatively, the query string parameter option:

curl https://www.googleapis.com/drive/v2/files?access_token=1/fFBGRNJru1FQd44AzqT3Zg

Complete example

The following example prints a JSON-formatted list of files in a user's Google Drive after the user authenticates and gives consent for the application to access the user's Drive files.

PHP

To run this example:

  1. In the Developers Console, add the URL of the local machine to the list of redirect URLs. For example, add http://localhost:8080.
  2. Create a new directory and change to it. For example:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. Clone the Google API Client Library for PHP:
    git clone https://github.com/google/google-api-php-client
  4. Create the files index.php and oauth2callback.php with the content below.
  5. Run the example with a web server configured to serve PHP. If you use PHP 5.4 or newer, you can use PHP's built-in test web server:
    php -S localhost:8080 ~/php-oauth2-example

index.php

<?php
require_once 'google-api-php-client/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $drive_service = new Google_Service_Drive($client);
  $files_list = $drive_service->files->listFiles(array())->getItems();
  echo json_encode($files_list);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

<?php
require_once 'google-api-php-client/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

This example uses the Flask framework.

import json

import flask
import httplib2

from apiclient import discovery
from oauth2client import client


app = flask.Flask(__name__)


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = client.OAuth2Credentials.from_json(flask.session['credentials'])
  if credentials.access_token_expired:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    http_auth = credentials.authorize(httplib2.Http())
    drive_service = discovery.build('drive', 'v2', http_auth)
    files = drive_service.files().list().execute()
    return json.dumps(files)


@app.route('/oauth2callback')
def oauth2callback():
  flow = client.flow_from_clientsecrets(
      'client_secrets.json',
      scope='https://www.googleapis.com/auth/drive.metadata.readonly',
      redirect_uri=flask.url_for('oauth2callback', _external=True),
      include_granted_scopes=True)
  if 'code' not in flask.request.args:
    auth_uri = flow.step1_get_authorize_url()
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    credentials = flow.step2_exchange(auth_code)
    flask.session['credentials'] = credentials.to_json()
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

Ruby

This example uses the Sinatra framework.

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'

enable :sessions
set :session_secret, 'setme'

get '/' do
  unless session.has_key?(:credentials)
    redirect to('/oauth2callback')
  end
  client_opts = JSON.parse(session[:credentials])
  auth_client = Signet::OAuth2::Client.new(client_opts)
  drive = Google::Apis::DriveV2::DriveService.new
  files = drive.list_files(options: { authorization: auth_client })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  client_secrets = Google::APIClient::ClientSecrets.load
  auth_client = client_secrets.to_authorization
  auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
    :redirect_uri => url('/oauth2callback'))
  if request['code'] == nil
    auth_uri = auth_client.authorization_uri.to_s
    redirect to(auth_uri)
  else
    auth_client.code = request['code']
    auth_client.fetch_access_token!
    auth_client.client_secret = nil
    session[:credentials] = auth_client.to_json
    redirect to('/')
  end
end

HTTP/REST

This example in Python uses the Flask framework and the Requests library to demonstrate the OAuth 2.0 web flow. Note that using the Python client library is easier and is the recommended way to implement this flow.

import json

import flask
import requests


app = flask.Flask(__name__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/drive/v2/files'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://www.googleapis.com/oauth2/v3/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

Incremental authorization

In the OAuth 2.0 protocol, your app requests authorization to access resources which are identified by scopes, and assuming the user is authenticated and approves, your app receives short-lived access tokens which let it access those resources, and (optionally) refresh tokens to allow long-term access.

It is considered a best user-experience practice to request authorization for resources at the time you need them. For example, an app that lets people sample music tracks and create mixes might need very few resources at sign-in time, perhaps nothing more than the name of the person signing in. However, saving a completed mix would require access to their Google Drive. Most people would find it natural if they only were asked for access to their Google Drive at the time the app actually needed it.

In this case, at sign-in time the app might request the profile scope to perform basic sign-in, and then later request the https://www.googleapis.com/auth/drive.file scope at the time of the first request to save a mix.

Using the procedures described in Using OpenID Connect and Using OAuth 2.0 to Access Google APIs would normally result in your app having to manage two different access tokens.

To avoid this complexity, you can include previously granted scopes in your authorization requests. For example:

PHP

$client->setIncludeGrantedScopes(true);

Python

flow = client.flow_from_clientsecrets(...)
flow.params['include_granted_scopes'] = True

Ruby

auth_client.update!(
  :additional_parameters => {"include_granted_scopes" => "true"}
)

HTTP/REST

GET https://accounts.google.com/o/oauth2/auth?
  scope=https://www.googleapis.com/auth/drive.file&
  state=security_token%3D138r5719ru3e1%26url%3Dhttps://oa2cb.example.com/myHome&
  redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fcallback&
  response_type=code&
  client_id=8127352506391.apps.googleusercontent.com&
  approval_prompt=force&
  include_granted_scopes=true

Let's call the resulting authorization the "combined authorization"; the following apply:

  • You can use the access tokens you get to access the resources corresponding to any of the scopes that are rolled into the combined authorization.
  • When you use the refresh token for a combined authorization, the new access tokens represent the combined authorization and can be used for any of its scopes.
  • The combined authorization includes any previously granted authorizations even if they were requested from different clients. For example, if you requested the profile scope from a desktop app, and then issued the request in the example URI above for the same user from a mobile app, and it was granted, the combined authorization would include both scopes.
  • When you revoke a token which represents a combined authorization, all of the authorizations are revoked simultaneously; this means that if you retain a token for one of the previous authorizations, it will stop working.

When you make an authorization request with granted scopes included, the Google authorization server rolls the authorization request together with all the previous authorizations granted to the requesting user from the requesting app.

Offline access

In some cases, your application might need to access a Google API when the user is not present. Examples of this include backup services and applications that make Blogger posts exactly at 8am on Monday morning. This style of access is called offline, and web server applications can request offline access from a user. The normal and default style of access is called online.

PHP

If your application needs offline access to a Google API, set the API client's access type to offline:

$client->setAccessType("offline");

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

Python

If your application needs offline access to a Google API, set the API client's access type to offline:

flow = client.flow_from_clientsecrets(...)
flow.params['access_type'] = 'offline'

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

Ruby

If your application needs offline access to a Google API, set the API client's access type to offline:

auth_client.update!(
  :additional_parameters => {"access_type" => "offline"}
)

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

HTTP/REST

If your application needs offline access to a Google API, then the request for an authorization code should include the access_type parameter, where the value of that parameter is offline. For example:

https://accounts.google.com/o/oauth2/auth?
 scope=email%20profile&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps://oa2cb.example.com/myHome&
 redirect_uri=https%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&
 response_type=code&
 client_id=812741506391.apps.googleusercontent.com&
 access_type=offline

The first time a given user's browser is sent to this URL, they see a consent page. If they grant access, then the response includes an authorization code which may be redeemed for an access token and a refresh token.

An example of an authorization code exchange is shown below:

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

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code

If this is the first time the application has exchanged an authorization code for a user, then the response includes an access token and a refresh token, as shown below:

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

After your application receives the refresh token, it can obtain new access tokens at any time. See the section on refresh tokens for more information.

The next time your application requests an authorization code for that user, the user will not be asked to grant consent (assuming they previously granted access, and you are asking for the same scopes). As expected, the response includes an authorization code which may be redeemed. However, unlike the first time an authorization code is exchanged for a given user, a refresh token will not be returned from the authorization code exchange. The following is an example of such a response:

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

Using a refresh token

As indicated in the previous section, a refresh token is obtained in offline scenarios during the first authorization code exchange. In these cases, your application may obtain a new access token by sending a refresh token to the Google OAuth 2.0 Authorization server.

To obtain a new access token this way, your application sends an HTTPS POST request to https://www.googleapis.com/oauth2/v3/token. The request must include the following parameters:

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

Such a request will look similar to the following:

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

client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
refresh_token=1/6BMfW9j53gdGImsiyUH5kU5RsR4zwI9lUVX-tqf8JXQ&
grant_type=refresh_token

As long as the user has not revoked the access granted to your application, the response includes a new access token. A response from such a request is shown below:

{
  "access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
  "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.

PHP

To programmatically revoke a token, call revokeToken():

$client->revokeToken();

Python

To programmatically revoke a token, call revoke():

credentials.revoke(httplib2.Http())

Ruby

To programmatically revoke a token, make an HTTP request to the oauth2.revoke endpoint:

uri = URI('https://accounts.google.com/o/oauth2/revoke')
params = { :token => auth_client.access_token }
uri.query = URI.encode_www_form(params)
response = Net::HTTP.get(uri)

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.

HTTP/REST

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 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.