OAuth 2.0 para aplicaciones web del cliente

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

En este documento, se explica cómo implementar la autorización OAuth 2.0 para acceder a las API de Google desde una aplicación web de JavaScript. OAuth 2.0 permite a los usuarios compartir datos específicos con una aplicación y, al mismo tiempo, mantener la privacidad de sus nombres de usuario, contraseñas y demás información. Por ejemplo, una aplicación puede usar OAuth 2.0 a fin de obtener permiso de los usuarios para almacenar archivos en sus unidades de Google Drive.

Este flujo de OAuth 2.0 se denomina flujo de concesión implícito. Está diseñado para aplicaciones que acceden a las API solo mientras el usuario está presente en la aplicación. Estas aplicaciones no pueden almacenar información confidencial.

En este flujo, tu app abre una URL de Google que usa parámetros de búsqueda para identificarla y el tipo de acceso a la API que requiere. Puedes abrir la URL en la ventana actual del navegador o en una ventana emergente. El usuario puede autenticarse con Google y otorgar los permisos solicitados. Luego, Google redirecciona al usuario de nuevo a tu app. El redireccionamiento incluye un token de acceso que tu app verifica y usa para realizar solicitudes a la API.

Requisitos previos

Habilita las API para tu proyecto.

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

Para habilitar una API en tu proyecto, sigue estos pasos:

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

Crea 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 al servidor OAuth 2.0 de Google. En los siguientes pasos, se explica cómo crear credenciales para tu proyecto. Luego, tus aplicaciones pueden usar las credenciales para acceder a las API que hayas habilitado en ese proyecto.

  1. Go to the Credentials page.
  2. Haz clic en Crear credenciales > ID de cliente de OAuth.
  3. Selecciona el tipo de aplicación Aplicación web.
  4. Completa el formulario. Las aplicaciones que usan JavaScript para realizar solicitudes autorizadas de la API de Google deben especificar los orígenes JavaScript autorizados. Los orígenes identifican los dominios desde los cuales tu aplicación puede enviar solicitudes al servidor de OAuth 2.0. Estos orígenes deben cumplir con las reglas de validación de Google.

Identifica permisos de acceso

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

Antes de comenzar a implementar la autorización OAuth 2.0, te recomendamos que identifiques los permisos para los que tu app necesitará permiso de acceso.

El documento Alcances de la API de OAuth 2.0 contiene una lista completa de los permisos que puedes usar para acceder a las API de Google.

Obtén tokens de acceso de OAuth 2.0

En los siguientes pasos, se muestra cómo tu aplicación interactúa con el servidor de OAuth 2.0 de Google a fin de obtener el consentimiento de un usuario para realizar una solicitud a la API en nombre del usuario. Tu aplicación debe tener ese consentimiento antes de poder ejecutar una solicitud a la API de Google que requiera la autorización del usuario.

Paso 1: Configura el objeto de cliente

Si usas la biblioteca cliente de las API de Google para JavaScript a fin de controlar el flujo de OAuth 2.0, el primer paso es configurar los objetos gapi.auth2 y gapi.client. Estos objetos permiten que tu aplicación obtenga la autorización del usuario y realice solicitudes autorizadas a la API.

El objeto de cliente identifica los permisos a los que la aplicación solicita permiso de acceso. Estos valores informan la pantalla de consentimiento que Google le muestra al usuario.

Biblioteca cliente de JS

La biblioteca cliente de JavaScript simplifica varios aspectos del proceso de autorización:

  1. Crea la URL de redireccionamiento del servidor de autorización de Google y proporciona un método para dirigir al usuario a esa URL.
  2. Maneja el redireccionamiento desde ese servidor a tu aplicación.
  3. Valida el token de acceso que muestra el servidor de autorización.
  4. Almacena el token de acceso que el servidor de autorización envía a tu aplicación y lo recupera cuando esta realiza llamadas a la API autorizadas posteriormente.

El fragmento de código que aparece a continuación es un extracto del ejemplo completo que se muestra más adelante en este documento. Este código inicializa el objeto gapi.client, que tu aplicación usaría posteriormente para realizar llamadas a la API. Cuando se crea ese objeto, también se inicializa el objeto gapi.auth2, que tu aplicación usa para verificar y supervisar el estado de autorización del usuario.

La llamada a gapi.client.init especifica los siguientes campos:

  • Los valores apiKey y clientId especifican las credenciales de autorización de la aplicación. Como se explica en la sección Crea credenciales de autorización, estos valores se pueden obtener en API Console. Ten en cuenta que clientId es obligatorio si tu aplicación realiza solicitudes a la API autorizadas. Las aplicaciones que solo realizan solicitudes no autorizadas pueden especificar una clave de API.
  • En el campo scope, se especifica una lista delimitada por espacios de permisos de acceso que corresponden a los recursos a los que tu aplicación podría acceder en nombre del usuario. Estos valores informan la pantalla de consentimiento que Google le muestra al usuario.

    Recomendamos que tu aplicación solicite acceso a los permisos de autorización en contexto siempre que sea posible. Cuando solicitas acceso a los datos del usuario en contexto, mediante la autorización incremental, ayudas a los usuarios a comprender más fácilmente por qué tu aplicación necesita el acceso que solicita.

  • El campo discoveryDocs identifica una lista de los documentos de descubrimiento de API que usa tu aplicación. En un documento de descubrimiento, se describe la superficie de una API, incluidos sus esquemas de recursos, y la biblioteca cliente de JavaScript usa esa información para generar métodos que las aplicaciones pueden usar. En este ejemplo, el código recupera el documento de descubrimiento para la versión 3 de la API de Google Drive.

Una vez que se completa la llamada a gapi.client.init, el código establece la variable GoogleAuth para identificar el objeto de Google Auth. Por último, el código establece un objeto de escucha que llama a una función cuando cambia el estado de acceso del usuario. (Esa función no está definida en el fragmento).

var GoogleAuth; // Google Auth object.
function initClient() {
  gapi.client.init({
      'apiKey': 'YOUR_API_KEY',
      'clientId': 'YOUR_CLIENT_ID',
      'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
      'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest']
  }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);
  });
}

Extremos de OAuth 2.0

Si accedes de forma directa a los extremos de OAuth 2.0, puedes continuar con el siguiente paso.

Paso 2: Redireccionar al servidor de OAuth 2.0 de Google

Si quieres solicitar permiso para acceder a los datos de un usuario, redirecciona al usuario al servidor OAuth 2.0 de Google.

Biblioteca cliente de JS

Llama al método GoogleAuth.signIn() para dirigir al usuario al servidor de autorización de Google.

GoogleAuth.signIn();

En la práctica, tu aplicación puede establecer un valor booleano para determinar si debe llamar al método signIn() antes de intentar hacer una llamada a la API.

El fragmento de código que aparece a continuación demuestra cómo iniciarías el flujo de autorización del usuario. Ten en cuenta los siguientes puntos sobre el fragmento:

  • El objeto GoogleAuth al que se hace referencia en el código es el mismo que el de la variable global definida en el fragmento de código del paso 1.

  • La función updateSigninStatus es un objeto de escucha que escucha los cambios en el estado de autorización del usuario. Su función como objeto de escucha también se definió en el fragmento de código del paso 1:
    GoogleAuth.isSignedIn.listen(updateSigninStatus);
  • El fragmento define dos variables globales adicionales:

    • isAuthorized es una variable booleana que indica si el usuario ya accedió. Este valor se puede establecer cuando la app se carga y se actualiza si el usuario accede a la app o sale de ella.

      En este fragmento, la función sendAuthorizedApiRequest verifica el valor de la variable para determinar si la app debe intentar realizar una solicitud a la API que requiera autorización o solicitarle al usuario que autorice la app.

    • currentApiRequest es un objeto que almacena detalles sobre la última solicitud a la API que intentó realizar el usuario. El valor del objeto se establece cuando la app llama a la función sendAuthorizedApiRequest.

      Si el usuario autorizó la app, la solicitud se ejecuta de inmediato. De lo contrario, la función redirecciona al usuario para que acceda. Después de que el usuario accede, la función updateSignInStatus llama a sendAuthorizedApiRequest y pasa la misma solicitud que se intentó antes de que se iniciara el flujo de autorización.

var isAuthorized;
var currentApiRequest;

/**
 * Store the request details. Then check to determine whether the user
 * has authorized the application.
 *   - If the user has granted access, make the API request.
 *   - If the user has not granted access, initiate the sign-in flow.
 */
function sendAuthorizedApiRequest(requestDetails) {
  currentApiRequest = requestDetails;
  if (isAuthorized) {
    // Make API request
    // gapi.client.request(requestDetails)

    // Reset currentApiRequest variable.
    currentApiRequest = {};
  } else {
    GoogleAuth.signIn();
  }
}

/**
 * Listener called when user completes auth flow. If the currentApiRequest
 * variable is set, then the user was prompted to authorize the application
 * before the request executed. In that case, proceed with that API request.
 */
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    isAuthorized = true;
    if (currentApiRequest) {
      sendAuthorizedApiRequest(currentApiRequest);
    }
  } else {
    isAuthorized = false;
  }
}

Extremos de OAuth 2.0

Genera una URL para solicitar acceso al extremo de OAuth 2.0 de Google en https://accounts.google.com/o/oauth2/v2/auth. Se puede acceder a este extremo a través de HTTPS; se rechazan las conexiones HTTP simples.

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

Parámetros
client_id Obligatorio

El ID de cliente para tu aplicación. Puedes encontrar este valor en la Credentials pagede API Console.

redirect_uri Obligatorio

Determina dónde el servidor de la API redirecciona al usuario después de que completa el flujo de autorización. El valor debe coincidir exactamente con uno de los URI de redireccionamiento autorizados para el cliente de OAuth 2.0, que configuraste en el Credentials pagede tu cliente API Console. Si este valor no coincide con un URI de redireccionamiento autorizado para la client_id proporcionada, se mostrará un error redirect_uri_mismatch.

Ten en cuenta que todos los esquemas, mayúsculas y minúsculas y la barra final ("/") de http o https deben coincidir.

response_type Obligatorio

Las aplicaciones de JavaScript deben establecer el valor del parámetro en token. Este valor le indica al servidor de autorización de Google que muestre el token de acceso como un par name=value en el identificador de fragmento del URI (#) al que se redirecciona al usuario después de completar el proceso de autorización.

scope Obligatorio

Una lista delimitada por espacios de los alcances que identifican los recursos a los que tu aplicación podría acceder en nombre del usuario. Estos valores informan la pantalla de consentimiento que Google le muestra al usuario.

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

Recomendamos que tu aplicación solicite acceso a los permisos de autorización en contexto cuando sea posible. Cuando solicitas acceso a los datos del usuario en contexto, mediante la autorización incremental, ayudas a los usuarios a comprender más fácilmente por qué tu aplicación necesita el acceso que solicita.

state Se recomienda

Especifica cualquier valor de string que use tu aplicación para mantener el estado entre tu solicitud de autorización y la respuesta del servidor de autorización. El servidor muestra el valor exacto que envías como un par name=value en el identificador de fragmento de URL (#) de redirect_uri después de que el usuario consiente o rechaza la solicitud de acceso de tu aplicación.

Puedes usar este parámetro para varios propósitos, como dirigir al usuario al recurso correcto en tu aplicación, enviar nonces y mitigar la falsificación de solicitudes entre sitios. Como se puede adivinar tu redirect_uri, el uso de un valor state puede aumentar la seguridad de que una conexión entrante es el resultado de una solicitud de autenticación. Si generas una string aleatoria o codificas el hash de una cookie o, también, otro valor que captura el estado del cliente, puedes validar la respuesta para asegurarte de que la solicitud y la respuesta se originen en el mismo navegador, lo que proporciona protección contra ataques, como la falsificación de solicitudes entre sitios. Consulta la documentación de OpenID Connect para ver un ejemplo de cómo crear y confirmar un token de state.

include_granted_scopes Optional

Permite que las aplicaciones usen la autorización incremental para solicitar acceso a permisos adicionales en contexto. Si configuras el valor de este parámetro como true y se otorga la solicitud de autorización, el nuevo token de acceso también cubrirá cualquier permiso al que el usuario le haya otorgado acceso a la aplicación anteriormente. Consulta la sección sobre autorización incremental para ver ejemplos.

login_hint Optional

Si tu aplicación sabe qué usuario intenta autenticarse, puede usar este parámetro para proporcionar una sugerencia al servidor de autenticación de Google. El servidor usa la sugerencia para simplificar el flujo de acceso, ya sea completando el campo de correo electrónico en el formulario de acceso o seleccionando la sesión de acceso múltiple adecuada.

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

prompt Optional

Una lista de solicitudes delimitadas por espacios y con mayúsculas de minúsculas para presentar al usuario. Si no especificas este parámetro, se le solicitará al usuario solo la primera vez que tu proyecto solicite acceso. Consulta Cómo solicitar la nueva autorización para obtener más información.

Los valores posibles son:

none No muestra ninguna pantalla de autenticación o consentimiento. No se debe especificar con otros valores.
consent Solicita el consentimiento del usuario.
select_account Pídele al usuario que seleccione una cuenta.

Redireccionamiento de muestra 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&
 include_granted_scopes=true&
 response_type=token&
 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, redirecciona al usuario a ella.

Código de muestra de JavaScript

En el siguiente fragmento de código JavaScript, se muestra cómo iniciar el flujo de autorización en JavaScript sin usar la biblioteca cliente de las API de Google para JavaScript. Dado que este extremo de OAuth 2.0 no admite el uso compartido de recursos multiorigen (CORS), el fragmento crea un formulario que abre la solicitud a ese extremo.

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

Paso 3: Google solicita el consentimiento del usuario

En este paso, el usuario decide si concede a tu aplicación el acceso solicitado. En esta etapa, Google muestra una ventana de consentimiento en la que aparece el nombre de tu 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 permisos de acceso que se otorgarán. Luego, el usuario puede aceptar otorgar acceso a uno o más alcances solicitados por la aplicación o rechazar la solicitud.

Tu aplicación no necesita hacer nada en esta etapa mientras espera la respuesta del servidor de OAuth 2.0 de Google que indica si se 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 orientados al usuario en lugar de los flujos de autenticación y autorización esperados. A continuación, se indican los códigos de error comunes y las resoluciones sugeridas.

admin_policy_enforced

La Cuenta de Google no puede autorizar uno o más permisos solicitados debido a las políticas de su administrador de Google Workspace. Consulta el artículo de ayuda para administradores de Google Workspace Controla qué apps internas y de terceros acceden a los datos de Google Workspace para obtener más información sobre cómo un administrador puede restringir el acceso a todos los permisos o a los permisos sensibles y restringidos hasta que se otorgue acceso de forma explícita a tu ID de cliente de OAuth.

disallowed_useragent

El extremo de autorización se muestra dentro de un usuario-agente incorporado que no está permitido en las Políticas de OAuth 2.0 de Google.

Android

Es posible que los desarrolladores de Android vean este mensaje de error cuando abran solicitudes de autorización en android.webkit.WebView. En su lugar, los desarrolladores deben usar bibliotecas de Android, como Acceso con Google para Android o AppAuth para Android de OpenID Foundation.

Los desarrolladores web pueden encontrar este error cuando una app para Android abre un vínculo web general en un usuario-agente incorporado y un usuario navega al extremo de autorización de OAuth 2.0 de Google desde tu sitio. Los desarrolladores deben permitir que se abran vínculos generales en el controlador de vínculos predeterminado del sistema operativo, que incluye los controladores de Android App Links o la app de navegador predeterminada. También se admite la biblioteca de pestañas personalizadas de Android.

iOS

Los desarrolladores de iOS y macOS pueden encontrar este error cuando abren solicitudes de autorización en WKWebView. En su lugar, los desarrolladores deben usar bibliotecas para iOS, como el Acceso con Google para iOS o AppAuth para iOS de OpenID Foundation.

Los desarrolladores web pueden encontrar este error cuando una app para iOS o macOS abre un vínculo web general en un usuario-agente incorporado y un usuario navega al extremo de autorización de OAuth 2.0 de Google desde tu sitio. Los desarrolladores deben permitir que se abran vínculos generales en el controlador de vínculos predeterminado del sistema operativo, que incluye los controladores de Universal Links o la app de navegador predeterminada. La biblioteca SFSafariViewController también es una opción compatible.

org_internal

El ID de cliente de OAuth de la solicitud forma 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, consulta la sección Tipo de usuario en el artículo de ayuda Configura tu pantalla de consentimiento de OAuth.

invalid_client

El origen desde el cual se realizó la solicitud no está autorizado para este cliente. Consulta origin_mismatch.

invalid_grant

Cuando usas la autorización incremental, es posible que el token haya caducado o se haya invalidado. Vuelve a autenticar al usuario y pídele su consentimiento para obtener nuevos tokens. Si continúas viendo este error, asegúrate de que tu aplicación se haya configurado correctamente y de que estés usando los tokens y parámetros correctos en tu solicitud. De lo contrario, es posible que la cuenta de usuario se haya borrado o inhabilitado.

origin_mismatch

Es posible que el esquema, el dominio o el puerto del JavaScript que originó la solicitud de autorización no coincidan con un URI de origen de JavaScript autorizado y registrado para el ID de cliente de OAuth. Revisa los orígenes autorizados de JavaScript en el Google API Console Credentials page.

redirect_uri_mismatch

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

Es posible que el esquema, el dominio o el puerto del JavaScript que originó la solicitud de autorización no coincidan con un URI de origen de JavaScript autorizado y registrado para el ID de cliente de OAuth. Revisa los orígenes autorizados de JavaScript en el archivo Google API Console Credentials page.

El parámetro redirect_uri puede referirse al flujo de OAuth fuera de banda (OOB) que dejó de estar disponible y ya no es compatible. Consulta la guía de migración para actualizar tu integración.

Paso 4: Controla la respuesta del servidor de OAuth 2.0

Biblioteca cliente de JS

La biblioteca cliente de JavaScript maneja la respuesta del servidor de autorización de Google. Si configuras un objeto de escucha para supervisar los cambios en el estado de acceso del usuario actual, se llama a esa función cuando el usuario otorga el acceso solicitado a la aplicación.

Extremos de OAuth 2.0

El servidor de OAuth 2.0 envía una respuesta al redirect_uri especificado en tu solicitud de token de acceso.

Si el usuario aprueba la solicitud, la respuesta contendrá un token de acceso. Si el usuario no aprueba la solicitud, la respuesta contendrá un mensaje de error. El token de acceso o el mensaje de error se muestran en el fragmento de hash del URI de redireccionamiento, como se muestra a continuación:

  • Una respuesta de token de acceso:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    Además del parámetro access_token, la string de fragmento también contiene el parámetro token_type, que siempre se establece en Bearer, y el parámetro expires_in, que especifica la vida útil del token, en segundos. Si se especificó el parámetro state en la solicitud de token de acceso, su valor también se incluye en la respuesta.

  • Una respuesta de error:
    https://oauth2.example.com/callback#error=access_denied

Ejemplo de respuesta del servidor OAuth 2.0

Para probar este flujo, haz clic en la siguiente URL de muestra, que solicita acceso de solo lectura a fin de ver los metadatos de los archivos en tu Google Drive:

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

Después de completar el flujo de OAuth 2.0, se te redireccionará a http://localhost/oauth2callback. Esa URL generará un error 404 NOT FOUND, a menos que tu máquina local entregue un archivo en esa dirección. En el siguiente paso, se proporcionan más detalles sobre la información que se muestra en el URI cuando se redirecciona al usuario a tu aplicación.

Llamar a las API de Google

Biblioteca cliente de JS

Una vez que tu aplicación obtenga un token de acceso, puedes usar la biblioteca cliente de JavaScript para realizar solicitudes a la API en nombre del usuario. La biblioteca cliente administra el token de acceso por ti y no necesitas hacer nada especial para enviarlo en la solicitud.

La biblioteca cliente admite dos métodos para llamar a los métodos de la API. Si cargaste un documento de descubrimiento, la API definirá las funciones específicas del método por ti. También puedes usar la función gapi.client.request para llamar a un método de API. En los dos fragmentos de código siguientes, se demuestran estas opciones para el método about.get de la API de Drive.

// Example 1: Use method-specific function
var request = gapi.client.drive.about.get({'fields': 'user'});

// Execute the API request.
request.execute(function(response) {
  console.log(response);
});


// Example 2: Use gapi.client.request(args) function
var request = gapi.client.request({
  'method': 'GET',
  'path': '/drive/v3/about',
  'params': {'fields': 'user'}
});
// Execute the API request.
request.execute(function(response) {
  console.log(response);
});

Extremos de OAuth 2.0

Una vez que tu aplicación obtenga un token de acceso, puedes usarlo para realizar llamadas a una API de Google en nombre de una cuenta de usuario determinada si se otorgaron los permisos de acceso que requiere la API. Para ello, incluye el token de acceso en una solicitud a la API mediante la inclusión de un parámetro de consulta access_token o un valor de encabezado HTTP Bearer de Authorization. Siempre que sea posible, es preferible usar el encabezado HTTP, ya que las strings de consulta suelen ser visibles en los registros del servidor. En la mayoría de los casos, puedes usar una biblioteca cliente para configurar tus llamadas a las API de Google (por ejemplo, cuando llamas a la API de archivos de Drive).

Puedes probar todas las API de Google y ver sus permisos en OAuth 2.0 Playground.

Ejemplos de HTTP GET

Una llamada al extremo drive.files (la API de archivos de Drive) que usa el encabezado HTTP Authorization: Bearer podría verse de la siguiente manera. Ten en cuenta que debes especificar tu propio token de acceso:

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

Esta es una llamada a la misma API para el usuario autenticado que usa el parámetro de string de consulta access_token:

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

curl ejemplos

Puedes probar estos comandos con la aplicación de línea de comandos de curl. A continuación, te mostramos un ejemplo en el que se usa la opción de encabezado HTTP (opción preferida):

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

Como alternativa, la opción de parámetro de string de consulta:

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

Código de muestra de JavaScript

En el siguiente fragmento de código, se muestra cómo usar CORS (uso compartido de recursos entre dominios) para enviar una solicitud a una API de Google. En este ejemplo, no se usa la biblioteca cliente de las API de Google para JavaScript. Sin embargo, incluso si no usas la biblioteca cliente, es posible que la guía de compatibilidad con CORS de la documentación de esa biblioteca te ayude a comprender mejor estas solicitudes.

En este fragmento de código, la variable access_token representa el token que obtuviste para realizar solicitudes a la API en nombre del usuario autorizado. En el ejemplo completo, se muestra cómo almacenar ese token en el almacenamiento local del navegador y recuperarlo cuando realizas una solicitud a la API.

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/drive/v3/about?fields=user&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

Ejemplo completo

Biblioteca cliente de JS

Ejemplo de código de muestra

En esta sección, se incluye una demostración funcional de la muestra de código que aparece a continuación para demostrar cómo se comporta el código en una app real. Después de autorizar la app, aparecerá entre las apps conectadas a tu Cuenta de Google. La aplicación se llama OAuth 2.0 Demo for Google API Docs (Demostración de OAuth 2.0 para los documentos de la API de Google) Del mismo modo, si revocas el acceso y actualizas la página, la app dejará de aparecer.

Ten en cuenta que esta app solicita acceso al permiso https://www.googleapis.com/auth/drive.metadata.readonly. El acceso se solicita solo para demostrar cómo iniciar el flujo de OAuth 2.0 en una aplicación de JavaScript. Esta app no realiza ninguna solicitud a la API.

Código de muestra de JavaScript

Como se mostró anteriormente, este ejemplo de código es para una página (una app) que carga la biblioteca cliente de las API de Google para JavaScript y que inicia el flujo de OAuth 2.0. La página muestra:

  • Un botón que permite al usuario acceder a la app. Si el usuario no autorizó la app anteriormente, esta inicia el flujo de OAuth 2.0.
  • Dos botones que permiten al usuario salir de la app o revocar el acceso otorgado anteriormente. Si sales de una app, no revocaste el acceso otorgado a ella. Deberás volver a acceder para que la app pueda realizar otras solicitudes autorizadas en tu nombre, pero no tendrás que volver a hacerlo la próxima vez que uses la app. Sin embargo, si revocas el acceso, deberás volver a hacerlo.

También puedes revocar el acceso a la app a través de la página Permisos de tu Cuenta de Google. La aplicación aparece como Demostración de OAuth 2.0 para documentos de la API de Google.

<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

Extremos de OAuth 2.0

En esta muestra de código, se muestra cómo completar el flujo de OAuth 2.0 en JavaScript sin usar la biblioteca cliente de las API de Google para JavaScript. El código es para una página HTML que muestra un botón a fin de probar una solicitud a la API. Si haces clic en el botón, el código verifica si la página almacenó un token de acceso a la API en el almacenamiento local de tu navegador. Si es así, ejecuta la solicitud a la API. De lo contrario, inicia el flujo de OAuth 2.0.

Para el flujo de OAuth 2.0, la página sigue estos pasos:

  1. Dirige al usuario al servidor de OAuth 2.0 de Google, que solicita acceso al permiso https://www.googleapis.com/auth/drive.metadata.readonly.
  2. Después de otorgar (o denegar) el acceso a uno o más alcances solicitados, se redirecciona al usuario a la página original, que analiza el token de acceso de la string del identificador de fragmento.
  3. La página usa el token de acceso para realizar la solicitud de la API de muestra.

    La solicitud a la API llama al método about.get de la API de Drive para recuperar información sobre la cuenta de Google Drive del usuario autorizado.

  4. Si la solicitud se ejecuta correctamente, la respuesta de la API se registra en la consola de depuración del navegador.

Puedes revocar el acceso a la app a través de la página Permisos de tu Cuenta de Google. La aplicación aparecerá como Demostración de OAuth 2.0 para documentos de la API de Google.

Si quieres ejecutar este código de forma local, debes establecer valores para las variables YOUR_CLIENT_ID y YOUR_REDIRECT_URI que correspondan a tus credenciales de autorización. La variable YOUR_REDIRECT_URI debe establecerse en la misma URL en la que se entrega la página. El valor debe coincidir exactamente con uno de los URI de redireccionamiento autorizados para el cliente de OAuth 2.0, que configuraste en el API Console Credentials page. Si este valor no coincide con un URI autorizado, recibirás un error redirect_uri_mismatch. Tu proyecto también debe tener habilitada la API adecuada para esta solicitud.

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

Reglas de validación del origen de JavaScript

Google aplica las siguientes reglas de validación a los orígenes de JavaScript para ayudar a los desarrolladores a mantener sus aplicaciones seguras. Tus orígenes de JavaScript deben cumplir con estas reglas. Consulta la sección 3 de RFC 3986 para obtener la definición de dominio, host y esquema, que se menciona a continuación.

Reglas de validación
Esquema

Los orígenes de JavaScript deben usar el esquema HTTPS, no HTTP sin formato. Los URI de hosthost (incluidos los URI de direcciones IP de localhost) están exentos de esta regla.

Host

Los hosts no pueden ser direcciones IP sin procesar. Las direcciones IP de LocalHost están exentas de esta regla.

Dominio
  • Los TLD del host (Dominios de nivel superior) deben pertenecer a la lista de sufijos públicos.
  • Los dominios del host no pueden ser “googleusercontent.com”.
  • Los orígenes de JavaScript no pueden contener dominios de acortamiento de URL (p.ej., goo.gl), a menos que la app sea propietaria del dominio.
  • Información del usuario

    Los orígenes de JavaScript no pueden contener el subcomponente userinfo.

    Ruta de acceso

    Los orígenes de JavaScript no pueden contener el componente de la ruta de acceso.

    Búsqueda

    Los orígenes de JavaScript no pueden contener el componente de la consulta.

    Fragmento

    Los orígenes de JavaScript no pueden contener el componente del fragmento.

    Caracteres Los orígenes de JavaScript no pueden contener ciertos caracteres, incluidos los siguientes:
    • Caracteres comodín ('*')
    • Caracteres ASCII no imprimibles
    • Codificaciones de porcentaje no válidas (cualquier codificación de porcentaje que no siga la forma de codificación URL de un signo de porcentaje seguido de dos dígitos hexadecimales)
    • Caracteres nulos (un carácter NULL codificado, p.ej., %00, %C0%80)

    Autorización incremental

    En el protocolo OAuth 2.0, tu app solicita autorización para acceder a los recursos, que se identifican con permisos. Se considera una práctica recomendada para solicitar la autorización de los recursos en el momento en que los necesitas. Para habilitar esa práctica, el servidor de autorización de Google admite la autorización incremental. Esta función te permite solicitar permisos a medida que se necesiten y, si el usuario otorga permiso para el permiso nuevo, mostrará un código de autorización que se puede intercambiar por un token que contenga todos los permisos que el usuario haya otorgado al proyecto.

    Por ejemplo, una app que permite que las personas tomen muestras de música y creen mezclas podría necesitar muy pocos recursos al acceder, tal vez solo el nombre de la persona que accede. Sin embargo, para guardar una combinación completa, se requiere acceso a su cuenta de Google Drive. A la mayoría de las personas les resultaría natural si solo se les pidiera acceso a su Google Drive en el momento en que la app realmente lo necesitaba.

    En este caso, en el momento del acceso, la app puede solicitar los permisos openid y profile para realizar el acceso básico y, luego, solicitar el permiso https://www.googleapis.com/auth/drive.file en el momento de la primera solicitud a fin de guardar una combinación.

    Las siguientes reglas se aplican a un token de acceso obtenido de una autorización incremental:

    • El token se puede usar para acceder a los recursos correspondientes a cualquiera de los permisos implementados en la nueva autorización combinada.
    • Cuando usas el token de actualización para que la autorización combinada obtenga un token de acceso, este representa la autorización combinada y se puede usar para cualquiera de los valores de scope incluidos en la respuesta.
    • La autorización combinada incluye todos los permisos que el usuario otorgó al proyecto de API, incluso si se otorgaron a otros clientes. Por ejemplo, si un usuario concede acceso a un permiso mediante el cliente de escritorio de una aplicación y, luego, otorga otro alcance a la misma aplicación a través de un cliente móvil, la autorización combinada incluirá ambos permisos.
    • Si revocas un token que representa una autorización combinada, el acceso a todos los permisos de esa autorización en nombre del usuario asociado se revoca de manera simultánea.

    En los siguientes ejemplos de código, se muestra cómo agregar alcances a un token de acceso existente. Este enfoque permite que tu app evite tener que administrar varios tokens de acceso.

    Biblioteca cliente de JS

    Para agregar permisos a un token de acceso existente, llama al método GoogleUser.grant(options). El objeto options identifica los permisos adicionales a los que deseas otorgar acceso.

    // Space-separated list of additional scope(s) you are requesting access to.
    // This code adds read-only access to the user's calendars via the Calendar API.
    var NEW_SCOPES = 'https://www.googleapis.com/auth/calendar.readonly';
    
    // Retrieve the GoogleUser object for the current user.
    var GoogleUser = GoogleAuth.currentUser.get();
    GoogleUser.grant({'scope': NEW_SCOPES});

    Extremos de OAuth 2.0

    Para agregar permisos a un token de acceso existente, incluye el parámetro include_granted_scopes en tu solicitud al servidor OAuth 2.0 de Google.

    En el siguiente fragmento de código, se muestra cómo hacerlo. En el fragmento, se supone que almacenaste los permisos para los que es válido tu token de acceso en el almacenamiento local del navegador. (El código de ejemplo completo almacena una lista de permisos para los que es válido el token de acceso mediante la configuración de la propiedad oauth2-test-params.scope en el almacenamiento local del navegador).

    El fragmento compara los permisos para los que el token de acceso es válido con el permiso que quieres usar en una consulta en particular. Si el token de acceso no cubre ese alcance, se inicia el flujo de OAuth 2.0. Aquí, la función oauth2SignIn es la misma que se proporcionó en el paso 2 (y que se brinda más adelante en el ejemplo completo).

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    Revoca un token

    En algunos casos, es posible que un usuario quiera revocar el acceso a una aplicación. Para revocar el acceso, el usuario debe ir a la Configuración de la cuenta. Consulta la sección Cómo quitar el acceso a sitios o apps de los sitios y apps de terceros con acceso a tu cuenta para obtener más información.

    También es posible que una aplicación revoque de manera programática el acceso que se le otorgó. La revocación programática es importante en las instancias en las que un usuario anula la suscripción, quita una aplicación o los recursos de la API que una app cambió de manera significativa. En otras palabras, una parte del proceso de eliminación puede incluir una solicitud a la API para garantizar que se quiten los permisos otorgados anteriormente a la aplicación.

    Biblioteca cliente de JS

    Para revocar un token de manera programática, llama a GoogleAuth.disconnect():

    GoogleAuth.disconnect();

    Extremos de OAuth 2.0

    Para revocar un token de manera programática, la aplicación realiza una solicitud a https://oauth2.googleapis.com/revoke y, también, incluye el token como parámetro:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    El token puede ser un token de acceso o un token de actualización. Si el token es de acceso y tiene un token de actualización correspondiente, este también se revocará.

    Si la revocación se procesa correctamente, el código de estado HTTP de la respuesta es 200. Para las condiciones de error, se muestra un código de estado HTTP 400 junto con un código de error.

    En el siguiente fragmento de JavaScript, se muestra cómo revocar un token en JavaScript sin usar la biblioteca cliente de las API de Google para JavaScript. Dado que el extremo de Google OAuth 2.0 para revocar tokens no admite el uso compartido de recursos entre dominios (CORS), el código crea un formulario y lo envía al extremo, en lugar de usar el método XMLHttpRequest() para publicar la solicitud.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }