Usa el modelo de tokens

La biblioteca de JavaScript de 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 concesión implícita de OAuth 2.0 y está diseñada para permitirte llamar a las APIs de Google directamente con REST y CORS, o bien usar nuestra biblioteca cliente de las APIs de Google para JavaScript (también conocida como gapi.client) para 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 selección de cuentas, acceso y consentimiento basados en la Web de Google. Por último, los servidores de OAuth de Google emiten y devuelven un token de acceso a tu app 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 explican en la guía anterior OAuth 2.0 para aplicaciones web del lado del cliente.

Requisitos previos

Sigue los pasos que se describen en Configuración para configurar tu pantalla de consentimiento de OAuth, obtener un ID de cliente y cargar la biblioteca cliente.

Inicializa un cliente de tokens

Llama a initTokenClient() para inicializar un nuevo cliente de tokens con el ID de cliente de tu app web. Debes incluir una lista de uno o más alcances a 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) => {
    ...
  },
});

Cómo activar 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 solicita al usuario que haga lo siguiente:

  • Elige su cuenta.
  • Acceder a la Cuenta de Google si aún no se accedió
  • 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 devuelve un TokenResponse que contiene un token de acceso y una lista de los permisos a los que el usuario otorgó acceso, o bien un error, a tu controlador de devolución de llamada.

Es posible que los usuarios cierren el selector de cuentas o las ventanas de acceso, en cuyo caso no se invocará tu función de devolución de llamada.

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

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

Durante este proceso, Google solicita el consentimiento del usuario y enumera individualmente 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 devolver un token de acceso y los alcances aprobados por el usuario. Luego, tu app controla de forma segura los diferentes resultados posibles con los permisos detallados.

Sin embargo, hay algunas excepciones. Las apps de Google Workspace Enterprise con delegación de autoridad de todo el dominio o las apps marcadas como Confiables omiten la pantalla de consentimiento de permisos detallados. En el caso de estas apps, los usuarios no verán la pantalla de consentimiento de permisos detallados. En cambio, tu app recibirá todos los permisos solicitados o ninguno.

Para obtener información más detallada, consulta Cómo controlar los permisos detallados.

Autorización incremental

En el caso de las apps web, las siguientes dos situaciones de alto nivel demuestran la autorización incremental con:

  • Una app de Ajax de una sola página que suele usar XMLHttpRequest con acceso dinámico a los recursos.
  • Varias páginas web y recursos separados y administrados por página

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

Ajax

Para agregar compatibilidad con la autorización incremental a tu app, realiza varias llamadas a requestAccessToken() y usa el parámetro scope del objeto OverridableTokenClientConfig para solicitar permisos individuales en el momento en que se necesiten y solo cuando sea necesario. En este ejemplo, los recursos se solicitarán y estará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 de tokens cuando se carga la página:
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
Solicita 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'
             })
           );
        

Mostrar fotos

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

Cada llamada a requestAccessToken activa un momento de consentimiento del usuario, por lo que tu app solo tendrá acceso a los recursos que requiera la sección que el usuario elija expandir, lo que limita 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 para 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 alcance necesario y obtiene un token de acceso llamando a initTokenClient() y requestAccessToken() en el momento de la carga. En este caso, se usan páginas web individuales para separar claramente la funcionalidad y los recursos del usuario por alcance. En una situación real, las páginas individuales pueden solicitar varios permisos relacionados.

Permisos detallados

Los permisos detallados se controlan de la misma manera en todos los casos. Después de que requestAccessToken() invoca tu función de devolución de llamada y se devuelve un token de acceso, verifica que el usuario haya aprobado los alcances 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 permisos aceptados previamente en sesiones o solicitudes anteriores. Se mantiene un registro del consentimiento del usuario por usuario y por ID de cliente, y persiste 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 tokens.

Trabaja con tokens

En el modelo de token, el SO o el navegador no almacenan un token de acceso. En cambio, primero se obtiene un token nuevo en el momento de la carga de la página o, posteriormente, se activa una llamada a requestAccessToken() a través de un gesto del usuario, como presionar un botón.

Uso de 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 consentimiento, que Google emita un token de acceso y que tu sitio trabaje con los datos del usuario.

En este ejemplo, se muestran los próximos eventos de calendario de los usuarios que accedieron con el token de acceso que devolvió tokenRequest():

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 integraciones fácilmente con APIs más complejas.

Trabaja con la biblioteca de JavaScript de las APIs de Google

El cliente de tokens funciona con la biblioteca cliente de la API 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 de que finalice la sesión del usuario, obtén un token nuevo llamando a requestAccessToken() desde un evento controlado por el usuario, como la presión de un botón.

Llama al método google.accounts.oauth2.revoke para quitar el consentimiento del usuario y el acceso a los recursos para todos los permisos 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);
  });