此页面由 Cloud Translation API 翻译。
Switch to English

将OAuth 2.0用于Web服务器应用程序

本文档说明了网络服务器应用程序如何使用Google API客户端库或Google OAuth 2.0端点来实现OAuth 2.0授权以访问Google API。

OAuth 2.0允许用户与应用程序共享特定数据,同时将用户名,密码和其他信息保密。例如,应用程序可以使用OAuth 2.0获得用户的许可,以将文件存储在其Google云端硬盘中。

此OAuth 2.0流程专门用于用户授权。它是为可以存储机密信息并维护状态的应用程序而设计的。在用户与应用程序交互时或在用户离开应用程序之后,经过适当授权的Web服务器应用程序可以访问API。

Web服务器应用程序还经常使用服务帐户来授权API请求,尤其是在调用Cloud API来访问基于项目的数据而不是特定于用户的数据时。 Web服务器应用程序可以将服务帐户与用户授权一起使用。

客户端库

此页面上特定于语言的示例使用Google API客户端库来实现OAuth 2.0授权。要运行代码示例,您必须首先安装您所用语言的客户端库。

当您使用Google API客户端库来处理应用程序的OAuth 2.0流时,客户端库会执行许多其他操作,而这些操作本应由应用程序自行处理。例如,它确定应用程序何时可以使用或刷新存储的访问令牌,以及应用程序何时必须重新获得同意。客户端库还会生成正确的重定向URL,并有助于实现重定向处理程序,该处理程序交换访问令牌的授权代码。

客户端库可用于以下语言:

先决条件

为您的项目启用API

任何调用Google API的应用程序都需要在API Console中启用这些API。

为您的项目启用API:

  1. Google API Console中的Open the API Library
  2. If prompted, select a project, or create a new one.
  3. API Library列出了所有可用的API,并按产品系列和受欢迎程度分组。如果您要启用的API在列表中不可见,请使用搜索找到它,或单击其所属产品系列中的“查看全部”。
  4. 选择要启用的API,然后单击“启用”按钮。
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

创建授权凭证

使用OAuth 2.0访问Google API的任何应用程序都必须具有授权凭据,以将应用程序标识到Google的OAuth 2.0服务器。以下步骤说明了如何为您的项目创建凭据。然后,您的应用程序可以使用凭据来访问为该项目启用的API。

  1. Go to the Credentials page.
  2. 点击创建凭据> OAuth客户端ID
  3. 选择Web应用程序应用程序类型。
  4. 填写表格,然后点击创建。使用PHP,Java,Python,Ruby和.NET等语言和框架的应用程序必须指定授权的重定向URI 。重定向URI是OAuth 2.0服务器可以向其发送响应的端点。这些端点必须遵守Google的验证规则

    为了进行测试,您可以指定引用本地计算机的URI,例如http://localhost:8080 。考虑到这一点,请注意,本文档中的所有示例都使用http://localhost:8080作为重定向URI。

    我们建议您设计应用程序的身份验证终结点,以使您的应用程序不会将授权代码暴露给页面上的其他资源。

创建凭据后,从API Console下载client_secret.json文件。将文件安全地存储在只有您的应用程序可以访问的位置。

确定访问范围

范围使您的应用程序仅可以请求访问其所需的资源,同时还使用户能够控制他们授予您的应用程序的访问量。因此,请求的范围数与获得用户同意的可能性之间可能存在反比关系。

在开始实施OAuth 2.0授权之前,我们建议您确定您的应用需要访问权限的范围。

我们还建议您的应用程序通过增量授权过程请求访问授权范围,在该过程中,您的应用程序请求访问上下文中的用户数据。此最佳实践可帮助用户更轻松地了解您的应用程序为何需要其所请求的访问权限。

OAuth 2.0 API范围文档包含您可以用来访问Google API的范围的完整列表。

特定语言的要求

要运行本文档中的任何代码示例,您将需要一个Google帐户,一个Internet访问权限和一个Web浏览器。如果您使用的是API客户端库之一,还请参见下面的特定于语言的要求。

的PHP

要运行本文档中的PHP代码示例,您需要:

  • 安装了命令行界面(CLI)和JSON扩展的PHP 5.4或更高版本。
  • Composer依赖性管理工具。
  • 适用于PHP的Google API客户端库:

    php composer.phar require google/apiclient:^2.0

Python

要运行本文档中的Python代码示例,您需要:

  • Python 2.6或更高版本
  • 点子包管理工具。
  • 适用于Python的Google API客户端库:
    pip install --upgrade google-api-python-client
  • 用于用户授权的google-authgoogle-auth-oauthlibgoogle-auth-httplib2
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • Flask Python Web应用程序框架。
    pip install --upgrade flask
  • requests HTTP库。
    pip install --upgrade requests

红宝石

要运行本文档中的Ruby代码示例,您需要:

  • Ruby 2.2.2或更高版本
  • 适用于Ruby的Google API客户端库:

    gem install google-api-client
  • Sinatra Ruby Web应用程序框架。

    gem install sinatra

HTTP / REST

您无需安装任何库即可直接调用OAuth 2.0端点。

获取OAuth 2.0访问令牌

以下步骤显示了您的应用程序如何与Google的OAuth 2.0服务器进行交互以获取用户的同意,以代表用户执行API请求。您的应用必须先获得同意,然后才能执行需要用户授权的Google API请求。

下面的列表快速总结了这些步骤:

  1. 您的应用程序将标识所需的权限。
  2. 您的应用程序将用户与请求的权限列表一起重定向到Google。
  3. 用户决定是否向您的应用程序授予权限。
  4. 您的应用程序可以找出用户的决定。
  5. 如果用户授予了请求的权限,则您的应用程序将检索代表用户发出API请求所需的令牌。

步骤1:设定授权参数

第一步是创建授权请求。该请求设置了用于标识您的应用程序的参数,并定义了将要求用户向您的应用程序授予的权限。

  • 如果您使用Google客户端库进行OAuth 2.0身份验证和授权,则会创建并配置一个定义这些参数的对象。
  • 如果直接调用Google OAuth 2.0端点,则将生成一个URL并在该URL上设置参数。

下面的选项卡定义了Web服务器应用程序支持的授权参数。特定于语言的示例还显示了如何使用客户端库或授权库来配置设置那些参数的对象。

的PHP

下面的代码段创建了一个Google_Client()对象,该对象定义了授权请求中的参数。

该对象使用client_secret.json文件中的信息来标识您的应用程序。 (有关该文件的更多信息,请参阅创建授权凭证。)该对象还标识您的应用程序请求访问权限的范围以及应用程序的auth端点的URL,该URL将处理来自Google OAuth 2.0服务器的响应。最后,代码设置了可选的access_typeinclude_granted_scopes参数。

例如,以下代码要求对用户的Google云端硬盘进行只读,离线访问:

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true);   // incremental auth

该请求指定以下信息:

参数
client_id必需的

您的应用程序的客户端ID。您可以在API Console Credentials page中找到该值。

在PHP中,调用setAuthConfig函数以从client_secret.json文件加载授权凭证。

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
redirect_uri必需的

确定用户完成授权流程后API服务器将用户重定向到的位置。该值必须与您在客户端的API Console Credentials page中配置的OAuth 2.0客户端的授权重定向URI之一完全匹配。如果此值与所提供的client_id的授权重定向URI不匹配,则会收到redirect_uri_mismatch错误。

请注意, httphttps方案,大小写和斜杠(' / ')必须全部匹配。

要在PHP中设置此值,请调用setRedirectUri函数。请注意,您必须为提供的client_id指定一个有效的重定向URI。

$client->setRedirectUri('https://oauth2.example.com/code');
scope必需的

用空格分隔的范围列表,这些范围标识应用程序可以代表用户访问的资源。这些值将告知Google向用户显示的同意屏幕。

范围使您的应用程序仅可以请求访问其所需的资源,同时还使用户能够控制他们授予您的应用程序的访问量。因此,在所请求范围的数量与获得用户同意的可能性之间存在反比关系。

要在PHP中设置此值,请调用addScope函数:

$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

我们建议您的应用程序尽可能请求在上下文中访问授权范围。通过使用增量授权在上下文中请求访问用户数据,您可以帮助用户更轻松地理解您的应用程序为何需要其所请求的访问权限。

access_type推荐的

指示当用户不在浏览器中时,您的应用程序是否可以刷新访问令牌。有效的参数值是online ,它是默认值,是offline

如果您的应用程序在浏览器中不存在用户时需要刷新访问令牌,则将该值设置为offline 。这是刷新访问令牌的方法,将在本文档后面部分介绍。此值指示Google授权服务器在您的应用程序第一次将授权代码交换为令牌时返回刷新令牌访问令牌。

要在PHP中设置此值,请调用setAccessType函数:

$client->setAccessType('offline');
state推荐的

指定应用程序用来维护授权请求和授权服务器的响应之间的状态的任何字符串值。在用户同意或拒绝您的应用程序的访问请求之后,服务器会返回您作为redirect_uri的URL查询组件( ? )中的name=value对发送的确切值。

您可以将此参数用于多种目的,例如将用户定向到应用程序中的正确资源,发送随机数以及减轻跨站点请求伪造。由于您可以猜测您的redirect_uri ,因此使用state值可以增加您对传入连接是身份验证请求的结果的保证。如果您生成随机字符串或对Cookie的哈希值或其他捕获客户端状态的值进行编码,则可以验证响应以进一步确保请求和响应源自同一浏览器,从而提供针对跨站点等攻击的防护要求伪造。有关如何创建和确认state令牌的示例,请参见OpenID Connect文档。

要在PHP中设置此值,请调用setState函数:

$client->setState($sample_passthrough_value);
include_granted_scopes选修的

使应用程序能够使用增量授权来请求访问上下文中的其他范围。如果将此参数的值设置为true并批准了授权请求,则新的访问令牌还将覆盖用户先前已授予应用程序访问权限的所有范围。有关示例,请参见增量授权部分。

要在PHP中设置此值,请调用setIncludeGrantedScopes函数:

$client->setIncludeGrantedScopes(true);
login_hint选修的

如果您的应用程序知道哪个用户正在尝试进行身份验证,则可以使用此参数向Google身份验证服务器提供提示。服务器通过预填写登录表单中的电子邮件字段或通过选择适当的多登录会话来使用提示来简化登录流程。

将参数值设置为电子邮件地址或sub标识符,与用户的Google ID等效。

要在PHP中设置此值,请调用setLoginHint函数:

$client->setLoginHint('None');
prompt选修的

以空格分隔的区分大小写的提示列表,以提示用户。如果您未指定此参数,则仅在您的项目第一次请求访问时才提示用户。有关更多信息,请参阅提示重新同意

要在PHP中设置此值,请调用setApprovalPrompt函数:

$client->setApprovalPrompt('consent');

可能的值为:

none不要显示任何身份验证或同意屏幕。不得与其他值一起指定。
consent提示用户同意。
select_account提示用户选择一个帐户。

Python

以下代码段使用google-auth-oauthlib.flow模块构造授权请求。

该代码构造了一个Flow对象,该对象使用创建授权凭证后下载的client_secret.json文件中的信息来标识您的应用程序。该对象还标识您的应用程序请求访问权限的范围以及应用程序的auth终结点的URL,该URL将处理来自Google OAuth 2.0服务器的响应。最后,代码设置了可选的access_typeinclude_granted_scopes参数。

例如,以下代码要求对用户的Google云端硬盘进行只读,离线访问:

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

该请求指定以下信息:

参数
client_id必需的

您的应用程序的客户端ID。您可以在API Console Credentials page中找到该值。

在Python中,调用from_client_secrets_file方法从client_secret.json文件中检索客户端ID。 (您也可以使用from_client_config方法,该方法传递客户端配置,因为它最初出现在客户端机密文件中,但不访问文件本身。)

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])
redirect_uri必需的

确定用户完成授权流程后API服务器将用户重定向到的位置。该值必须与您在客户端的API Console Credentials page中配置的OAuth 2.0客户端的授权重定向URI之一完全匹配。如果此值与提供的client_id的授权重定向URI不匹配,您将收到redirect_uri_mismatch错误。

请注意, httphttps方案,大小写和斜杠(' / ')必须全部匹配。

要在Python中设置此值,请设置flow对象的redirect_uri属性:

flow.redirect_uri = 'https://oauth2.example.com/code'
scope必需的

范围列表,用于标识应用程序可以代表用户访问的资源。这些值将告知Google向用户显示的同意屏幕。

范围使您的应用程序仅可以请求访问其所需的资源,同时还使用户能够控制他们授予您的应用程序的访问量。因此,在所请求范围的数量与获得用户同意的可能性之间存在反比关系。

在Python中,使用与设置client_id来指定作用域列表相同的方法。

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

我们建议您的应用程序尽可能请求在上下文中访问授权范围。通过使用增量授权在上下文中请求访问用户数据,您可以帮助用户更轻松地理解您的应用程序为何需要其所请求的访问权限。

access_type推荐的

指示当用户不在浏览器中时,您的应用程序是否可以刷新访问令牌。有效的参数值是online ,它是默认值,而offline则是offline

如果您的应用程序需要在用户不在浏览器中时刷新访问令牌,则将该值设置为offline 。这是刷新访问令牌的方法,将在本文档后面部分介绍。此值指示Google授权服务器在您的应用程序第一次将授权代码交换为令牌时返回刷新令牌访问令牌。

在Python,设置access_type通过指定参数access_type调用时作为关键字参数flow.authorization_url方法:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
state推荐的

指定应用程序用来维护授权请求和授权服务器的响应之间的状态的任何字符串值。在用户同意或拒绝您的应用程序的访问请求之后,服务器会返回您作为redirect_uri的URL查询组件( ? )中的name=value对发送的确切值。

您可以将此参数用于多种目的,例如将用户定向到应用程序中的正确资源,发送随机数以及减轻跨站点请求伪造。由于可以猜测您的redirect_uri ,因此使用state值可以增加对传入连接是身份验证请求的结果的保证。如果您生成随机字符串或对Cookie的哈希值或其他捕获客户端状态的值进行编码,则可以验证响应以进一步确保请求和响应源自同一浏览器,从而提供针对跨站点等攻击的防护要求伪造。有关如何创建和确认state令牌的示例,请参见OpenID Connect文档。

在Python,设定state通过指定参数state调用时作为关键字参数flow.authorization_url方法:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes选修的

使应用程序能够使用增量授权来请求访问上下文中的其他范围。如果将此参数的值设置为true并批准了授权请求,则新的访问令牌还将覆盖用户先前已授予应用程序访问权限的所有范围。有关示例,请参见增量授权部分。

在Python,设置include_granted_scopes参数通过指定include_granted_scopes调用时作为关键字参数flow.authorization_url方法:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint选修的

如果您的应用程序知道哪个用户正在尝试进行身份验证,则可以使用此参数向Google身份验证服务器提供提示。服务器通过预填写登录表单中的电子邮件字段或选择适当的多登录会话来使用提示来简化登录流程。

将参数值设置为电子邮件地址或sub标识符,与用户的Google ID等效。

在Python,设置login_hint通过指定参数login_hint调用时作为关键字参数flow.authorization_url方法:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    login_hint='None',
    include_granted_scopes='true')
prompt选修的

以空格分隔的区分大小写的提示列表,以提示用户。如果您未指定此参数,则仅在您的项目第一次请求访问时才提示用户。有关更多信息,请参阅提示重新同意

在Python,设置prompt通过指定参数prompt调用时作为关键字参数flow.authorization_url方法:

authorization_url, state = flow.authorization_url(
      access_type='offline',
      prompt='consent',
      include_granted_scopes='true')

可能的值为:

none不要显示任何身份验证或同意屏幕。不得与其他值一起指定。
consent提示用户同意。
select_account提示用户选择一个帐户。

红宝石

使用您创建的client_secrets.json文件在应用程序中配置客户端对象。配置客户端对象时,您可以指定应用程序需要访问的范围以及应用程序的auth终结点的URL,该URL将处理来自OAuth 2.0服务器的响应。

例如,以下代码要求对用户的Google云端硬盘进行只读,离线访问:

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',
  :additional_parameters => {
    "access_type" => "offline",         # offline access
    "include_granted_scopes" => "true"  # incremental auth
  }
)

您的应用程序使用客户端对象执行OAuth 2.0操作,例如生成授权请求URL并将访问令牌应用于HTTP请求。

HTTP / REST

Google的OAuth 2.0终结点位于https://accounts.google.com/o/oauth2/v2/auth 。该端点只能通过HTTPS访问。纯HTTP连接被拒绝。

Google授权服务器支持Web服务器应用程序的以下查询字符串参数:

参数
client_id必需的

您的应用程序的客户端ID。您可以在API Console Credentials page中找到该值。

redirect_uri必需的

确定用户完成授权流程后API服务器将用户重定向到的位置。该值必须与您在客户端的API Console Credentials page中配置的OAuth 2.0客户端的授权重定向URI之一完全匹配。如果此值与所提供的client_id的授权重定向URI不匹配,则会收到redirect_uri_mismatch错误。

请注意, httphttps方案,大小写和斜杠(' / ')必须全部匹配。

response_type必需的

确定Google OAuth 2.0端点是否返回授权码。

将参数值设置为Web服务器应用程序的code

scope必需的

用空格分隔的范围列表,这些范围标识应用程序可以代表用户访问的资源。这些值将告知Google向用户显示的同意屏幕。

范围使您的应用程序仅可以请求访问其所需的资源,同时还使用户能够控制他们授予您的应用程序的访问量。因此,在所请求范围的数量与获得用户同意的可能性之间存在反比关系。

我们建议您的应用程序尽可能请求在上下文中访问授权范围。通过使用增量授权在上下文中请求访问用户数据,可以帮助用户更轻松地理解应用程序为何需要其所请求的访问权限。

access_type推荐的

指示当用户不在浏览器中时,您的应用程序是否可以刷新访问令牌。有效的参数值是online ,它是默认值,而offline则是offline

如果您的应用程序在浏览器中不存在用户时需要刷新访问令牌,则将该值设置为offline 。这是刷新访问令牌的方法,将在本文档后面部分介绍。此值指示Google授权服务器在您的应用程序第一次将授权代码交换为令牌时返回刷新令牌访问令牌。

state推荐的

指定应用程序用来维护授权请求和授权服务器的响应之间的状态的任何字符串值。在用户同意或拒绝您的应用程序的访问请求之后,服务器会返回您作为redirect_uri的URL查询组件( ? )中的name=value对发送的确切值。

您可以将此参数用于多种目的,例如将用户定向到应用程序中的正确资源,发送随机数以及减轻跨站点请求伪造。由于可以猜测您的redirect_uri ,因此使用state值可以增加对传入连接是身份验证请求的结果的保证。如果您生成随机字符串或对Cookie的哈希值或其他捕获客户端状态的值进行编码,则可以验证响应以进一步确保请求和响应源自同一浏览器,从而提供针对跨站点等攻击的防护要求伪造。有关如何创建和确认state令牌的示例,请参见OpenID Connect文档。

include_granted_scopes选修的

使应用程序能够使用增量授权来请求访问上下文中的其他范围。如果将此参数的值设置为true并批准了授权请求,则新的访问令牌还将覆盖用户先前已授予应用程序访问权限的所有范围。有关示例,请参见增量授权部分。

login_hint选修的

如果您的应用程序知道哪个用户正在尝试进行身份验证,则可以使用此参数向Google身份验证服务器提供提示。服务器通过预填写登录表单中的电子邮件字段或通过选择适当的多登录会话来使用提示来简化登录流程。

将参数值设置为电子邮件地址或sub标识符,与用户的Google ID等效。

prompt选修的

以空格分隔的区分大小写的提示列表,以提示用户。如果您未指定此参数,则仅在您的项目第一次请求访问时才提示用户。有关更多信息,请参阅提示重新同意

可能的值为:

none不要显示任何身份验证或同意屏幕。不得与其他值一起指定。
consent提示用户同意。
select_account提示用户选择一个帐户。

第2步:重定向到Google的OAuth 2.0服务器

将用户重定向到Google的OAuth 2.0服务器,以启动身份验证和授权过程。通常,这在您的应用程序首次需要访问用户数据时发生。对于增量授权,当您的应用程序首先需要访问尚无访问权限的其他资源时,也会发生此步骤。

的PHP

  1. 生成一个URL,以请求从Google的OAuth 2.0服务器进行访问:
    $auth_url = $client->createAuthUrl();
  2. 将用户重定向到$auth_url
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

此示例说明如何使用Flask Web应用程序框架将用户重定向到授权URL:

return flask.redirect(authorization_url)

红宝石

  1. 生成一个URL,以请求从Google的OAuth 2.0服务器进行访问:
    auth_uri = auth_client.authorization_uri.to_s
  2. 将用户重定向到auth_uri

HTTP / REST

样本重定向到Google的授权服务器

下面显示了一个示例URL,其中包含换行符和空格,以提高可读性。

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

创建请求URL后,将用户重定向到该URL。

Google的OAuth 2.0服务器对用户进行身份验证,并获得用户的同意,您的应用才能访问所请求的范围。响应将使用您指定的重定向URL发送回您的应用程序。

第3步:Google提示用户同意

在此步骤中,用户决定是否向您的应用程序授予所请求的访问权限。在此阶段,Google将显示一个同意窗口,其中显示了您的应用程序的名称以及它请求使用用户的授权凭证进行访问的Google API服务以及要授予的访问范围的摘要。然后,用户可以同意授予对您的应用程序请求的一个或多个范围的访问权限,或拒绝该请求。

您的应用程序在此阶段不需要执行任何操作,因为它等待来自Google的OAuth 2.0服务器的响应(指示是否已授予任何访问权限)。该响应将在以下步骤中进行说明。

步骤4:处理OAuth 2.0服务器响应

OAuth 2.0服务器通过使用请求中指定的URL来响应您的应用程序的访问请求。

如果用户批准访问请求,则响应中将包含授权码。如果用户不同意该请求,则响应中将包含一条错误消息。返回到Web服务器的授权代码或错误消息出现在查询字符串上,如下所示:

错误响应:

https://oauth2.example.com/auth?error=access_denied

授权码响应:

https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

OAuth 2.0服务器响应示例

您可以通过单击以下示例URL来测试此流程,该示例URL要求具有只读访问权限,以查看Google云端硬盘中文件的元数据:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

完成OAuth 2.0流程后,应该将您重定向到http://localhost/oauth2callback ,除非本地计算机在该地址提供文件,否则可能会产生404 NOT FOUND错误。下一步将提供有关将用户重定向回您的应用程序时URI中返回的信息的更多详细信息。

步骤5:将授权代码交换为刷新和访问令牌

Web服务器收到授权代码后,可以将授权代码交换为访问令牌。

的PHP

要交换访问令牌的授权码,请使用authenticate方法:

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

您可以使用getAccessToken方法检索访问令牌:

$access_token = $client->getAccessToken();

Python

在您的回调页面上,使用google-auth库来验证授权服务器响应。然后,使用flow.fetch_token方法将响应中的授权代码交换为访问令牌:

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'],
    state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

# Store the credentials in the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    'scopes': credentials.scopes}

红宝石

要交换访问令牌的授权代码,请使用fetch_access_token!方法:

auth_client.code = auth_code
auth_client.fetch_access_token!

HTTP / REST

要为访问令牌交换授权码,请调用https://oauth2.googleapis.com/token端点并设置以下参数:

领域
client_id从API Console Credentials page获得的客户端ID。
client_secret从API Console Credentials page获得的客户端密钥。
code从初始请求返回的授权码。
grant_type根据OAuth 2.0规范中的定义,此字段的值必须设置为authorization_code
redirect_uri给定client_id的API Console Credentials page中为您的项目列出的重定向URI之一。

以下代码段显示了一个示例请求:

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

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

Google通过返回一个JSON对象来响应此请求,该对象包含一个短暂的访问令牌和一个刷新令牌。请注意,仅当您的应用程序在向Google授权服务器发出的初始请求中将access_type参数设置为offline ,才会返回刷新令牌。

响应包含以下字段:

领域
access_token您的应用程序发送的用于授权Google API请求的令牌。
expires_in访问令牌的剩余生存时间(以秒为单位)。
refresh_token可用于获取新的访问令牌的令牌。刷新令牌在用户撤销访问权限之前一直有效。同样,仅当您在对Google授权服务器的初始请求中将access_type参数设置为offline时,此字段才会出现在此响应中。
scope access_token授予的访问范围以空格分隔,区分大小写的字符串列表表示。
token_type返回的令牌类型。目前,此字段的值始终设置为Bearer

The following snippet shows a sample response:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

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 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 = 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 = $drive->files->listFiles(array())->getItems();

Python

After obtaining an access token, your application can use that token to authorize API requests on behalf of a given user account or service account. Use the user-specific authorization credentials to build a service object for the API that you want to call, and then use that object to make authorized API requests.

  1. Build a service object for the API that you want to call. You build a service object by calling the googleapiclient.discovery library's build method with the name and version of the API and the user credentials: For example, to call version 2 of the Drive API:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  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.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 if the scope(s) of access required by the API have been granted. To do this, include the access token in a request to the API by including either an access_token query parameter or an Authorization HTTP header Bearer value. 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 Files 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 Files 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
Host: www.googleapis.com
Authorization: Bearer access_token

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

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

PHP

To run this example:

  1. In the API 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. Install the Google API Client Library for PHP using Composer :
    composer require google/apiclient:^2.0
  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 __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfig('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 = new Google_Service_Drive($client);
  $files = $drive->files->listFiles(array())->getItems();
  echo json_encode($files);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

<?php
require_once __DIR__.'/vendor/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. It runs a web application at http://localhost:8080 that lets you test the OAuth 2.0 flow. If you go to that URL, you should see four links:

  • Test an API request: This link points to a page that tries to execute a sample API request. If necessary, it starts the authorization flow. If successful, the page displays the API response.
  • Test the auth flow directly: This link points to a page that tries to send the user through the authorization flow . The app requests permission to submit authorized API requests on the user's behalf.
  • Revoke current credentials: This link points to a page that revokes permissions that the user has already granted to the application.
  • Clear Flask session credentials: This link clears authorization credentials that are stored in the Flask session. This lets you see what would happen if a user who had already granted permission to your app tried to execute an API request in a new session. It also lets you see the API response your app would get if a user had revoked permissions granted to your app, and your app still tried to authorize a request with a revoked access token.
# -*- coding: utf-8 -*-

import os
import flask
import requests

import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery

# This variable specifies the name of a file that contains the OAuth 2.0
# information for this application, including its client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
API_SERVICE_NAME = 'drive'
API_VERSION = 'v2'

app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'


@app.route('/')
def index():
  return print_index_table()


@app.route('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

  drive = googleapiclient.discovery.build(
      API_SERVICE_NAME, API_VERSION, credentials=credentials)

  files = drive.files().list().execute()

  # Save credentials back to session in case access token was refreshed.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.jsonify(**files)


@app.route('/authorize')
def authorize():
  # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES)

  # The URI created here must exactly match one of the authorized redirect URIs
  # for the OAuth 2.0 client, which you configured in the API Console. If this
  # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
  # error.
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  authorization_url, state = flow.authorization_url(
      # Enable offline access so that you can refresh an access token without
      # re-prompting the user for permission. Recommended for web server apps.
      access_type='offline',
      # Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes='true')

  # Store the state so the callback can verify the auth server response.
  flask.session['state'] = state

  return flask.redirect(authorization_url)


@app.route('/oauth2callback')
def oauth2callback():
  # Specify the state when creating the flow in the callback so that it can
  # verified in the authorization server response.
  state = flask.session['state']

  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  # Use the authorization server's response to fetch the OAuth 2.0 tokens.
  authorization_response = flask.request.url
  flow.fetch_token(authorization_response=authorization_response)

  # Store credentials in the session.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  credentials = flow.credentials
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.redirect(flask.url_for('test_api_request'))


@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  revoke = requests.post('https://oauth2.googleapis.com/revoke',
      params={'token': credentials.token},
      headers = {'content-type': 'application/x-www-form-urlencoded'})

  status_code = getattr(revoke, 'status_code')
  if status_code == 200:
    return('Credentials successfully revoked.' + print_index_table())
  else:
    return('An error occurred.' + print_index_table())


@app.route('/clear')
def clear_credentials():
  if 'credentials' in flask.session:
    del flask.session['credentials']
  return ('Credentials have been cleared.<br><br>' +
          print_index_table())


def credentials_to_dict(credentials):
  return {'token': credentials.token,
          'refresh_token': credentials.refresh_token,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          'scopes': credentials.scopes}

def print_index_table():
  return ('<table>' +
          '<tr><td><a href="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' +
          '<td>Go directly to the authorization flow. If there are stored ' +
          '    credentials, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/revoke">Revoke current credentials</a></td>' +
          '<td>Revoke the access token associated with the current user ' +
          '    session. After revoking credentials, if you go to the test ' +
          '    page, you should see an <code>invalid_grant</code> error.' +
          '</td></tr>' +
          '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' +
          '<td>Clear the access token currently stored in the user session. ' +
          '    After clearing the token, if you <a href="/test">test the ' +
          '    API request</a> again, you should go back to the auth flow.' +
          '</td></tr></table>')


if __name__ == '__main__':
  # When running locally, disable OAuthlib's HTTPs verification.
  # ACTION ITEM for developers:
  #     When running in production *do not* leave this option enabled.
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

  # Specify a hostname and port that are set as a valid redirect URI
  # for your API project in the Google API Console.
  app.run('localhost', 8080, debug=True)

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 Python example uses the Flask framework and the Requests library to demonstrate the OAuth 2.0 web flow. We recommend using the Google API Client Library for Python for this flow. (The example in the Python tab does use the client library.)

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://oauth2.googleapis.com/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()

Redirect URI validation rules

Google applies the following validation rules to redirect URIs in order to help developers keep their applications secure. Your redirect URIs must adhere to these rules. See RFC 3986 section 3 for the definition of domain, host, path, query, scheme and userinfo, mentioned below.

Validation rules
Scheme

URIs must use the HTTPS scheme, not plain HTTP.

Host

Hosts cannot be raw IP addresses. Localhost IP addresses are exempted from this rule.

Domain
  • Host TLDs ( Top Level Domains ) must belong to the public suffix list .
  • Host domains cannot be “googleusercontent.com” .
  • URIs cannot contain URL shortener domains (eg goo.gl ) unless the app owns the domain. Furthermore, if an app that owns a shortener domain chooses to redirect to that domain, that redirect URI must either contain “/google-callback/” in its path or end with “/google-callback” .
  • Userinfo

    Redirect URIs cannot contain the userinfo subcomponent.

    Path

    Redirect URIs cannot contain a path traversal (also called directory backtracking), which is represented by an “/..” or “\..” or their URL encoding.

    Query

    Redirect URIs cannot contain open redirects .

    Characters URIs cannot contain certain characters including:
    • Wildcard characters ( '*' )
    • Non-printable ASCII characters
    • Invalid percent encodings (any percent encoding that does not follow URL-encoding form of a percent sign followed by two hexadecimal digits)
    • Null characters (an encoded NULL character, eg, %00 , %C0%80 )

    Incremental authorization

    In the OAuth 2.0 protocol, your app requests authorization to access resources, which are identified by scopes. It is considered a best user-experience practice to request authorization for resources at the time you need them. To enable that practice, Google's authorization server supports incremental authorization. This feature lets you request scopes as they are needed and, if the user grants permission for the new scope, returns an authorization code that may be exchanged for a token containing all scopes the user has granted the project.

    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 openid and profile scopes 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.

    To implement incremental authorization, you complete the normal flow for requesting an access token but make sure that the authorization request includes previously granted scopes. This approach allows your app to avoid having to manage multiple access tokens.

    The following rules apply to an access token obtained from an incremental authorization:

    • The token can be used to access resources corresponding to any of the scopes rolled into the new, combined authorization.
    • When you use the refresh token for the combined authorization to obtain an access token, the access token represents the combined authorization and can be used for any of the scope values included in the response.
    • The combined authorization includes all scopes that the user granted to the API project even if the grants were requested from different clients. For example, if a user granted access to one scope using an application's desktop client and then granted another scope to the same application via a mobile client, the combined authorization would include both scopes.
    • If you revoke a token that represents a combined authorization, access to all of that authorization's scopes on behalf of the associated user are revoked simultaneously.

    The language-specific code samples in Step 1: Set authorization parameters and the sample HTTP/REST redirect URL in Step 2: Redirect to Google's OAuth 2.0 server all use incremental authorization. The code samples below also show the code that you need to add to use incremental authorization.

    PHP

    $client->setIncludeGrantedScopes(true);

    Python

    In Python, set the include_granted_scopes keyword argument to true to ensure that an authorization request includes previously granted scopes. It is very possible that include_granted_scopes will not be the only keyword argument that you set, as shown in the example below.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        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?
      client_id=your_client_id&
      response_type=code&
      state=state_parameter_passthrough_value&
      scope=https%3A//www.googleapis.com/auth/drive.file&
      redirect_uri=https%3A//oauth2.example.com/code&
      prompt=consent&
      include_granted_scopes=true

    Refreshing an access token (offline access)

    Access tokens periodically expire and become invalid credentials for a related API request. 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.

    • If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
    • If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the user to Google's OAuth 2.0 server . In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.

    Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present. The default style of access is called online .

    Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.

    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

    In Python, set the access_type keyword argument to offline to ensure that you will be able to refresh the access token without having to re-prompt the user for permission. It is very possible that access_type will not be the only keyword argument that you set, as shown in the example below.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    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

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

    Fields
    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's value must be set to refresh_token .
    refresh_token The refresh token returned from the authorization code exchange.

    The following snippet shows a sample request:

    POST /token HTTP/1.1
    Host: oauth2.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,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
      "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 . See the Remove site or app access section of the Third-party sites & apps with access to your account support document for more information.

    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, removes an application, or the API resources required by an app have significantly changed. In other words, part of the removal process can include an API request to ensure the permissions previously granted to the application are removed.

    PHP

    To programmatically revoke a token, call revokeToken() :

    $client->revokeToken();

    Python

    To programmatically revoke a token, make a request to https://oauth2.googleapis.com/revoke that includes the token as a parameter and sets the Content-Type header:

    requests.post('https://oauth2.googleapis.com/revoke',
        params={'token': credentials.token},
        headers = {'content-type': 'application/x-www-form-urlencoded'})

    Ruby

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

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_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.

    HTTP/REST

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

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/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 HTTP status code of the response is 200 . For error conditions, an HTTP status code 400 is returned along with an error code.