Uso de OAuth 2.0 para aplicaciones de servidor web

Este documento explica cómo las aplicaciones de servidor web utilizan las bibliotecas cliente de API de Google o los puntos finales de Google OAuth 2.0 para implementar la autorización de OAuth 2.0 para acceder a las API de Google.

OAuth 2.0 permite a los usuarios compartir datos específicos con una aplicación mientras mantienen la privacidad de sus nombres de usuario, contraseñas y otra información. Por ejemplo, una aplicación puede usar OAuth 2.0 para obtener permiso de los usuarios para almacenar archivos en sus Google Drives.

Este flujo de OAuth 2.0 es específicamente para la autorización del usuario. Está diseñado para aplicaciones que pueden almacenar información confidencial y mantener el estado. Una aplicación de servidor web debidamente autorizada puede acceder a una API mientras el usuario interactúa con la aplicación o después de que el usuario ha abandonado la aplicación.

Las aplicaciones de servidor web con frecuencia también usan cuentas de servicio para autorizar solicitudes de API, particularmente cuando llaman a las API de Cloud para acceder a datos basados ​​en proyectos en lugar de datos específicos del usuario. Las aplicaciones de servidor web pueden utilizar cuentas de servicio junto con la autorización del usuario.

Bibliotecas cliente

Los ejemplos específicos del idioma de esta página utilizan las bibliotecas cliente de la API de Google para implementar la autorización OAuth 2.0. Para ejecutar los ejemplos de código, primero debe instalar la biblioteca cliente para su idioma.

Cuando usa una biblioteca de cliente de API de Google para manejar el flujo de OAuth 2.0 de su aplicación, la biblioteca de cliente realiza muchas acciones que la aplicación debería manejar por sí sola. Por ejemplo, determina cuándo la aplicación puede usar o actualizar los tokens de acceso almacenados, así como cuándo la aplicación debe volver a obtener el consentimiento. La biblioteca cliente también genera URL de redireccionamiento correctas y ayuda a implementar controladores de redireccionamiento que intercambian códigos de autorización por tokens de acceso.

Las bibliotecas cliente están disponibles para los siguientes idiomas:

Prerrequisitos

Habilite las API para su proyecto

Cualquier aplicación que llame a las API de Google debe habilitar esas API en el API Console.

Para habilitar una API para su proyecto:

  1. Open the API Library en el Google API Console.
  2. If prompted, select a project, or create a new one.
  3. El API Library enumera todas las API disponibles, agrupadas por familia de productos y popularidad. Si la API que desea habilitar no está visible en la lista, utilice la función de búsqueda para encontrarla o haga clic en Ver todo en la familia de productos a la que pertenece.
  4. Seleccione la API que desea habilitar y luego haga clic en el botón Habilitar .
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

Crear credenciales de autorización

Cualquier aplicación que use OAuth 2.0 para acceder a las API de Google debe tener credenciales de autorización que identifiquen la aplicación en el servidor OAuth 2.0 de Google. Los siguientes pasos explican cómo crear credenciales para su proyecto. Luego, sus aplicaciones pueden usar las credenciales para acceder a las API que haya habilitado para ese proyecto.

  1. Go to the Credentials page.
  2. Haga clic en Crear credenciales> ID de cliente de OAuth .
  3. Seleccione el tipo de aplicación de la aplicación web .
  4. Complete el formulario y haga clic en Crear . Las aplicaciones que utilizan lenguajes y marcos como PHP, Java, Python, Ruby y .NET deben especificar URI de redireccionamiento autorizados. Los URI de redireccionamiento son los puntos finales a los que el servidor OAuth 2.0 puede enviar respuestas. Estos puntos finales deben adherirse a las reglas de validación de Google .

    Para las pruebas, puede especificar URI que hagan referencia a la máquina local, como http://localhost:8080 . Teniendo esto en cuenta, tenga en cuenta que todos los ejemplos de este documento utilizan http://localhost:8080 como URI de redireccionamiento.

    Le recomendamos que diseñe los puntos finales de autenticación de su aplicación para que su aplicación no exponga los códigos de autorización a otros recursos de la página.

Después de crear sus credenciales, descargue el archivo client_secret.json del API Console. Almacene de forma segura el archivo en una ubicación a la que solo pueda acceder su aplicación.

Identificar ámbitos de acceso

Los ámbitos permiten que su aplicación solo solicite acceso a los recursos que necesita, al mismo tiempo que permite a los usuarios controlar la cantidad de acceso que otorgan a su aplicación. Por lo tanto, puede haber una relación inversa entre el número de alcances solicitados y la probabilidad de obtener el consentimiento del usuario.

Antes de comenzar a implementar la autorización OAuth 2.0, le recomendamos que identifique los ámbitos a los que su aplicación necesitará permiso para acceder.

También recomendamos que su aplicación solicite acceso a los ámbitos de autorización a través de un proceso de autorización incremental , en el que su aplicación solicita acceso a los datos del usuario en contexto. Esta práctica recomendada ayuda a los usuarios a comprender más fácilmente por qué su aplicación necesita el acceso que solicita.

El documento Ámbitos de la API de OAuth 2.0 contiene una lista completa de los ámbitos que puede utilizar para acceder a las API de Google.

Requisitos específicos del idioma

Para ejecutar cualquiera de los ejemplos de código de este documento, necesitará una cuenta de Google, acceso a Internet y un navegador web. Si está utilizando una de las bibliotecas cliente de API, consulte también los requisitos específicos del idioma a continuación.

PHP

Para ejecutar los ejemplos de código PHP en este documento, necesitará:

  • PHP 5.4 o superior con la interfaz de línea de comandos (CLI) y la extensión JSON instaladas.
  • La herramienta de gestión de dependencias de Composer .
  • La biblioteca cliente de las API de Google para PHP:

    php composer.phar require google/apiclient:^2.0

Pitón

Para ejecutar los ejemplos de código de Python en este documento, necesitará:

  • Python 2.6 o superior
  • La herramienta de gestión de paquetes pip .
  • Biblioteca cliente de las API de Google para Python:
    pip install --upgrade google-api-python-client
  • google-auth , google-auth-oauthlib y google-auth-httplib2 para la autorización del usuario.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • El marco de trabajo de la aplicación web Flask Python.
    pip install --upgrade flask
  • La biblioteca HTTP de requests .
    pip install --upgrade requests

Rubí

Para ejecutar los ejemplos de código Ruby en este documento, necesitará:

  • Ruby 2.2.2 o superior
  • La biblioteca cliente de las API de Google para Ruby:

    gem install google-api-client
  • El marco de la aplicación web Sinatra Ruby.

    gem install sinatra

HTTP / REST

No es necesario instalar ninguna biblioteca para poder llamar directamente a los puntos finales de OAuth 2.0.

Obtención de tokens de acceso de OAuth 2.0

Los siguientes pasos muestran cómo su aplicación interactúa con el servidor OAuth 2.0 de Google para obtener el consentimiento de un usuario para realizar una solicitud de API en nombre del usuario. Su aplicación debe tener ese consentimiento antes de poder ejecutar una solicitud de API de Google que requiere la autorización del usuario.

La siguiente lista resume rápidamente estos pasos:

  1. Su aplicación identifica los permisos que necesita.
  2. Su aplicación redirige al usuario a Google junto con la lista de permisos solicitados.
  3. El usuario decide si concede los permisos a su aplicación.
  4. Su aplicación descubre lo que decidió el usuario.
  5. Si el usuario otorgó los permisos solicitados, su aplicación recupera los tokens necesarios para realizar solicitudes de API en nombre del usuario.

Paso 1: configurar los parámetros de autorización

Su primer paso es crear la solicitud de autorización. Esa solicitud establece parámetros que identifican su aplicación y definen los permisos que se le pedirá al usuario que otorgue a su aplicación.

  • Si usa una biblioteca cliente de Google para la autenticación y autorización de OAuth 2.0, crea y configura un objeto que define estos parámetros.
  • Si llama directamente al punto final de Google OAuth 2.0, generará una URL y establecerá los parámetros en esa URL.

Las pestañas siguientes definen los parámetros de autorización admitidos para las aplicaciones del servidor web. Los ejemplos específicos del idioma también muestran cómo utilizar una biblioteca de cliente o una biblioteca de autorización para configurar un objeto que establece esos parámetros.

PHP

El siguiente fragmento de código crea un objeto Google_Client() , que define los parámetros en la solicitud de autorización.

Ese objeto usa información de su archivo client_secret.json para identificar su aplicación. (Consulte Creación de credenciales de autorización para obtener más información sobre ese archivo). El objeto también identifica los ámbitos a los que su aplicación solicita permiso para acceder y la URL al extremo de autenticación de su aplicación, que manejará la respuesta del servidor OAuth 2.0 de Google. Finalmente, el código establece los access_type opcionales access_type e include_granted_scopes .

Por ejemplo, este código solicita acceso sin conexión de solo lectura a Google Drive de un usuario:

$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

La solicitud especifica la siguiente información:

Parámetros
client_id Requerido

El ID de cliente de su aplicación. Puede encontrar este valor en el API Console Credentials page.

En PHP, llame a la función setAuthConfig para cargar credenciales de autorización desde un archivo client_secret.json .

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

Determina dónde el servidor de API redirige al usuario después de que el usuario completa el flujo de autorización. El valor debe coincidir exactamente con uno de los URI de redireccionamiento autorizados para el cliente OAuth 2.0, que configuró en el API Console Credentials page de su cliente. Si este valor no coincide con un URI de redireccionamiento autorizado para el client_id proporcionado, obtendrá un error redirect_uri_mismatch .

Tenga en cuenta que el esquema http o https , el caso y la barra inclinada (' / ') deben coincidir.

Para establecer este valor en PHP, llame a la función setRedirectUri . Tenga en cuenta que debe especificar un URI de redireccionamiento válido para el client_id proporcionado.

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

Una lista de ámbitos delimitada por espacios que identifica los recursos a los que su aplicación podría acceder en nombre del usuario. Estos valores informan la pantalla de consentimiento que Google muestra al usuario.

Los ámbitos permiten que su aplicación solo solicite acceso a los recursos que necesita, al mismo tiempo que permite a los usuarios controlar la cantidad de acceso que otorgan a su aplicación. Por tanto, existe una relación inversa entre el número de alcances solicitados y la probabilidad de obtener el consentimiento del usuario.

Para establecer este valor en PHP, llame a la función addScope :

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

Recomendamos que su aplicación solicite acceso a los ámbitos de autorización en contexto siempre que sea posible. Al solicitar acceso a los datos del usuario en contexto, a través de una autorización incremental , ayuda a los usuarios a comprender más fácilmente por qué su aplicación necesita el acceso que solicita.

access_type Recomendado

Indica si su aplicación puede actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Los valores de parámetro válidos están en online , que es el valor predeterminado, y offline .

Establezca el valor en offline de offline si su aplicación necesita actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Este es el método para actualizar los tokens de acceso que se describe más adelante en este documento. Este valor indica al servidor de autorización de Google que devuelva un token de actualización y un token de acceso la primera vez que su aplicación intercambia un código de autorización por tokens.

Para establecer este valor en PHP, llame a la función setAccessType :

$client->setAccessType('offline');
state Recomendado

Especifica cualquier valor de cadena que utiliza su aplicación para mantener el estado entre su solicitud de autorización y la respuesta del servidor de autorización. El servidor devuelve el valor exacto que envía como un par name=value en el componente de consulta de URL ( ? ) De redirect_uri después de que el usuario consiente o deniegue la solicitud de acceso de su aplicación.

Puede usar este parámetro para varios propósitos, como dirigir al usuario al recurso correcto en su aplicación, enviar nonces y mitigar la falsificación de solicitudes entre sitios. Dado que se puede adivinar su redirect_uri , el uso de un valor de state puede aumentar su seguridad de que una conexión entrante es el resultado de una solicitud de autenticación. Si genera una cadena aleatoria o codifica el hash de una cookie u otro valor que captura el estado del cliente, puede validar la respuesta para asegurarse adicionalmente de que la solicitud y la respuesta se originaron en el mismo navegador, brindando protección contra ataques como entre sitios. Solicitar falsificación. Consulte la documentación de OpenID Connect para ver un ejemplo de cómo crear y confirmar un token de state .

Para establecer este valor en PHP, llame a la función setState :

$client->setState($sample_passthrough_value);
include_granted_scopes Opcional

Permite que las aplicaciones utilicen una autorización incremental para solicitar acceso a ámbitos adicionales en contexto. Si establece el valor de este parámetro en true y se concede la solicitud de autorización, el nuevo token de acceso también cubrirá cualquier ámbito al que el usuario haya concedido previamente acceso a la aplicación. Consulte la sección de autorización incremental para ver ejemplos.

Para establecer este valor en PHP, llame a la función setIncludeGrantedScopes :

$client->setIncludeGrantedScopes(true);
login_hint Opcional

Si su aplicación sabe qué usuario está intentando autenticarse, puede utilizar este parámetro para proporcionar una pista al servidor de autenticación de Google. El servidor utiliza la sugerencia para simplificar el flujo de inicio de sesión, ya sea rellenando previamente el campo de correo electrónico en el formulario de inicio de sesión o seleccionando la sesión de inicio de sesión múltiple adecuada.

Establezca el valor del parámetro en una dirección de correo electrónico o un sub identificador, que es equivalente al ID de Google del usuario.

Para establecer este valor en PHP, llame a la función setLoginHint :

$client->setLoginHint('None');
prompt Opcional

Una lista de mensajes delimitados por espacios que distinguen entre mayúsculas y minúsculas para presentar al usuario. Si no especifica este parámetro, se le preguntará al usuario solo la primera vez que su proyecto solicite acceso. Consulte Solicitar un nuevo consentimiento para obtener más información.

Para establecer este valor en PHP, llame a la función setApprovalPrompt :

$client->setApprovalPrompt('consent');

Los posibles valores son:

none No muestre ninguna pantalla de autenticación o consentimiento. No debe especificarse con otros valores.
consent Solicitar al usuario su consentimiento.
select_account Solicitar al usuario que seleccione una cuenta.

Pitón

El siguiente fragmento de código usa el módulo google-auth-oauthlib.flow para construir la solicitud de autorización.

El código construye un objeto Flow , que identifica su aplicación utilizando información del archivo client_secret.json que descargó después de crear las credenciales de autorización . Ese objeto también identifica los ámbitos a los que su aplicación solicita permiso para acceder y la URL al extremo de autenticación de su aplicación, que manejará la respuesta del servidor OAuth 2.0 de Google. Finalmente, el código establece los access_type opcionales access_type e include_granted_scopes .

Por ejemplo, este código solicita acceso de solo lectura y sin conexión a Google Drive de un usuario:

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')

La solicitud especifica la siguiente información:

Parámetros
client_id Requerido

El ID de cliente de su aplicación. Puede encontrar este valor en el API Console Credentials page.

En Python, llame al método from_client_secrets_file para recuperar el ID de cliente de un archivo client_secret.json . (También puede usar el método from_client_config , que pasa la configuración del cliente como apareció originalmente en un archivo de secretos del cliente, pero no accede al archivo en sí).

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

Determina dónde el servidor de API redirige al usuario después de que el usuario completa el flujo de autorización. El valor debe coincidir exactamente con uno de los URI de redireccionamiento autorizados para el cliente OAuth 2.0, que configuró en el API Console Credentials page de su cliente. Si este valor no coincide con un URI de redireccionamiento autorizado para el client_id proporcionado, obtendrá un error redirect_uri_mismatch .

Tenga en cuenta que el esquema http o https , el caso y la barra inclinada (' / ') deben coincidir.

Para establecer este valor en Python, establezca la propiedad redirect_uri del objeto de flow :

flow.redirect_uri = 'https://oauth2.example.com/code'
scope Requerido

Una lista de ámbitos que identifican los recursos a los que su aplicación podría acceder en nombre del usuario. Estos valores informan la pantalla de consentimiento que Google muestra al usuario.

Los ámbitos permiten que su aplicación solo solicite acceso a los recursos que necesita, al mismo tiempo que permite a los usuarios controlar la cantidad de acceso que otorgan a su aplicación. Por tanto, existe una relación inversa entre el número de alcances solicitados y la probabilidad de obtener el consentimiento del usuario.

En Python, use el mismo método que usa para configurar el client_id para especificar la lista de alcances.

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

Recomendamos que su aplicación solicite acceso a los ámbitos de autorización en contexto siempre que sea posible. Al solicitar acceso a los datos del usuario en contexto, a través de una autorización incremental , ayuda a los usuarios a comprender más fácilmente por qué su aplicación necesita el acceso que solicita.

access_type Recomendado

Indica si su aplicación puede actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Los valores de parámetro válidos están en online , que es el valor predeterminado, y offline .

Establezca el valor en offline de offline si su aplicación necesita actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Este es el método para actualizar los tokens de acceso que se describe más adelante en este documento. Este valor indica al servidor de autorización de Google que devuelva un token de actualización y un token de acceso la primera vez que su aplicación intercambia un código de autorización por tokens.

En Python, configure el parámetro access_type especificando access_type como un argumento de palabra clave cuando llame al método flow.authorization_url :

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

Especifica cualquier valor de cadena que utiliza su aplicación para mantener el estado entre su solicitud de autorización y la respuesta del servidor de autorización. El servidor devuelve el valor exacto que envía como un par name=value en el componente de consulta de URL ( ? ) De redirect_uri después de que el usuario consiente o deniegue la solicitud de acceso de su aplicación.

Puede usar este parámetro para varios propósitos, como dirigir al usuario al recurso correcto en su aplicación, enviar nonces y mitigar la falsificación de solicitudes entre sitios. Dado que se puede adivinar su redirect_uri , el uso de un valor de state puede aumentar su seguridad de que una conexión entrante es el resultado de una solicitud de autenticación. Si genera una cadena aleatoria o codifica el hash de una cookie u otro valor que captura el estado del cliente, puede validar la respuesta para asegurarse adicionalmente de que la solicitud y la respuesta se originaron en el mismo navegador, brindando protección contra ataques como entre sitios. Solicitar falsificación. Consulte la documentación de OpenID Connect para ver un ejemplo de cómo crear y confirmar un token de state .

En Python, establecer el state de parámetros especificando state como un argumento de palabra clave cuando se llama al flow.authorization_url método:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes Opcional

Permite que las aplicaciones utilicen una autorización incremental para solicitar acceso a ámbitos adicionales en contexto. Si establece el valor de este parámetro en true y se concede la solicitud de autorización, el nuevo token de acceso también cubrirá cualquier ámbito al que el usuario haya concedido previamente acceso a la aplicación. Consulte la sección de autorización incremental para ver ejemplos.

En Python, configure el parámetro include_granted_scopes especificando include_granted_scopes como un argumento de palabra clave al llamar al método flow.authorization_url :

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint Opcional

Si su aplicación sabe qué usuario está intentando autenticarse, puede utilizar este parámetro para proporcionar una pista al servidor de autenticación de Google. El servidor utiliza la sugerencia para simplificar el flujo de inicio de sesión, ya sea rellenando previamente el campo de correo electrónico en el formulario de inicio de sesión o seleccionando la sesión de inicio de sesión múltiple adecuada.

Establezca el valor del parámetro en una dirección de correo electrónico o un sub identificador, que es equivalente al ID de Google del usuario.

En Python, configure el parámetro login_hint especificando login_hint como un argumento de palabra clave cuando llame al método flow.authorization_url :

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

Una lista de mensajes delimitados por espacios que distinguen entre mayúsculas y minúsculas para presentar al usuario. Si no especifica este parámetro, se le preguntará al usuario solo la primera vez que su proyecto solicite acceso. Consulte Solicitar un nuevo consentimiento para obtener más información.

En Python, configure el parámetro prompt especificando prompt como un argumento de palabra clave al llamar al método flow.authorization_url :

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

Los posibles valores son:

none No muestre ninguna pantalla de autenticación o consentimiento. No debe especificarse con otros valores.
consent Solicitar al usuario su consentimiento.
select_account Solicitar al usuario que seleccione una cuenta.

Rubí

Utilice el archivo client_secrets.json que creó para configurar un objeto de cliente en su aplicación. Cuando configura un objeto de cliente, especifica los ámbitos a los que debe acceder su aplicación, junto con la URL al extremo de autenticación de su aplicación, que manejará la respuesta del servidor OAuth 2.0.

Por ejemplo, este código solicita acceso de solo lectura y sin conexión a Google Drive de un usuario:

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
  }
)

Tu aplicación usa el objeto de cliente para realizar operaciones de OAuth 2.0, como generar URL de solicitud de autorización y aplicar tokens de acceso a solicitudes HTTP.

HTTP / REST

El extremo OAuth 2.0 de Google se encuentra en https://accounts.google.com/o/oauth2/v2/auth . Solo se puede acceder a este punto final a través de HTTPS. Se rechazan las conexiones HTTP simples.

El servidor de autorización de Google admite los siguientes parámetros de cadena de consulta para aplicaciones de servidor web:

Parámetros
client_id Requerido

El ID de cliente de su aplicación. Puede encontrar este valor en el API Console Credentials page.

redirect_uri Requerido

Determina dónde el servidor de API redirige al usuario después de que el usuario completa el flujo de autorización. El valor debe coincidir exactamente con uno de los URI de redireccionamiento autorizados para el cliente OAuth 2.0, que configuró en el API Console Credentials page de su cliente. Si este valor no coincide con un URI de redireccionamiento autorizado para el client_id proporcionado, obtendrá un error redirect_uri_mismatch .

Tenga en cuenta que el esquema http o https , el caso y la barra inclinada (' / ') deben coincidir.

response_type Requerido

Determina si el extremo de Google OAuth 2.0 devuelve un código de autorización.

Establezca el valor del parámetro en code para aplicaciones de servidor web.

scope Requerido

Una lista de ámbitos delimitada por espacios que identifica los recursos a los que su aplicación podría acceder en nombre del usuario. Estos valores informan la pantalla de consentimiento que Google muestra al usuario.

Los ámbitos permiten que su aplicación solo solicite acceso a los recursos que necesita, al mismo tiempo que permite a los usuarios controlar la cantidad de acceso que otorgan a su aplicación. Por tanto, existe una relación inversa entre el número de alcances solicitados y la probabilidad de obtener el consentimiento del usuario.

Recomendamos que su aplicación solicite acceso a los ámbitos de autorización en contexto siempre que sea posible. Al solicitar acceso a los datos del usuario en contexto, a través de una autorización incremental , ayuda a los usuarios a comprender más fácilmente por qué su aplicación necesita el acceso que solicita.

access_type Recomendado

Indica si su aplicación puede actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Los valores de parámetro válidos están en online , que es el valor predeterminado, y offline .

Establezca el valor en offline de offline si su aplicación necesita actualizar los tokens de acceso cuando el usuario no está presente en el navegador. Este es el método para actualizar los tokens de acceso que se describe más adelante en este documento. Este valor indica al servidor de autorización de Google que devuelva un token de actualización y un token de acceso la primera vez que su aplicación intercambia un código de autorización por tokens.

state Recomendado

Especifica cualquier valor de cadena que utiliza su aplicación para mantener el estado entre su solicitud de autorización y la respuesta del servidor de autorización. El servidor devuelve el valor exacto que envía como un par name=value en el componente de consulta de URL ( ? ) De redirect_uri después de que el usuario consiente o deniegue la solicitud de acceso de su aplicación.

Puede usar este parámetro para varios propósitos, como dirigir al usuario al recurso correcto en su aplicación, enviar nonces y mitigar la falsificación de solicitudes entre sitios. Dado que se puede adivinar su redirect_uri , el uso de un valor de state puede aumentar su seguridad de que una conexión entrante es el resultado de una solicitud de autenticación. Si genera una cadena aleatoria o codifica el hash de una cookie u otro valor que captura el estado del cliente, puede validar la respuesta para asegurarse adicionalmente de que la solicitud y la respuesta se originaron en el mismo navegador, brindando protección contra ataques como entre sitios. Solicitar falsificación. Consulte la documentación de OpenID Connect para ver un ejemplo de cómo crear y confirmar un token de state .

include_granted_scopes Opcional

Permite que las aplicaciones utilicen una autorización incremental para solicitar acceso a ámbitos adicionales en contexto. Si establece el valor de este parámetro en true y se concede la solicitud de autorización, el nuevo token de acceso también cubrirá cualquier ámbito al que el usuario haya concedido previamente acceso a la aplicación. Consulte la sección de autorización incremental para ver ejemplos.

login_hint Opcional

Si su aplicación sabe qué usuario está intentando autenticarse, puede utilizar este parámetro para proporcionar una pista al servidor de autenticación de Google. El servidor utiliza la sugerencia para simplificar el flujo de inicio de sesión, ya sea rellenando previamente el campo de correo electrónico en el formulario de inicio de sesión o seleccionando la sesión de inicio de sesión múltiple adecuada.

Establezca el valor del parámetro en una dirección de correo electrónico o un sub identificador, que es equivalente al ID de Google del usuario.

prompt Opcional

Una lista de mensajes delimitados por espacios que distingue entre mayúsculas y minúsculas para presentar al usuario. Si no especifica este parámetro, se le preguntará al usuario solo la primera vez que su proyecto solicite acceso. Consulte Solicitar un nuevo consentimiento para obtener más información.

Los posibles valores son:

none No muestre ninguna pantalla de autenticación o consentimiento. No debe especificarse con otros valores.
consent Solicitar al usuario su consentimiento.
select_account Solicitar al usuario que seleccione una cuenta.

Paso 2: Redirigir al servidor OAuth 2.0 de Google

Redirija al usuario al servidor OAuth 2.0 de Google para iniciar el proceso de autenticación y autorización. Normalmente, esto ocurre cuando su aplicación necesita acceder por primera vez a los datos del usuario. En el caso de la autorización incremental , este paso también ocurre cuando su aplicación primero necesita acceder a recursos adicionales a los que aún no tiene permiso para acceder.

PHP

  1. Genere una URL para solicitar acceso desde el servidor OAuth 2.0 de Google:
    $auth_url = $client->createAuthUrl();
  2. Redirigir al usuario a $auth_url :
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Pitón

Este ejemplo muestra cómo redirigir al usuario a la URL de autorización utilizando el marco de la aplicación web Flask:

return flask.redirect(authorization_url)

Rubí

  1. Genere una URL para solicitar acceso desde el servidor OAuth 2.0 de Google:
    auth_uri = auth_client.authorization_uri.to_s
  2. Redirigir al usuario a auth_uri .

HTTP / REST

Ejemplo de redireccionamiento al servidor de autorización de Google

A continuación se muestra un ejemplo de URL, con saltos de línea y espacios para facilitar la lectura.

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

Después de crear la URL de la solicitud, redirija al usuario a ella.

El servidor OAuth 2.0 de Google autentica al usuario y obtiene el consentimiento del usuario para que su aplicación acceda a los ámbitos solicitados. La respuesta se envía de vuelta a su aplicación utilizando la URL de redireccionamiento que especificó.

Paso 3: Google solicita el consentimiento del usuario

En este paso, el usuario decide si concede a su aplicación el acceso solicitado. En esta etapa, Google muestra una ventana de consentimiento que muestra el nombre de su aplicación y los servicios de la API de Google a los que solicita permiso para acceder con las credenciales de autorización del usuario y un resumen de los alcances de acceso que se otorgarán. El usuario puede dar su consentimiento para otorgar acceso a uno o más ámbitos solicitados por su aplicación o rechazar la solicitud.

Su aplicación no necesita hacer nada en esta etapa, ya que espera la respuesta del servidor OAuth 2.0 de Google que indica si se le otorgó acceso. Esa respuesta se explica en el siguiente paso.

Errores

Las solicitudes al extremo de autorización de OAuth 2.0 de Google pueden mostrar mensajes de error de cara al usuario en lugar de los flujos de autenticación y autorización esperados. Los códigos de error comunes y las soluciones sugeridas se enumeran a continuación.

admin_policy_enforced

La cuenta de Google no puede autorizar uno o más ámbitos solicitados debido a las políticas de su administrador de Google Workspace. Consulte el artículo de ayuda del administrador del espacio de trabajo de Google Controlar qué aplicaciones internas y de terceros acceden a los datos del espacio de trabajo de Google para obtener más información sobre cómo un administrador puede restringir el acceso a todos los ámbitos o ámbitos confidenciales y restringidos hasta que se otorgue acceso explícitamente a su ID de cliente de OAuth.

disallowed_useragent

El punto final de autorización se muestra dentro de un agente de usuario integrado no permitido por las políticas de OAuth 2.0 de Google.

Androide

Los desarrolladores de Android pueden encontrar este mensaje de error al abrir solicitudes de autorización en android.webkit.WebView . En su lugar, los desarrolladores deberían usar bibliotecas de Android como Google Sign-In para Android o AppAuth de OpenID Foundation para Android .

Los desarrolladores web pueden encontrar este error cuando una aplicación de Android abre un enlace web general en un agente de usuario integrado y un usuario navega al extremo de autorización OAuth 2.0 de Google desde su sitio. Los desarrolladores deben permitir que los enlaces generales se abran en el controlador de enlaces predeterminado del sistema operativo, que incluye tanto los controladores deenlaces de aplicaciones de Android como la aplicación de navegador predeterminada. La biblioteca de pestañas personalizadas de Android también es una opción compatible.

iOS

Los desarrolladores de iOS y macOS pueden encontrar este error al abrir solicitudes de autorización en WKWebView . En su lugar, los desarrolladores deberían utilizar bibliotecas de iOS como Google Sign-In para iOS o AppAuth de OpenID Foundation para iOS .

Los desarrolladores web pueden encontrar este error cuando una aplicación iOS o macOS abre un enlace web general en un agente de usuario integrado y un usuario navega al extremo de autorización OAuth 2.0 de Google desde su sitio. Los desarrolladores deben permitir que los enlaces generales se abran en el controlador de enlaces predeterminado del sistema operativo, que incluye tantolos controladores deenlaces universales como la aplicación de navegador predeterminada. La biblioteca SFSafariViewController también es una opción compatible.

org_internal

El ID de cliente de OAuth en la solicitud es parte de un proyecto que limita el acceso a las cuentas de Google en una organización de Google Cloud específica. Para obtener más información sobre esta opción de configuración, consulte la sección Tipo de usuario en el artículo de ayuda Configuración de la pantalla de consentimiento de OAuth.

redirect_uri_mismatch

El redirect_uri pasado en la solicitud de autorización no coincide con un URI de redireccionamiento autorizado para el ID de cliente de OAuth. Revise los URI de redireccionamiento autorizados en Google API Console Credentials page.

Paso 4: Manejar la respuesta del servidor OAuth 2.0

El servidor OAuth 2.0 responde a la solicitud de acceso de su aplicación mediante el uso de la URL especificada en la solicitud.

Si el usuario aprueba la solicitud de acceso, la respuesta contiene un código de autorización. Si el usuario no aprueba la solicitud, la respuesta contiene un mensaje de error. El código de autorización o el mensaje de error que se devuelve al servidor web aparece en la cadena de consulta, como se muestra a continuación:

Una respuesta de error:

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

Una respuesta de código de autorización:

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

Ejemplo de respuesta del servidor OAuth 2.0

Puede probar este flujo haciendo clic en la siguiente URL de muestra, que solicita acceso de solo lectura para ver los metadatos de los archivos en su Google Drive:

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

After completing the OAuth 2.0 flow, you should be redirected to http://localhost/oauth2callback , which will likely yield a 404 NOT FOUND error unless your local machine serves a file at that address. The next step provides more detail about the information returned in the URI when the user is redirected back to your application.

Step 5: Exchange authorization code for refresh and access tokens

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

On your callback page, use the google-auth library to verify the authorization server response. Then, use the flow.fetch_token method to exchange the authorization code in that response for an access 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}

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, call the https://oauth2.googleapis.com/token endpoint and set the following parameters:

Fields
client_id The client ID obtained from the API Console Credentials page.
client_secret The client secret obtained from the API Console Credentials page.
code The authorization code returned from the initial request.
grant_type As defined in the OAuth 2.0 specification , this field's value must be set to authorization_code .
redirect_uri One of the redirect URIs listed for your project in the API Console Credentials page for the given client_id .

The following snippet shows a sample request:

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 responds to this request by returning a JSON object that contains a short-lived access token and a refresh token. Note that the refresh token is only returned if your application set the access_type parameter to offline in the initial request to Google's authorization server .

The response contains the following fields:

Fields
access_token The token that your application sends to authorize a Google API request.
expires_in The remaining lifetime of the access token in seconds.
refresh_token A token that you can use to obtain a new access token. Refresh tokens are valid until the user revokes access. Again, this field is only present in this response if you set the access_type parameter to offline in the initial request to Google's authorization server.
scope The scopes of access granted by the access_token expressed as a list of space-delimited, case-sensitive strings.
token_type The type of token returned. At this time, this field's value is always set to Bearer .

The following snippet shows a sample response:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "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. Localhost URIs (including localhost IP address URIs) are exempt from this rule.

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.