Usa el modelo de tokens

La biblioteca de JavaScript google.accounts.oauth2 te ayuda a solicitar el consentimiento del usuario y obtener un token de acceso para trabajar con sus datos. Se basa en el flujo de otorgamiento implícito de OAuth 2.0 y está diseñado para permitirte llamar a las APIs de Google directamente con REST y CORS, o usar nuestra biblioteca cliente de las APIs de Google para JavaScript (también conocida como gapi.client) a fin de acceder de forma simple y flexible a nuestras APIs más complejas.

Antes de acceder a los datos protegidos del usuario desde un navegador, los usuarios de tu sitio activan los procesos de acceso, consentimiento y selector de cuentas basados en la Web de Google. Por último, los servidores OAuth de Google emiten y muestran un token de acceso a tu aplicación web.

En el modelo de autorización basado en tokens, no es necesario almacenar tokens de actualización por usuario en tu servidor de backend.

Te recomendamos que sigas el enfoque que se describe aquí en lugar de las técnicas que se abordan en la guía anterior de OAuth 2.0 para aplicaciones web del cliente.

Configuración

Para buscar o crear un ID de cliente, sigue los pasos que se describen en la guía Cómo obtener tu ID de cliente de la API de Google. A continuación, agrega la biblioteca cliente a las páginas de tu sitio que llamarán a las APIs de Google. Por último, inicializa el cliente del token. Por lo general, esto se hace dentro del controlador onload de la biblioteca cliente.

Inicializa un cliente de tokens

Llama a initTokenClient() para inicializar un nuevo cliente de token con el ID de cliente de tu app web. De manera opcional, puedes incluir una lista de uno o más permisos para los que el usuario necesita acceder:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (response) => {
    ...
  },
});

Activa el flujo de tokens de OAuth 2.0

Usa el método requestAccessToken() para activar el flujo de UX del token y obtener un token de acceso. Google le pide al usuario que haga lo siguiente:

  • Elegir su cuenta
  • Accede a la Cuenta de Google si aún no lo hiciste.
  • otorgar consentimiento para que tu app web acceda a cada alcance solicitado.

Un gesto del usuario activa el flujo de tokens: <button onclick="client.requestAccessToken();">Authorize me</button>

Luego, Google muestra un TokenResponse que contiene un token de acceso y una lista de permisos a los que el usuario le otorgó acceso, o bien un error, a tu controlador de devolución de llamada.

Los usuarios pueden cerrar el selector de cuentas o las ventanas de acceso, en cuyo caso no se invocará la función de devolución de llamada.

El diseño y la experiencia del usuario de tu app deben implementarse solo después de una revisión minuciosa de las políticas de OAuth 2.0 de Google. Estas políticas abarcan el trabajo con varios alcances, cuándo y cómo controlar el consentimiento del usuario y mucho más.

La autorización incremental es una política y la metodología de diseño de apps que se usa para solicitar acceso a los recursos mediante alcances, solo según sea necesario, en lugar de hacerlo por adelantado y de una sola vez. Los usuarios pueden aprobar o rechazar el uso compartido de los recursos individuales que solicita tu app, lo que se conoce como permisos detallados.

Durante este proceso, Google solicita el consentimiento del usuario y enumera de forma individual cada alcance solicitado, los usuarios seleccionan los recursos que se compartirán con tu app y, por último, Google invoca tu función de devolución de llamada para mostrar un token de acceso y los alcances aprobados por el usuario. Luego, la app manejará de forma segura los distintos resultados posibles con permisos detallados.

Autorización incremental

Para las aplicaciones web, las siguientes dos situaciones de alto nivel demuestran la autorización incremental mediante:

  • Es una app Ajax de una sola página que, a menudo, usa XMLHttpRequest con acceso dinámico a recursos.
  • Varias páginas web, los recursos se separan y administran por página.

Estas dos situaciones se presentan para ilustrar las consideraciones y metodologías de diseño, pero no pretenden ser recomendaciones exhaustivas sobre cómo generar consentimiento en tu app. Las apps del mundo real pueden usar una variación o una combinación de estas técnicas.

Ajax

Agrega compatibilidad con la autorización incremental a tu app. Para ello, realiza varias llamadas a requestAccessToken() y usa el parámetro scope del objeto OverridableTokenClientConfig a fin de solicitar permisos individuales en el momento en que sean necesarios y solo cuando sea necesario. En este ejemplo, se solicitarán los recursos y serán visibles solo después de que un gesto del usuario expanda una sección de contenido contraída.

App de Ajax
Inicializa el cliente del token cuando se carga la página:
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
Solicita el consentimiento y obtén tokens de acceso a través de gestos del usuario. Haz clic en “+” para abrir:

Documentos para leer

Mostrar documentos recientes

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/documents.readonly'
             })
           );
        

Próximos eventos

Mostrar información del calendario

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/calendar.readonly'
             })
           );
        

Muestra fotos

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/photoslibrary.readonly'
             })
           );
        

Cada llamada a requestAccessToken activa un momento de consentimiento del usuario. Tu app solo tendrá acceso a los recursos requeridos por la sección que el usuario elija expandir. De esta manera, se limitará el uso compartido de recursos a través de la elección del usuario.

Varias páginas web

Cuando se diseña para la autorización incremental, se usan varias páginas a fin de solicitar solo los alcances necesarios para cargar una página, lo que reduce la complejidad y la necesidad de realizar varias llamadas para obtener el consentimiento del usuario y recuperar un token de acceso.

App de varias páginas
Página web Código
Página 1: Documentos para leer
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/documents.readonly',
  });
  client.requestAccessToken();
          
Página 2: Próximos eventos
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/calendar.readonly',
  });
  client.requestAccessToken();
          
Página 3: Carrusel de fotos
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/photoslibrary.readonly',
  });
  client.requestAccessToken();
          

Cada página solicita el permiso necesario y obtiene un token de acceso llamando a initTokenClient() y requestAccessToken() en el momento de la carga. En esta situación, se usan páginas web individuales para separar con claridad la funcionalidad del usuario y los recursos por alcance. En una situación real, las páginas individuales pueden solicitar varios alcances relacionados.

Permisos detallados

Los permisos detallados se controlan de la misma manera en todas las situaciones. Después de que requestAccessToken() invoque tu función de devolución de llamada y se muestre un token de acceso, verifica que el usuario haya aprobado los permisos solicitados con hasGrantedAllScopes() o hasGrantedAnyScope(). Por ejemplo:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
          https://www.googleapis.com/auth/documents.readonly \
          https://www.googleapis.com/auth/photoslibrary.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
          'https://www.googleapis.com/auth/photoslibrary.readonly')) {
        // Look at pictures
        ...
      }
      if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
          'https://www.googleapis.com/auth/calendar.readonly',
          'https://www.googleapis.com/auth/documents.readonly')) {
        // Meeting planning and review documents
        ...
      }
    }
  },
});

En la respuesta, también se incluirán los subsidios aceptados anteriormente de sesiones o solicitudes anteriores. Se mantiene un registro del consentimiento del usuario por ID de cliente y usuario, y se conserva en varias llamadas a initTokenClient() o requestAccessToken(). De forma predeterminada, el consentimiento del usuario solo es necesario la primera vez que un usuario visita tu sitio web y solicita un alcance nuevo, pero se puede solicitar en cada carga de página con prompt=consent en los objetos de configuración del cliente de token.

Trabaja con tokens

En el modelo de token, el SO ni el navegador no almacenan un token de acceso. En su lugar, se obtiene uno nuevo durante el tiempo de carga de la página o, luego, mediante la activación de una llamada a requestAccessToken() mediante un gesto del usuario, como la presión de un botón.

Usa REST y CORS con las APIs de Google

Se puede usar un token de acceso para realizar solicitudes autenticadas a las APIs de Google con REST y CORS. Esto permite que los usuarios accedan, otorguen su consentimiento, que Google emita un token de acceso y que tu sitio funcione con los datos del usuario.

En este ejemplo, usa el token de acceso que muestra tokenRequest() para ver los próximos eventos de calendario de los usuarios que accedieron:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();

Consulta Cómo usar CORS para acceder a las APIs de Google para obtener más información.

En la siguiente sección, se explica cómo realizar una integración sencilla en APIs más complejas.

Cómo trabajar con la biblioteca JavaScript de las APIs de Google

El cliente del token trabaja con la biblioteca cliente de las APIs de Google para JavaScript. Consulta el siguiente fragmento de código.

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

Vencimiento del token

Por diseño, los tokens de acceso tienen una vida útil corta. Si el token de acceso vence antes del final de la sesión del usuario, llama a requestAccessToken() desde un evento controlado por el usuario, como la presión de un botón, para obtener uno nuevo.

Llama al método google.accounts.oauth2.revoke para quitar el consentimiento del usuario y el acceso a los recursos en todos los alcances otorgados a tu app. Se requiere un token de acceso válido para revocar este permiso:

google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
    console.log(done);
    console.log(done.successful);
    console.log(done.error);
    console.log(done.error_description);
  });