Uso de OAuth 2.0 para aplicaciones de servidor a servidor

El sistema Google OAuth 2.0 admite interacciones de servidor a servidor, como las que existen entre una aplicación web y un servicio de Google. Para este escenario, necesita una cuenta de servicio , que es una cuenta que pertenece a su aplicación en lugar de a un usuario final individual. Su aplicación llama a las API de Google en nombre de la cuenta de servicio, por lo que los usuarios no se involucran directamente. Este escenario a veces se denomina "OAuth de dos patas" o "2LO". (El término relacionado "OAuth de tres patas" se refiere a situaciones en las que su 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).

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

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

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

Descripción general

Para admitir interacciones de servidor a servidor, primero cree una cuenta de servicio para su proyecto en el API Console. Si desea acceder a los datos de los usuarios de su cuenta de Google Workspace, delegue el acceso de todo el dominio a la cuenta de servicio.

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

Finalmente, su 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 al menos un par de claves pública / privada. Si la delegación de todo el dominio está habilitada, una ID de cliente también forma parte de las credenciales de la cuenta de servicio.

Si su aplicación se ejecuta en Google App Engine, una cuenta de servicio se configura automáticamente cuando crea su proyecto.

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

Si su aplicación no se ejecuta en Google App Engine o Google Compute Engine, debe obtener estas credenciales en Google API Console. Para generar credenciales de cuenta de servicio o para ver las credenciales públicas que ya ha generado, haga lo siguiente:

  1. Abra el Service accounts page .
  2. If prompted, select a project, or create a new one.
  3. Haga clic en Crear cuenta de servicio .
  4. En Detalles de la cuenta de servicio , escriba un nombre, ID y descripción para la cuenta de servicio, luego haga clic en Crear .
  5. Opcional: en Permisos de la cuenta de servicio , seleccione los roles de IAM para otorgar a la cuenta de servicio, luego haga clic en Continuar .
  6. Opcional: en Conceder a los usuarios acceso a esta cuenta de servicio , agregue los usuarios o grupos que pueden usar y administrar la cuenta de servicio.
  7. Haga clic en clave Crear , luego haga clic en Crear .

Su nuevo par de claves pública / privada se genera y descarga en su máquina; sirve como la única copia de la clave privada. Usted es responsable de almacenarlo de forma segura. Si pierde este par de claves, deberá generar uno nuevo.

Si necesita otorgar autoridad de dominio de G Suite a la cuenta de servicio, haga clic en la dirección de correo electrónico de la cuenta de servicio que creó, luego copie el valor del cuadro ID único .

Para delegar autoridad a la cuenta de servicio, use el valor que copió como ID de cliente.

Puede volver al 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 la cuenta de servicio en API Console, consulte Cuentas de servicio en el archivo de ayuda API Console.

Tome nota de la dirección de correo electrónico de la cuenta de servicio y almacene el archivo de clave privada de la cuenta de servicio en una ubicación accesible para su aplicación. Su aplicación los necesita para realizar llamadas API autorizadas.

Delegar autoridad en todo el dominio a la cuenta de servicio

Si tiene una cuenta de Google Workspace, un administrador de la organización puede autorizar que una aplicación 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 Google Calendar para agregar eventos a los calendarios de todos los usuarios en un dominio de Google Workspace usaría una cuenta de servicio para acceder a la API de Google Calendar en nombre de los usuarios. En ocasiones, la autorización de una cuenta de servicio para acceder a los datos en nombre de los usuarios de un dominio se denomina "delegación de autoridad en todo el dominio" a una cuenta de servicio.

Para delegar la autoridad de todo el dominio a una cuenta de servicio, primero habilite la delegación de todo el dominio para una cuenta de servicio existente en el Service accounts page o cree una nueva cuenta de servicio con la delegación de todo el dominio habilitada.

Luego, un superadministrador del dominio de Google Workspace debe completar los siguientes pasos:

  1. Desde la consola de administración de su dominio de Google Workspace, vaya al menú del principal> Seguridad> Controles de API .
  2. En el panel de delegación de todo el dominio , seleccione Administrar la delegación de todo el dominio .
  3. Haga clic en Agregar nuevo .
  4. En el campo ID de cliente , ingrese el ID de cliente de la cuenta de servicio. Puede encontrar el ID de cliente de su cuenta de servicio en el Service accounts page.
  5. En el campo Ámbitos de OAuth (delimitados por comas) , ingrese la lista de ámbitos a los que se le debe otorgar acceso a su aplicación. Por ejemplo, si su aplicación necesita acceso completo en todo el dominio a la API de Google Drive y la API de Google Calendar, ingrese: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth / calendario .
  6. Haga clic en Autorizar .

Su aplicación ahora tiene la autoridad para realizar llamadas a la API como usuarios de su dominio (para "hacerse pasar por usuarios"). Cuando se prepara para realizar llamadas API autorizadas, especifica el usuario para suplantar.

Preparándose para realizar una llamada API autorizada

Java

Después de obtener la dirección de correo electrónico del cliente y la clave privada del API Console, use la biblioteca cliente de las API de Google para Java para crear un objeto GoogleCredential partir de las credenciales de la cuenta de servicio y los ámbitos a los que su aplicación necesita acceder. 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 está desarrollando una aplicación en Google Cloud Platform, puede usar las credenciales predeterminadas de la aplicación en su lugar, lo que puede simplificar el proceso.

Delegar autoridad en todo el dominio

Si ha delegado el acceso de todo el dominio de la cuenta de servicio y quiere hacerse pasar por una cuenta de usuario, especifique la dirección de correo electrónico de la cuenta de usuario con la createDelegated método de la GoogleCredential objeto. Por ejemplo:

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

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

Pitón

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

  1. Cree un objeto Credentials partir de las Credentials de la cuenta de servicio y los ámbitos a los que su aplicación necesita acceder. 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 está desarrollando una aplicación en Google Cloud Platform, puede usar las credenciales predeterminadas de la aplicación en su lugar, lo que puede simplificar el proceso.

  2. Delegar autoridad en todo el dominio

    Si ha delegado acceso de todo el dominio a la cuenta de servicio y desea hacerse pasar por una cuenta de usuario, use 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, su aplicación debe completar los siguientes pasos:

  1. Cree un token web JSON (JWT, pronunciado, "jot") que incluya un encabezado, un conjunto de reclamos y una firma.
  2. Solicite un token de acceso del servidor de autorización de Google OAuth 2.0.
  3. Maneja la respuesta JSON que devuelve el servidor de autorización.

Las secciones que siguen describen cómo completar estos pasos.

Si la respuesta incluye un token de acceso, puede usar el token de acceso para llamar a una API de Google . (Si la respuesta no incluye un token de acceso, es posible que su JWT y su solicitud de token no estén formados correctamente o que la cuenta de servicio no tenga permiso para acceder a los ámbitos solicitados).

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

Su aplicación de servidor usa un JWT para solicitar un token del servidor de autorización de Google y luego usa el token para llamar a un punto final de la API de Google. Ningún usuario final está involucrado.

El resto de esta sección describe los detalles de la creación de un JWT, la firma del JWT, la formación de la solicitud del token de acceso y el manejo de la respuesta.

Creando un JWT

Un JWT se compone de tres partes: un encabezado, un conjunto de reclamos y una firma. El encabezado y el conjunto de notificaciones 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 resistencia frente a los cambios de codificación debidos a operaciones de codificación repetidas. El encabezado, el conjunto de notificaciones 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 cadena base para la firma es la siguiente:

{Base64url encoded header}.{Base64url encoded claim set}
Formando 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 introducen algoritmos y formatos adicionales, este encabezado cambiará en consecuencia.

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

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

La representación de Base64url de esto es la siguiente:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Formación del conjunto de reclamaciones de JWT

El conjunto de notificaciones de JWT contiene información sobre el JWT, incluidos los permisos que se solicitan (ámbitos), el destino del token, el emisor, la hora en que se emitió el token y la vida útil del token. La mayoría de los campos son obligatorios. Al igual que el encabezado JWT, el conjunto de notificaciones JWT es un objeto JSON y se utiliza en el cálculo de la firma.

Reclamaciones requeridas

Las reclamaciones requeridas en el conjunto de reclamaciones JWT se muestran a continuación. Pueden aparecer en cualquier orden en el conjunto de notificaciones.

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 Un descriptor del objetivo previsto de la aserción. Al realizar una solicitud de token de acceso, este valor siempre es 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 La hora a la que se emitió la aserción, especificada en segundos desde las 00:00:00 UTC del 1 de enero de 1970.

La representación JSON de los campos obligatorios en un conjunto de notificaciones JWT se muestra a continuación:

{
  "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
}
Reclamaciones adicionales

En algunos casos empresariales, una aplicación puede utilizar la delegación de todo el dominio para actuar en nombre de un usuario en particular en una organización. El permiso para realizar este tipo de suplantación de identidad se debe otorgar antes de que una aplicación pueda suplantar a un usuario y, por lo general, lo maneja un superadministrador. Para obtener más información, consulte Controlar el acceso a la API con delegación en todo el dominio .

Para obtener un token de acceso que otorgue a una aplicación acceso delegado a un recurso, incluya la dirección de correo electrónico del usuario en el conjunto de reclamos JWT como el valor del 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 hacerse pasar por un usuario, la respuesta a una solicitud de token de acceso que incluye el sub será un error .

A continuación, se muestra un ejemplo de un conjunto de notificaciones JWT que incluye el 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
}
Codificación del conjunto de notificaciones JWT

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

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

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

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

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

Firme la representación UTF-8 de la entrada usando SHA256withRSA (también conocido como RSASSA-PKCS1-V1_5-SIGN con la función hash SHA-256) con la clave privada obtenida del Google API Console. La salida será una matriz de bytes.

Luego, la firma debe estar codificada en Base64url. El encabezado, el conjunto de notificaciones y la firma se concatenan junto con un carácter de punto ( . ). El resultado es el JWT. Debe ser lo siguiente (saltos de línea agregados para 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 ha firmado y está listo para su transmisión:

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

Realizar la solicitud del 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 POST HTTPS POST y el cuerpo está codificado en URL. La URL se muestra a continuación:

https://oauth2.googleapis.com/token

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

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

A continuación se muestra un volcado sin procesar de la POST HTTPS POST utilizada 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, usando 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

Manejando la respuesta

Si el JWT y la solicitud del token de acceso están formados correctamente y la cuenta de servicio tiene permiso para realizar la operación, la respuesta JSON del servidor de autorización incluye un token de acceso. La siguiente es una respuesta de ejemplo:

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

Los tokens de acceso se pueden reutilizar durante la ventana de duración especificada por el valor expires_in .

Llamar a las API de Google

Java

Utilice el objeto GoogleCredential para llamar a las API de Google completando los siguientes pasos:

  1. Cree un objeto de servicio para la API que desea llamar mediante el objeto GoogleCredential . Por ejemplo:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Realice solicitudes al servicio API utilizando la interfaz proporcionada por el objeto de servicio . Por ejemplo, para enumerar las instancias de bases de datos de Cloud SQL en el emocionante proyecto-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Pitón

Utilice el objeto Credentials autorizado para llamar a las API de Google completando los siguientes pasos:

  1. Cree un objeto de servicio para la API que desea llamar. Usted crea un objeto de servicio llamando a la función de 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 administración de Cloud SQL:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Realice solicitudes al servicio API utilizando la interfaz proporcionada por el objeto de servicio . Por ejemplo, para enumerar las instancias de bases de datos de Cloud SQL en el proyecto emocionante-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP / REST

Una vez que su aplicación obtiene un token de acceso, puede usar el token para realizar llamadas a una API de Google en nombre de una cuenta de servicio o cuenta de usuario determinada si se han otorgado los alcances de acceso requeridos por la API. Para hacer esto, incluya el token de acceso en una solicitud a la API incluyendo un parámetro de consulta access_token o un valor de Bearer encabezado HTTP de Authorization . Cuando sea posible, es preferible el encabezado HTTP, porque las cadenas de consulta tienden a ser visibles en los registros del servidor. En la mayoría de los casos, puede utilizar una biblioteca cliente para configurar sus llamadas a las API de Google (por ejemplo, al llamar a la API de archivos de Drive ).

Puede probar todas las API de Google y ver sus alcances en OAuth 2.0 Playground .

Ejemplos de HTTP GET

Una llamada al drive.files final drive.files (la API de archivos de Drive) utilizando el encabezado HTTP Authorization: Bearer puede tener el siguiente aspecto. Tenga en cuenta que debe especificar su propio token de acceso:

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

Aquí hay una llamada a la misma API para el usuario autenticado usando el parámetro de cadena de consulta access_token :

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

ejemplos de curl

Puede probar estos comandos con la aplicación de línea de comandos curl . Aquí hay un ejemplo que usa la opción de encabezado HTTP (preferido):

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

O, alternativamente, la opción de parámetro de cadena de consulta:

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

Cuando caducan los tokens de acceso

Los tokens de acceso emitidos por el servidor de autorización de Google OAuth 2.0 caducan después de la duración proporcionada por el valor expires_in . Cuando un token de acceso caduca, la aplicación debe generar otro JWT, firmarlo y solicitar otro token de acceso.

Códigos de error de JWT

campo de error campo error_description Significado Cómo resolver
unauthorized_client Unauthorized client or scope in request. Si está intentando utilizar la delegación de todo el dominio, la cuenta de servicio no está autorizada en la Consola de administración del dominio del usuario.

Asegúrese de que la cuenta de servicio esté autorizada en la página de delegación de todo el dominio de la Consola de administración para el usuario en la reclamación sub (campo).

Si bien suele demorar unos minutos, la autorización puede demorar hasta 24 horas en propagarse a todos los usuarios de su 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 utilizando la dirección de correo electrónico del cliente en lugar del ID de cliente (numérico) en la Consola de administración. En la página de delegación de todo el dominio en la consola de administración, elimine el cliente y vuelva a agregarlo con el ID numérico.
access_denied (algún valor) Si utiliza la delegación de todo el dominio, uno o más ámbitos solicitados no están autorizados en la Consola de administración.

Asegúrese de que la cuenta de servicio esté autorizada en la página de delegación de todo el dominio de la Consola de administración para el usuario en el reclamo sub (campo) y de que incluya todos los alcances que solicita en el reclamo de scope de su JWT.

Si bien generalmente toma unos minutos, la autorización puede demorar hasta 24 horas en propagarse a todos los usuarios de su cuenta de Google.

invalid_grant Not a valid email. El usuario no existe. Verifique que la dirección de correo electrónico en la reclamación 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 suceder si el valor exp es más de 65 minutos en el futuro del valor iat , o si el valor exp es menor que el valor iat .

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

invalid_grant Invalid JWT Signature.

La aserción JWT está firmada con una clave privada no asociada con la cuenta de servicio identificada por el correo electrónico del cliente.

Alternativamente, la aserción JWT podría estar codificada incorrectamente; debe estar codificada en Base64, sin líneas nuevas ni signos iguales de relleno.

Decodifique el conjunto de notificaciones de JWT y verifique que la clave que firmó la aserción esté asociada con la cuenta de servicio.

Intente utilizar una biblioteca OAuth proporcionada por Google para asegurarse de que el JWT se genere correctamente.

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

Asegúrese de que el reclamo de scope (campo) del JWT esté completo y compare los alcances que contiene con los alcances documentados para las API que desea usar, para asegurarse de que no haya errores ni errores tipográficos.

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

disabled_client The OAuth client was disabled. La clave utilizada para firmar la aserción JWT está deshabilitada.

Vaya a Google API Console y, en IAM y administración> Cuentas de servicio , habilite la cuenta de servicio que contiene la "ID de clave" utilizada para firmar la aserción.

Anexo: autorización de la cuenta de servicio sin OAuth

Con algunas API de Google, puede realizar llamadas API autorizadas utilizando un JWT firmado directamente como un token de portador, en lugar de un token de acceso OAuth 2.0. Cuando esto sea posible, puede 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 desea llamar tiene una definición de servicio publicada en el repositorio de GitHub de las API de Google , puede realizar llamadas API autorizadas utilizando un JWT en lugar de un token de acceso. Para hacerlo:

  1. Cree una cuenta de servicio como se describe arriba. Asegúrese de conservar el archivo JSON que obtiene cuando crea la cuenta.
  2. Con cualquier biblioteca JWT estándar, como la que se encuentra en jwt.io , cree 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 para kid en el encabezado, especifique el ID de clave privada de su cuenta de servicio. Puede encontrar este valor en el campo private_key_id del archivo JSON de su cuenta de servicio.
    • Para los campos iss y sub , especifique la dirección de correo electrónico de su cuenta de servicio. Puede encontrar este valor en el campo client_email del archivo JSON de su cuenta de servicio.
    • Para el campo aud , especifique el punto final de la API. Por ejemplo: https:// SERVICE .googleapis.com/ .
    • Para el campo iat , especifique la hora actual de Unix, y para el campo exp , especifique la hora exactamente 3600 segundos después, cuando el JWT caducará.

Firme el JWT con RSA-256 utilizando la clave privada que se encuentra en el archivo JSON de su cuenta de servicio.

Por ejemplo:

Java

Usando 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 ...

Pitón

Usando 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, utilizando el JWT firmado como token de portador:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com