Uso de OAuth 2.0 para aplicaciones de servidor a servidor

. Para obtener más información, consulta Descripción general de la autenticación en la documentación de Google Cloud Platform.

El sistema Google OAuth 2.0 admite interacciones de servidor a servidor, como las que se generan entre una aplicación web y un servicio de Google. Para este caso, necesitas una cuenta de servicio, que es una cuenta que pertenece a tu aplicación en lugar de a un usuario final individual. Tu aplicación llama a las API de Google en nombre de la cuenta de servicio, por lo que los usuarios no están involucrados de forma directa. A veces, esta situación se denomina "OAuth de dos segmentos" o "2LO". El término relacionado "OAuth de tres segmentos" hace referencia a situaciones en las que tu aplicación llama a las API de Google en nombre de los usuarios finales y en las que a veces se requiere el consentimiento del usuario.

Por lo general, una aplicación usa una cuenta de servicio cuando usa las API de Google para trabajar con sus propios datos en lugar de los datos del usuario. Por ejemplo, una aplicación que usa Google Cloud Datastore para la persistencia de datos usaría una cuenta de servicio a fin de autenticar sus llamadas a la API de Google Cloud Datastore.

Los administradores de dominio de Google Workspace también pueden otorgar autoridad sobre todo el dominio a cuentas de servicio para acceder a datos del usuario en nombre de los usuarios del dominio.

En este documento, se describe cómo una aplicación puede completar el flujo de OAuth 2.0 de servidor a servidor mediante una biblioteca cliente de las API de Google (recomendado) o HTTP.

Descripción general

Para admitir interacciones de servidor a servidor, primero crea una cuenta de servicio para tu proyecto en el . Delegar el acceso de todo el dominio a la cuenta de servicio si desea acceder a los datos de los usuarios de su cuenta de Google Workspace.

Luego, tu aplicación se prepara para realizar llamadas autorizadas a la API mediante las credenciales de la cuenta de servicio a fin de solicitar un token de acceso desde el servidor de autenticación OAuth 2.0.

Por último, la aplicación puede usar el token de acceso para llamar a las API de Google.

Crear una cuenta de servicio

Las credenciales de una cuenta de servicio incluyen una dirección de correo electrónico generada que es única y que tiene como mínimo un par de claves públicas o privadas. Si se habilita la delegación de todo el dominio, el ID de cliente también forma parte de las credenciales de la cuenta de servicio.

Si tu aplicación se ejecuta en Google App Engine, se creará una cuenta de servicio de forma automática cuando crees el proyecto.

Si tu aplicación se ejecuta en Google Compute Engine, también se configura automáticamente una cuenta de servicio cuando creas el proyecto, pero debes especificar los permisos a los que necesita acceder la aplicación cuando creas una instancia de Google Compute Engine. Si quieres obtener más información, consulta Prepara una instancia para usar cuentas de servicio.

Si tu aplicación no se ejecuta en Google App Engine ni en Google Compute Engine, debes obtener estas credenciales en el . Para generar credenciales de la cuenta de servicio o ver las credenciales públicas que ya generaste, haz lo siguiente:

First, create a service account:

  1. Open the Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Click  Create service account.
  4. Under Service account details, type a name, ID, and description for the service account, then click Create and continue.
  5. Optional: Under Grant this service account access to project, select the IAM roles to grant to the service account.
  6. Click Continue.
  7. Optional: Under Grant users access to this service account, add the users or groups that are allowed to use and manage the service account.
  8. Click Done.
  9. Click  Create key, then click Create.

Next, create a service account key:

  1. Click the email address for the service account you created.
  2. Click the Keys tab.
  3. In the Add key drop-down list, select Create new key.
  4. Click Create.

Your new public/private key pair is generated and downloaded to your machine; it serves as the only copy of the private key. You are responsible for storing it securely. If you lose this key pair, you will need to generate a new one.

Puedes volver a API Console en cualquier momento para ver la dirección de correo electrónico, las huellas digitales de la clave pública y otra información, o para generar pares de claves públicas/privadas adicionales. Para obtener más detalles sobre las credenciales de cuenta de servicio en el API Console, consulta Cuentas de servicio en el archivo de ayuda API Console.

Toma nota de la dirección de correo electrónico de la cuenta de servicio y almacena el archivo de claves privadas de la cuenta en una ubicación accesible para tu aplicación. Tu aplicación los necesita para realizar llamadas autorizadas a la API.

Delegar la autoridad de todo el dominio a la cuenta de servicio

Si tienes una cuenta de Google Workspace, un administrador de la organización puede autorizar a una aplicación para que acceda a los datos del usuario en nombre de los usuarios del dominio de Google Workspace. Por ejemplo, una aplicación que usa la API de Calendario de Google para agregar eventos a los calendarios de todos los usuarios en un dominio de Google Workspace usará una cuenta de servicio para acceder a la API de Calendario de Google en nombre de los usuarios. La autorización de una cuenta de servicio para acceder a los datos en nombre de los usuarios de un dominio se conoce como “delegación de la autoridad de todo el dominio” a una cuenta de servicio.

Para delegar autoridad a todo el dominio a una cuenta de servicio, un administrador avanzado del dominio de Google Workspace debe completar los siguientes pasos:

  1. En la Consola del administrador de tu dominio de Google Workspace, ve al menú principal > Security > Access and data control > API Controls.
  2. En el panel Delegación de todo el dominio, selecciona Administrar la delegación de todo el dominio.
  3. Haz clic en Add new (Agregar nuevo).
  4. En el campo ID de cliente, ingresa el ID de cliente de la cuenta de servicio. Puedes encontrar el ID de cliente de tu cuenta de servicio en el Service accounts page.
  5. En el campo Alcances de OAuth (delimitados por comas), ingresa la lista de permisos a los que debe otorgarse acceso la aplicación. Por ejemplo, si tu aplicación necesita acceso completo a todo el dominio a la API de Google Drive y a la API del Calendario de Google, ingresa: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Haga clic en Authorize.

Tu aplicación ahora está autorizada para realizar llamadas a la API como usuarios de tu dominio (para robar la identidad de los usuarios). Cuando te prepares para realizar llamadas autorizadas a la API, especificas el usuario que actuará.

Cómo prepararse para realizar una llamada a la API autorizada

Java

Una vez que obtengas la dirección de correo electrónico de cliente y la clave privada del API Console, usa la biblioteca cliente de las API de Google para Java a fin de crear un objeto GoogleCredential a partir de las credenciales de la cuenta de servicio y los permisos a los que necesita acceder tu aplicación. Por ejemplo:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Si desarrollas una app en Google Cloud Platform, puedes usar las credenciales predeterminadas de la aplicación, lo que puede simplificar el proceso.

Delegar autoridad sobre todo el dominio

Si delegaste el acceso en todo el dominio a la cuenta de servicio y deseas usar una cuenta de usuario, especifica la dirección de correo electrónico de la cuenta de usuario con el método createDelegated del objeto GoogleCredential. Por ejemplo:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("user@example.com");

Usa el objeto GoogleCredential para llamar a las API de Google en tu aplicación.

Python

Después de obtener la dirección de correo electrónico y la clave privada del cliente del API Console, usa la biblioteca cliente de las API de Google para Python a fin de completar los siguientes pasos:

  1. Crea un objeto Credentials a partir de las credenciales de la cuenta de servicio y los permisos a los que necesita acceder tu aplicación. Por ejemplo:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    .

    Si desarrollas una app en Google Cloud Platform, puedes usar las credenciales predeterminadas de la aplicación, lo que puede simplificar el proceso.

  2. Delegar autoridad sobre todo el dominio

    Si delegaste el acceso en todo el dominio a la cuenta de servicio y deseas usar una cuenta de usuario, usa el método with_subject de un objeto ServiceAccountCredentials existente. Por ejemplo:

    delegated_credentials = credentials.with_subject('user@example.org')

Utilice el objeto Credentials para llamar a las API de Google en su aplicación.

HTTP/REST

Después de obtener el ID de cliente y la clave privada del API Console, tu aplicación debe completar los siguientes pasos:

  1. Crea un token web JSON (JWT, se pronuncia, “jot&quot”), que incluye un encabezado, un conjunto de reclamaciones y una firma.
  2. Solicita un token de acceso al servidor de autorización de Google OAuth 2.0.
  3. Maneja la respuesta JSON que muestra el servidor de autorización.

En las siguientes secciones, se describe cómo completar estos pasos.

Si la respuesta incluye un token de acceso, puedes usarlo para llamar a una API de Google. (Si la respuesta no incluye un token de acceso, es posible que tu JWT y solicitud de token no se hayan formado correctamente o que la cuenta de servicio no tenga permiso para acceder a los permisos solicitados).

Cuando vence el token de acceso, la aplicación genera otro JWT, lo firma y solicita otro token de acceso.

Tu aplicación de servidor usa un JWT para solicitar un token del servidor de autorización de Google y después usa el token para llamar a un extremo de la API de Google. No
                  hay ningún usuario final involucrado.

En el resto de esta sección, se describen los detalles para crear un JWT, firmar el JWT, formar la solicitud de token de acceso y manejar la respuesta.

Cómo crear un JWT

Un JWT se compone de tres partes: un encabezado, un conjunto de reclamaciones y una firma. El encabezado y el conjunto de reclamaciones son objetos JSON. Estos objetos JSON se serializan en bytes UTF-8 y, luego, se codifican con la codificación Base64url. Esta codificación proporciona resiliencia contra los cambios de codificación debido a operaciones de codificación repetidas. El encabezado, el conjunto de reclamaciones y la firma se concatenan junto con un carácter de punto (.).

Un JWT se compone de la siguiente manera:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

La string base para la firma es la siguiente:

{Base64url encoded header}.{Base64url encoded claim set}
Cómo crear el encabezado JWT

El encabezado consta de dos campos que indican el algoritmo de firma y el formato de la aserción. Ambos campos son obligatorios, y cada campo tiene un solo valor. A medida que se incorporen más algoritmos y formatos, este encabezado cambiará en consecuencia.

Las cuentas de servicio se basan en el algoritmo SHA-256 de RSA y en el formato de token de JWT. Por lo tanto, la representación JSON del encabezado es la siguiente:

{"alg":"RS256","typ":"JWT"}

La representación de Base64url es la siguiente:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Cómo crear el conjunto de reclamaciones de JWT

El conjunto de reclamaciones de JWT contiene información sobre el JWT, incluidos los permisos que se solicitan (permisos), el objetivo del token, el emisor, la hora de emisión del token y el ciclo de vida del token. La mayoría de los campos son obligatorios. Al igual que el encabezado JWT, el conjunto de reclamaciones de JWT es un objeto JSON y se usa en el cálculo de la firma.

Reclamos obligatorios

A continuación, se muestran las reclamaciones obligatorias del conjunto de reclamaciones de JWT. Pueden aparecer en cualquier orden en el conjunto de reclamaciones.

Nombre Descripción
iss La dirección de correo electrónico de la cuenta de servicio.
scope Una lista delimitada por espacios de los permisos que solicita la aplicación.
aud Descriptor del destino previsto de la aserción. Cuando realizas una solicitud de token de acceso, este valor es siempre https://oauth2.googleapis.com/token.
exp La hora de vencimiento de la aserción, especificada como segundos desde las 00:00:00 UTC, 1 de enero de 1970. Este valor tiene un máximo de 1 hora después de la hora emitida.
iat Hora en la que se emitió la aserción, especificada como segundos desde las 00:00:00 UTC, 1 de enero de 1970.

A continuación, se muestra la representación de JSON de los campos obligatorios en un conjunto de reclamaciones de JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Reclamos adicionales

En algunos casos empresariales, una aplicación puede usar la delegación de todo el dominio para actuar en nombre de un usuario particular en una organización. Se debe otorgar permiso para realizar este tipo de robo de identidad antes de que una aplicación pueda robar la identidad de un usuario. Por lo general, la gestiona un administrador avanzado. Para obtener más información, consulta Cómo controlar el acceso a la API con la delegación de todo el dominio.

Para obtener un token de acceso que otorgue a una aplicación acceso delegado a un recurso, incluye la dirección de correo electrónico del usuario en la reclamación JWT configurada como el valor del campo sub.

Nombre Descripción
sub La dirección de correo electrónico del usuario para el que la aplicación solicita acceso delegado.

Si una aplicación no tiene permiso para robar la identidad de un usuario, la respuesta a una solicitud de token de acceso que incluye el campo sub será un error.

A continuación, se muestra un ejemplo de un conjunto de reclamaciones de JWT que incluye el campo sub:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Codificar el conjunto de reclamaciones de JWT

Al igual que el encabezado JWT, el conjunto de reclamaciones de JWT debe serializarse en formato UTF-8 y estar codificado en formato seguro en Base64url. A continuación, se muestra un ejemplo de una representación JSON de un conjunto de reclamaciones JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Cómo procesar la firma

La firma web de JSON (JWS) es la especificación que guía la mecánica de generar la firma para el JWT. La entrada de la firma es el array de bytes del siguiente contenido:

{Base64url encoded header}.{Base64url encoded claim set}

El algoritmo de firma en el encabezado JWT debe usarse cuando se calcula la firma. El único algoritmo de firma compatible con el servidor de autorización de Google OAuth 2.0 es RSA con el algoritmo de hash SHA-256. Esto se expresa como RS256 en el campo alg del encabezado JWT.

Firma la representación UTF-8 de la entrada mediante SHA256withRSA (también conocida como RSASSA-PKCS1-V1_5-SIGN con la función de hash SHA-256) con la clave privada obtenida de Google API Console. El resultado será un array de bytes.

La firma debe estar codificada en Base64url. El encabezado, el conjunto de reclamaciones y la firma se concatenan con un carácter de punto (.). El resultado es JWT. Deben ser las siguientes (se agregaron saltos de línea para brindar mayor claridad):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

A continuación, se muestra un ejemplo de un JWT antes de la codificación Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

A continuación, se muestra un ejemplo de un JWT que se firmó y está listo para su transmisión:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Realiza la solicitud de token de acceso

Después de generar el JWT firmado, una aplicación puede usarlo para solicitar un token de acceso. Esta solicitud de token de acceso es una solicitud HTTPS POST y el cuerpo está codificado como URL. La URL se muestra a continuación:

https://oauth2.googleapis.com/token

Los siguientes parámetros son obligatorios en la solicitud POST HTTPS:

Nombre Descripción
grant_type Usa la siguiente string, codificada en URL según sea necesario: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JWT, incluida la firma.

A continuación, se muestra un volcado sin procesar de la solicitud POST de HTTPS que se usó en una solicitud de token de acceso:

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

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

A continuación, se muestra la misma solicitud, con curl:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Cómo manejar la respuesta

Si la solicitud de token de acceso y JWT tienen el formato correcto y la cuenta de servicio tiene permiso para realizar la operación, la respuesta JSON del servidor de autorización incluirá un token de acceso. El siguiente es un ejemplo de respuesta:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

Los tokens de acceso se pueden volver a usar durante el período de duración especificado por el valor expires_in.

Cómo llamar a las API de Google

Java

Sigue estos pasos para usar el objeto GoogleCredential a fin de llamar a las API de Google:

  1. Crea un objeto de servicio para la API a la que deseas llamar con el objeto GoogleCredential. Por ejemplo:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
    .
  2. Realiza solicitudes al servicio de la API mediante la interfaz que proporciona el objeto de servicio. Por ejemplo, para generar una lista de las instancias de bases de datos de Cloud SQL en el proyecto fascinante ejemplo-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Usa el objeto Credentials autorizado para llamar a las API de Google mediante los siguientes pasos:

  1. Compila un objeto de servicio para la API a la que deseas llamar. Para crear un objeto de servicio, llama a la función build con el nombre y la versión de la API, y el objeto Credentials autorizado. Por ejemplo, para llamar a la versión 1beta3 de la API de Cloud SQL Management, haz lo siguiente:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Realiza solicitudes al servicio de la API mediante la interfaz que proporciona el objeto de servicio. Por ejemplo, para generar una lista de las instancias de bases de datos de Cloud SQL en el proyecto fascinante ejemplo-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Una vez que tu aplicación obtenga un token de acceso, puedes usarlo para hacer llamadas a una API de Google en nombre de una cuenta de servicio o 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 incluyendo un parámetro de búsqueda access_token o un valor Bearer de encabezado HTTP Authorization. Cuando es posible, se prefiere el encabezado HTTP, ya que las strings de consulta tienden a 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, al llamar a la API de Drive Files).

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

Ejemplos de HTTP GET

Una llamada al extremo drive.files (la API de Drive Files) mediante 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 mediante 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, se muestra un ejemplo que 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, puedes usar la opción del parámetro de string de consulta:

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

Cuándo vencen los tokens de acceso

Los tokens de acceso que emite el servidor de autorización de Google OAuth 2.0 vencen después de la duración que proporciona el valor expires_in. Cuando un token de acceso vence, la aplicación debe generar otro JWT, firmarlo y solicitar otro token de acceso.

Códigos de error de JWT

Campo error Campo error_description Significado Cómo resolver el problema
unauthorized_client Unauthorized client or scope in request. Si intentas usar la delegación de todo el dominio, la cuenta de servicio no está autorizada en la Consola del administrador del dominio del usuario.

Asegúrate de que la cuenta de servicio esté autorizada en la página sub para el usuario en la página Delegación de todo el dominio de la Consola del administrador.

Si bien suele demorar unos minutos, la autorización puede demorar hasta 24 horas en propagarse a todos los usuarios de tu Cuenta de Google.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Se autorizó una cuenta de servicio con la dirección de correo electrónico del cliente en lugar del ID de cliente (numérico) en la Consola del administrador. En la página de delegación de todo el dominio de la Consola del administrador, quita el cliente y vuelve a agregarlo con el ID numérico.
access_denied (cualquier valor) Si usas la delegación de todo el dominio, uno o más permisos solicitados no se autorizaron en la Consola del administrador.

Asegúrate de que la cuenta de servicio esté autorizada en la página Delegación de todo el dominio de la Consola del administrador del usuario en la reclamación (campo) sub y de que incluya todos los permisos que solicitas en la reclamación scope de tu JWT.

Si bien suele demorar unos minutos, la autorización puede demorar hasta 24 horas en propagarse a todos los usuarios de tu Cuenta de Google.

invalid_grant Not a valid email. El usuario no existe. Comprueba que la dirección de correo electrónico que aparece en el reclamo sub (campo) sea correcta.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

Por lo general, significa que la hora del sistema local no es correcta. También podría ocurrir si el valor exp está a más de 65 minutos en el futuro a partir del valor iat o si el valor exp es menor que iat.

Asegúrese de que el reloj del sistema en el que se genera el JWT sea correcto. Si es necesario, sincroniza tu tiempo con la NTP de Google.

invalid_grant Invalid JWT Signature.

La aserción de JWT se firma con una clave privada que no está asociada a la cuenta de servicio identificada mediante el correo electrónico del cliente, o bien la clave que se usó se borró, se inhabilitó o venció.

Como alternativa, la aserción de JWT podría estar codificada de forma incorrecta. Debe estar codificada en Base64 sin saltos de línea ni con relleno igual.

Decodifica el conjunto de reclamaciones de JWT y verifica que la clave que firmó la aserción esté asociada con la cuenta de servicio.

Intenta usar una biblioteca de OAuth proporcionada por Google para asegurarte de que el JWT se genere correctamente.

invalid_scope Invalid OAuth scope or ID token audience provided. No se solicitaron permisos (lista vacía de permisos), o uno de los alcances solicitados no existe (es decir, no es válido).

Asegúrate de que se complete la reclamación scope (campo) del JWT y compara los permisos que contiene con los alcances documentados de las API que deseas usar, para asegurarte de que no haya errores o errores tipográficos.

Ten en cuenta que la lista de alcances de la reclamación scope debe estar separada por espacios, no por comas.

disabled_client The OAuth client was disabled. La clave que se usa para firmar la aserción de JWT está inhabilitada.

Ve a la sección Google API Consoley, en IAM & Admin (Cuentas de servicio), habilita la cuenta de servicio que contiene el ID de clave que se usa para firmar la aserción.

Anexo: Autorización de cuentas de servicio sin OAuth

Con algunas API de Google, puedes realizar llamadas a la API autorizadas directamente con un JWT firmado como un token del portador, en lugar de un token de acceso OAuth 2.0. Cuando esto sea posible, puedes evitar tener que realizar una solicitud de red al servidor de autorización de Google antes de realizar una llamada a la API.

Si la API a la que quieres llamar tiene una definición de servicio publicada en el repositorio de GitHub de las API de Google, puedes realizar llamadas a la API autorizadas con un JWT en lugar de un token de acceso. Para ello, sigue estos pasos:

  1. Crea una cuenta de servicio como se describió anteriormente. Asegúrate de conservar el archivo JSON que obtienes cuando creas la cuenta.
  2. Con cualquier biblioteca JWT estándar, como una que se encuentra en jwt.io, crea un JWT con un encabezado y una carga útil como el siguiente ejemplo:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • Para el campo kid en el encabezado, especifica el ID de clave privada de tu cuenta de servicio. Puedes encontrar este valor en el campo private_key_id del archivo JSON de tu cuenta de servicio.
    • Para los campos iss y sub, especifica la dirección de correo electrónico de tu cuenta de servicio. Puedes encontrar este valor en el campo client_email del archivo JSON de tu cuenta de servicio.
    • En el campo aud, especifica el extremo de API. Por ejemplo: https://SERVICE.googleapis.com/.
    • En el campo iat, especifica la hora actual de Unix y, en el campo exp, especifica la hora exactamente 3, 600 segundos después de la fecha de vencimiento del JWT.

Firma el JWT con RSA-256 mediante la clave privada que se encuentra en el archivo JSON de tu cuenta de servicio.

Por ejemplo:

Java

Mediante google-api-java-client y java-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Uso de PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Llame a la API con el JWT firmado como el token del portador:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com