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:
- Open the Credentials page.
- 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.
-
You can also create and edit redirect URIs from this page, by clicking a client ID. 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
- Generate a URL to request access from Google's OAuth 2.0 server:
$auth_url = $client->createAuthUrl();
- Redirect the user to
$auth_url:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
- Generate a URL to request access from Google's OAuth 2.0 server:
auth_uri = flow.step1_get_authorize_url()
- Redirect the user to
auth_uri.
Ruby
- Generate a URL to request access from Google's OAuth 2.0 server:
auth_uri = auth_client.authorization_uri.to_s
- 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/v2/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. |
||||||
prompt |
Space-delimited, case-sensitive list of prompts to present the user. If you don't specify this parameter, the user will be prompted only the first time your app requests access. |
Possible values:
|
||||||
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/v2/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
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/v4/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/v4/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:
- If you need to apply an access token to a new
Google_Clientobject—for example, if you stored the access token in a user session—use thesetAccessTokenmethod:$client->setAccessToken($access_token);
- Build a service object for the API that you want to call. You build a
a service object by providing an authorized
Google_Clientobject to the constructor for the API you want to call. For example, to call the Drive API:$drive_service = new Google_Service_Drive($client);
- 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:
- Build a service object for the API that you want to call. You build a
a service object by calling the
buildfunction with the name and version of the API and the authorizedHttpobject. For example, to call version 2 of the Drive API:from apiclient.discovery import build drive_service = build('drive', 'v2', http=http_auth) - 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:
- 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
- Set the credentials on the service:
drive.authorization = auth_client
- 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:
- In the Developers Console, add the URL of the local machine to the
list of redirect URLs. For example, add
http://localhost:8080. - Create a new directory and change to it. For example:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Clone the Google API Client Library for PHP:
git clone https://github.com/google/google-api-php-client
- Create the files index.php and oauth2callback.php with the content below.
- 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/v2/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/v4/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/v2/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& prompt=consent& 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
profilescope 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/v2/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/v4/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/v4/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/v4/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.