Autenticación programática

En esta página, se describe cómo autenticar una cuenta de usuario o una cuenta de servicio con un recurso seguro de Identity-Aware Proxy (IAP).

  • Una cuenta de usuario pertenece a un usuario individual. Debes autenticarla cuando tu aplicación requiera acceso a recursos protegidos con IAP en nombre de un usuario. Para obtener más información, consulta Cuentas de usuario.

  • Una cuenta de servicio pertenece a una aplicación y no a un usuario individual. Debes autenticarla cuando desees permitir que una aplicación acceda a tus recursos protegidos con IAP. Para obtener más información, consulta Cuentas de servicio.

Antes de comenzar

Necesitarás lo siguiente antes de comenzar:

  • Una aplicación protegida con IAP a la que deseas conectarte de manera programática con una cuenta de desarrollador, una cuenta de servicio o credenciales de aplicación para dispositivos móviles.

Autentica una cuenta de usuario

Puedes permitir que los usuarios accedan a tu aplicación, desde una app para dispositivos móviles o de escritorio, de tal forma que el programa interactúe con un recurso protegido con IAP.

Autenticación desde una aplicación para dispositivos móviles

  1. Crea o usa un ID de cliente de OAuth 2.0 existente para tu app para dispositivos móviles. Para usar un ID de cliente de OAuth 2.0 existente, sigue los pasos que se indican en Cómo compartir clientes de OAuth.
  2. Agrega a la lista de entidades permitidas el ID de cliente de OAuth para el acceso programático de la aplicación.
  3. Obtén un token de ID para el ID de cliente protegido con IAP.
  4. Incluye el token de ID en un encabezado Authorization: Bearer a fin de realizar la solicitud autenticada para el recurso protegido con IAP.

Autenticación desde una aplicación de escritorio

En esta sección se describe cómo autenticar una cuenta de usuario desde una línea de comandos de escritorio.

  1. Para permitir que los desarrolladores accedan a tu aplicación desde la línea de comandos, crea un ID de cliente de OAuth 2.0 para computadoras o comparte un ID de cliente de OAuth para computadoras existente.
  2. Agrega a la lista de entidades permitidas el ID de cliente de OAuth para el acceso programático de la aplicación.

Accede a la aplicación

Todos los desarrolladores que quieran acceder a una aplicación protegida con IAP deberán primero acceder. Puedes empaquetar el proceso en una secuencia de comandos, por ejemplo, mediante gcloud CLI. A continuación se muestra un ejemplo del uso de curl para ingresar y generar un token que se puede usar a fin de acceder a la aplicación:

  1. Ingresa a tu cuenta que tiene acceso al recurso de Google Cloud.
  2. Inicia un servidor local que pueda repetir las solicitudes entrantes.
        $ nc -k -l 4444
        
    NOTA: El comando usa la utilidad NetCat. Puedes usar la utilidad que elijas.
  3. Ve al siguiente URI, en el que DESKTOP_CLIENT_ID es el ID de cliente de la app para computadoras:
    https://accounts.google.com/o/oauth2/v2/auth?client_id=DESKTOP_CLIENT_ID&response_type=code&scope=openid%20email&access_type=offline&redirect_uri=http://localhost:4444&cred_ref=true
  4. En el resultado del servidor local, busca los parámetros de solicitud. Deberías ver algo similar a lo siguiente: GET /?code=$CODE&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email&hd=google.com&prompt=consent HTTP/1.1 copia el CÓDIGO para reemplazar AUTH_CODE a continuación junto con el ID de cliente y el secreto de la app de escritorio:

    curl --verbose \
          --data client_id=DESKTOP_CLIENT_ID \
          --data client_secret=DESKTOP_CLIENT_SECRET \
          --data code=AUTH_CODE \
          --data redirect_uri=http://localhost:4444 \
          --data grant_type=authorization_code \
          https://oauth2.googleapis.com/token

    Este código muestra un objeto JSON con un campo id_token que puedes usar para acceder a la aplicación.

Accede a la aplicación

Para acceder a la app, usa el id_token de la siguiente manera:

curl --verbose --header 'Authorization: Bearer ID_TOKEN' URL

Token de actualización

Puedes usar el token de actualización generado durante el flujo de acceso para obtener nuevos tokens de ID. Esto es útil cuando vence el token de ID original. Cada token de ID es válido durante aproximadamente una hora, durante la cual puedes realizar varias solicitudes a una app específica.

A continuación, se muestra un ejemplo del uso de curl para usar el token de actualización y obtener un nuevo token de ID. En el siguiente ejemplo, REFRESH_TOKEN es el token del flujo de acceso. DESKTOP_CLIENT_ID y DESKTOP_CLIENT_SECRET son los mismos que se usan en el flujo de acceso:

curl --verbose \
--data client_id=DESKTOP_CLIENT_ID \
--data client_secret=DESKTOP_CLIENT_SECRET \
--data refresh_token=REFRESH_TOKEN \
--data grant_type=refresh_token \
https://oauth2.googleapis.com/token

Este código muestra un objeto JSON con un nuevo campo id_token que puedes usar para acceder a la app.

Autentica una cuenta de servicio

Puedes usar un JWT de cuenta de servicio o un token de OpenID Connect (OIDC) para autenticar una cuenta de servicio con un recurso protegido con IAP. En la siguiente tabla, se describen algunas de las diferencias entre los diferentes tokens de autenticación y sus funciones.

Funciones de Authentication JWT de la cuenta de servicio Token de OpenID Connect
Compatibilidad con el acceso adaptado al contexto
Requisito de ID de cliente de OAuth 2.0
Alcance del token URL del recurso protegido con IAP ID de cliente de OAuth 2.0

Cómo autenticar con un JWT de una cuenta de servicio

La autenticación de una cuenta de servicio con un JWT incluye los siguientes pasos principales:

  1. Otorga a la cuenta de servicio que realiza la llamada el rol de Creador de tokens de cuenta de servicio (roles/iam.serviceAccountTokenCreator).

    El rol les otorga a las principales permiso para crear credenciales de corta duración, como los JWT.

  2. Crea un JWT para el recurso protegido por IAP.

  3. Firma el JWT con la clave privada de la cuenta de servicio.

Crea el JWT

El JWT creado debe tener una carga útil similar al siguiente ejemplo:

{
  "iss": SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "sub": SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "aud": TARGET_URL,
  "iat": IAT,
  "exp": EXP,
}
  • En los campos iss y sub, especifica la dirección de correo electrónico de la cuenta de servicio. Se encuentra en el campo client_email del archivo JSON de la cuenta de servicio o se pasa. Formato típico: service-account@PROJECT_ID.iam.gserviceaccount.com

  • En el campo aud, especifica la URL del recurso protegido por IAP.

  • Para el campo iat, especifica la hora actual de la época de Unix y, para el campo exp, especifica una hora dentro de 3,600 segundos después. Esto define cuándo vence el JWT.

Firma el JWT

Puedes usar uno de los siguientes métodos para firmar el JWT:

  • Usa la API de credenciales de IAM para firmar un JWT sin necesidad de acceso directo a una clave privada.
  • Usa un archivo de claves de credenciales local para firmar el JWT de forma local.

Firma el JWT con la API de credenciales de la cuenta de servicio de IAM

Usa la API de credenciales de la cuenta de servicio de IAM para firmar un JWT de cuenta de servicio. El método recupera la clave privada asociada con tu cuenta de servicio y la usa para firmar la carga útil del JWT. Esto permite firmar un JWT sin acceso directo a una clave privada.

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

gcloud

  1. Ejecuta el siguiente comando para preparar una solicitud con la carga útil del JWT:

    cat > claim.json << EOM
    {
      "iss": "SERVICE_ACCOUNT_EMAIL_ADDRESS",
      "sub": "SERVICE_ACCOUNT_EMAIL_ADDRESS",
      "aud": "TARGET_URL",
      "iat": $(date +%s),
      "exp": $((`date +%s` + 3600))
    }
    EOM
    
  2. Usa el siguiente comando de Google Cloud CLI para firmar la carga útil en request.json:

    gcloud iam service-accounts sign-jwt --iam-account=SERVICE_ACCOUNT_EMAIL_ADDRESS claim.json output.jwt
    

    Si la solicitud se realiza correctamente, output.jwt contiene un JWT firmado.

  3. Usa el JWT para acceder a tu recurso protegido por IAP.

Python

import datetime
import json

import google.auth
from google.cloud import iam_credentials_v1
import jwt

def generate_jwt_payload(service_account_email: str, resource_url: str) -> str:
  """Generates JWT payload for service account.

  The resource url provided must be the same as the url of the IAP secured resource.

  Args:
    service_account_email (str): Specifies service account JWT is created for.
    resource_url (str): Specifies scope of the JWT, the URL that the JWT will be allowed to access.
  Returns:
    A signed-jwt that can be used to access IAP protected applications.
    Access the application with the JWT in the Authorization Header.
    curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
  """
  iat = datetime.datetime.now(tz=datetime.timezone.utc)
  exp = iat + 3600
  return json.dumps({
      'iss': service_account_email,
      'sub': service_account_email,
      'aud': resource_url,
      'iat': iat,
      'exp': exp,
  })

def sign_jwt(target_sa: str, resource_url: str) -> str:
  """Signs JWT payload using ADC and IAM credentials API.

  Args:
    target_sa (str): Service Account JWT is being created for.
      iap.webServiceVersions.accessViaIap permission is required.
    resource_url (str): Audience of the JWT, and scope of the JWT token.
      This is the url of the IAP protected application.
  Returns:
    A signed-jwt that can be used to access IAP protected apps.
  """
  source_credentials, _ = google.auth.default()
  iam_client = iam_credentials_v1.IAMCredentialsClient(credentials=source_credentials)
  return iam_client.sign_jwt(
      name=iam_client.service_account_path('-', target_sa),
      payload=generate_jwt_payload(target_sa, resource_url),
  ).signed_jwt

Si la solicitud se realiza correctamente, la secuencia de comandos muestra un JWT firmado. Usa el JWT para acceder a tu recurso protegido por IAP.

curl

  1. Ejecuta el siguiente comando para preparar una solicitud con la carga útil del JWT:

    cat << EOF > request.json
    {
      "payload": JWT_PAYLOAD
    }
    EOF
    
  2. Firma el JWT con la API de credenciales de la cuenta de servicio de IAM:

    curl -X POST \ 
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \ 
    -H "Content-Type: application/json; charset=utf-8" \ 
    -d @request.json \ 
    "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL_ADDRESS:signJwt"

    Cuando se realiza una solicitud correctamente, se incluye un JWT firmado en la respuesta.

  3. Usa el JWT para acceder a tu recurso protegido por IAP.

Firma el JWT desde un archivo de claves de credenciales local

Los JWT se firman con la clave privada de la cuenta de servicio.

Si tienes un archivo de claves de cuenta de servicio, el JWT se puede firmar de forma local.

La secuencia de comandos envía un encabezado JWT junto con la carga útil. Para el campo kid del encabezado, usa el ID de clave privada de la cuenta de servicio, que se encuentra en el campo private_key_id del archivo JSON de credenciales de la cuenta de servicio. La clave también se usa para firmar el JWT.

Python

import time
import jwt
import json

def generate_jwt_payload(service_account_email, resource_url):
  """Generates JWT payload for service account.

  The resource url provided must be the same as the url of the IAP secured resource.

  Args:
    service_account_email (str): Specifies service account JWT is created for.
    resource_url (str): Specifies scope of the JWT, the URL that the JWT will be allowed to access.
  Returns:
    A signed-jwt that can be used to access IAP protected applications.
    Access the application with the JWT in the Authorization Header.
    curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
  """
  iat = datetime.datetime.now(tz=datetime.timezone.utc)
  exp = iat + 3600
  return json.dumps({
      'iss': service_account_email,
      'sub': service_account_email,
      'aud': resource_url,
      'iat': iat,
      'exp': exp,
  })

def sign_jwt_with_key_file(credential_key_file_path, resource_url):
  """Signs JWT payload using local service account credential key file.

  Args:
    credential_key_file_path (str): Path to the downloaded JSON credentials of the service
      account the JWT is being created for.
    resource_url (str): Scope of JWT token, This is the url of the IAP protected application.
  Returns:
    A service account JWT created with a downloaded private key.
  """
  with open(credential_key_file_path, 'r') as credential_key_file:
      key_data = json.load(credential_key_file)

  PRIVATE_KEY_ID_FROM_JSON = key_data["private_key_id"]
  PRIVATE_KEY_FROM_JSON = key_data["private_key"]
  SERVICE_ACCOUNT_EMAIL = key_data["client_email"]

  # Sign JWT with private key and store key id in the header
  additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
  payload = generate_jwt_payload(service_account_email=SERVICE_ACCOUNT_EMAIL, resource_url=resource_url)

  signed_jwt = jwt.encode(
      payload,
      PRIVATE_KEY_FROM_JSON,
      headers=additional_headers,
      algorithm='RS256',
  )
  return signed_jwt

El resultado es un JWT firmado.

Accede a la aplicación

En todos los casos, para acceder a la app, usa el signed-jwt de la siguiente manera:

curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL

Cómo autenticar con un token de OIDC

  1. Crea o usa un ID de cliente de OAuth 2.0 existente. Para usar un ID de cliente de OAuth 2.0 existente, sigue los pasos que se indican en Cómo compartir clientes de OAuth.
  2. Agrega a la lista de entidades permitidas el ID de cliente de OAuth para el acceso programático de la aplicación.

También debes agregar la cuenta de servicio a la lista de acceso del proyecto protegido con IAP. En las siguientes muestras de código, se muestra cómo obtener un token de OIDC. Debes incluir el token en un encabezado Authorization: Bearer para realizar la solicitud de autenticación al recurso protegido con IAP.

Cómo obtener un token de OIDC para la cuenta de servicio predeterminada

Si deseas obtener un token de OIDC para la cuenta de servicio predeterminada de Compute Engine, App Engine o Cloud Run, puedes usar el siguiente muestra de código para generar el token y acceder a un recurso protegido con IAP:

C#


using Google.Apis.Auth.OAuth2;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

public class IAPClient
{
    /// <summary>
    /// Makes a request to a IAP secured application by first obtaining
    /// an OIDC token.
    /// </summary>
    /// <param name="iapClientId">The client ID observed on 
    /// https://console.cloud.google.com/apis/credentials. </param>
    /// <param name="uri">HTTP URI to fetch.</param>
    /// <param name="cancellationToken">The token to propagate operation cancel notifications.</param>
    /// <returns>The HTTP response message.</returns>
    public async Task<HttpResponseMessage> InvokeRequestAsync(
        string iapClientId, string uri, CancellationToken cancellationToken = default)
    {
        // Get the OidcToken.
        // You only need to do this once in your application
        // as long as you can keep a reference to the returned OidcToken.
        OidcToken oidcToken = await GetOidcTokenAsync(iapClientId, cancellationToken);

        // Before making an HTTP request, always obtain the string token from the OIDC token,
        // the OIDC token will refresh the string token if it expires.
        string token = await oidcToken.GetAccessTokenAsync(cancellationToken);

        // Include the OIDC token in an Authorization: Bearer header to 
        // IAP-secured resource
        // Note: Normally you would use an HttpClientFactory to build the httpClient.
        // For simplicity we are building the HttpClient directly.
        using HttpClient httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        return await httpClient.GetAsync(uri, cancellationToken);
    }

    /// <summary>
    /// Obtains an OIDC token for authentication an IAP request.
    /// </summary>
    /// <param name="iapClientId">The client ID observed on 
    /// https://console.cloud.google.com/apis/credentials. </param>
    /// <param name="cancellationToken">The token to propagate operation cancel notifications.</param>
    /// <returns>The HTTP response message.</returns>
    public async Task<OidcToken> GetOidcTokenAsync(string iapClientId, CancellationToken cancellationToken)
    {
        // Obtain the application default credentials.
        GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync(cancellationToken);

        // Request an OIDC token for the Cloud IAP-secured client ID.
       return await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId), cancellationToken);
    }
}

Go

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

import (
	"context"
	"fmt"
	"io"
	"net/http"

	"google.golang.org/api/idtoken"
)

// makeIAPRequest makes a request to an application protected by Identity-Aware
// Proxy with the given audience.
func makeIAPRequest(w io.Writer, request *http.Request, audience string) error {
	// request, err := http.NewRequest("GET", "http://example.com", nil)
	// audience := "IAP_CLIENT_ID.apps.googleusercontent.com"
	ctx := context.Background()

	// client is a http.Client that automatically adds an "Authorization" header
	// to any requests made.
	client, err := idtoken.NewClient(ctx, audience)
	if err != nil {
		return fmt.Errorf("idtoken.NewClient: %w", err)
	}

	response, err := client.Do(request)
	if err != nil {
		return fmt.Errorf("client.Do: %w", err)
	}
	defer response.Body.Close()
	if _, err := io.Copy(w, response.Body); err != nil {
		return fmt.Errorf("io.Copy: %w", err)
	}

	return nil
}

Java


import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.auth.oauth2.IdTokenProvider;
import com.google.common.base.Preconditions;
import java.io.IOException;
import java.util.Collections;

public class BuildIapRequest {
  private static final String IAM_SCOPE = "https://www.googleapis.com/auth/iam";

  private static final HttpTransport httpTransport = new NetHttpTransport();

  private BuildIapRequest() {}

  private static IdTokenProvider getIdTokenProvider() throws IOException {
    GoogleCredentials credentials =
        GoogleCredentials.getApplicationDefault().createScoped(Collections.singleton(IAM_SCOPE));

    Preconditions.checkNotNull(credentials, "Expected to load credentials");
    Preconditions.checkState(
        credentials instanceof IdTokenProvider,
        String.format(
            "Expected credentials that can provide id tokens, got %s instead",
            credentials.getClass().getName()));

    return (IdTokenProvider) credentials;
  }

  /**
   * Clone request and add an IAP Bearer Authorization header with ID Token.
   *
   * @param request Request to add authorization header
   * @param iapClientId OAuth 2.0 client ID for IAP protected resource
   * @return Clone of request with Bearer style authorization header with ID Token.
   * @throws IOException exception creating ID Token
   */
  public static HttpRequest buildIapRequest(HttpRequest request, String iapClientId)
      throws IOException {

    IdTokenProvider idTokenProvider = getIdTokenProvider();
    IdTokenCredentials credentials =
        IdTokenCredentials.newBuilder()
            .setIdTokenProvider(idTokenProvider)
            .setTargetAudience(iapClientId)
            .build();

    HttpRequestInitializer httpRequestInitializer = new HttpCredentialsAdapter(credentials);

    return httpTransport
        .createRequestFactory(httpRequestInitializer)
        .buildRequest(request.getRequestMethod(), request.getUrl(), request.getContent());
  }
}

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const url = 'https://some.iap.url';
// const targetAudience = 'IAP_CLIENT_ID.apps.googleusercontent.com';

const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
  console.info(`request IAP ${url} with target audience ${targetAudience}`);
  const client = await auth.getIdTokenClient(targetAudience);
  const res = await client.request({url});
  console.info(res.data);
}

request().catch(err => {
  console.error(err.message);
  process.exitCode = 1;
});

PHP

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

namespace Google\Cloud\Samples\Iap;

# Imports Auth libraries and Guzzle HTTP libraries.
use Google\Auth\ApplicationDefaultCredentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;

/**
 * Make a request to an application protected by Identity-Aware Proxy.
 *
 * @param string $url The Identity-Aware Proxy-protected URL to fetch.
 * @param string $clientId The client ID used by Identity-Aware Proxy.
 */
function make_iap_request($url, $clientId)
{
    // create middleware, using the client ID as the target audience for IAP
    $middleware = ApplicationDefaultCredentials::getIdTokenMiddleware($clientId);
    $stack = HandlerStack::create();
    $stack->push($middleware);

    // create the HTTP client
    $client = new Client([
        'handler' => $stack,
        'auth' => 'google_auth'
    ]);

    // make the request
    $response = $client->get($url);
    print('Printing out response body:');
    print($response->getBody());
}

Python

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

from google.auth.transport.requests import Request
from google.oauth2 import id_token
import requests


def make_iap_request(url, client_id, method="GET", **kwargs):
    """Makes a request to an application protected by Identity-Aware Proxy.

    Args:
      url: The Identity-Aware Proxy-protected URL to fetch.
      client_id: The client ID used by Identity-Aware Proxy.
      method: The request method to use
              ('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
      **kwargs: Any of the parameters defined for the request function:
                https://github.com/requests/requests/blob/master/requests/api.py
                If no timeout is provided, it is set to 90 by default.

    Returns:
      The page body, or raises an exception if the page couldn't be retrieved.
    """
    # Set the default timeout, if missing
    if "timeout" not in kwargs:
        kwargs["timeout"] = 90

    # Obtain an OpenID Connect (OIDC) token from metadata server or using service
    # account.
    open_id_connect_token = id_token.fetch_id_token(Request(), client_id)

    # Fetch the Identity-Aware Proxy-protected URL, including an
    # Authorization header containing "Bearer " followed by a
    # Google-issued OpenID Connect token for the service account.
    resp = requests.request(
        method,
        url,
        headers={"Authorization": "Bearer {}".format(open_id_connect_token)},
        **kwargs
    )
    if resp.status_code == 403:
        raise Exception(
            "Service account does not have permission to "
            "access the IAP-protected application."
        )
    elif resp.status_code != 200:
        raise Exception(
            "Bad response from application: {!r} / {!r} / {!r}".format(
                resp.status_code, resp.headers, resp.text
            )
        )
    else:
        return resp.text

Ruby

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

# url = "The Identity-Aware Proxy-protected URL to fetch"
# client_id = "The client ID used by Identity-Aware Proxy"
require "googleauth"
require "faraday"

# The client ID as the target audience for IAP
id_token_creds = Google::Auth::Credentials.default target_audience: client_id

headers = {}
id_token_creds.client.apply! headers

resp = Faraday.get url, nil, headers

if resp.status == 200
  puts "X-Goog-Iap-Jwt-Assertion:"
  puts resp.body
else
  puts "Error requesting IAP"
  puts resp.status
  puts resp.headers
end

Cómo obtener un token de OIDC desde un archivo de claves de cuenta de servicio local

Si tienes un archivo de claves de cuenta de servicio, puedes adaptar las muestras de código anteriores para proporcionar el archivo de claves de la cuenta de servicio.

Bash

  #!/usr/bin/env bash
  set -euo pipefail

  get_token() {
    # Get the bearer token in exchange for the service account credentials.
    local service_account_key_file_path="${1}"
    local iap_client_id="${2}"

    local iam_scope="https://www.googleapis.com/auth/iam"
    local oauth_token_uri="https://www.googleapis.com/oauth2/v4/token"

    local private_key_id="$(cat "${service_account_key_file_path}" | jq -r '.private_key_id')"
    local client_email="$(cat "${service_account_key_file_path}" | jq -r '.client_email')"
    local private_key="$(cat "${service_account_key_file_path}" | jq -r '.private_key')"
    local issued_at="$(date +%s)"
    local expires_at="$((issued_at + 600))"
    local header="{'alg':'RS256','typ':'JWT','kid':'${private_key_id}'}"
    local header_base64="$(echo "${header}" | base64)"
    local payload="{'iss':'${client_email}','aud':'${oauth_token_uri}','exp':${expires_at},'iat':${issued_at},'sub':'${client_email}','target_audience':'${iap_client_id}'}"
    local payload_base64="$(echo "${payload}" | base64)"
    local signature_base64="$(printf %s "${header_base64}.${payload_base64}" | openssl dgst -binary -sha256 -sign <(printf '%s\n' "${private_key}")  | base64)"
    local assertion="${header_base64}.${payload_base64}.${signature_base64}"
    local token_payload="$(curl -s \
      --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
      --data-urlencode "assertion=${assertion}" \
      https://www.googleapis.com/oauth2/v4/token)"
    local bearer_id_token="$(echo "${token_payload}" | jq -r '.id_token')"
    echo "${bearer_id_token}"
  }

  main(){
    # TODO: Replace the following variables:
    SERVICE_ACCOUNT_KEY="service_account_key_file_path"
    IAP_CLIENT_ID="iap_client_id"
    URL="application_url"

    # Obtain the ID token.
    ID_TOKEN=$(get_token "${SERVICE_ACCOUNT_KEY}" "${IAP_CLIENT_ID}")
    # Access the application with the ID token.
    curl --header "Authorization: Bearer ${ID_TOKEN}" "${URL}"
  }

  main "$@"

Cómo obtener un token de OIDC en todos los demás casos

En todos los demás casos, usa la API de credenciales de IAM paragenerar un token de OIDC a través de la suplantación de identidad de una cuenta de servicio objetivo justo antes de acceder a un recurso protegido con IAP. Este proceso implica los siguientes pasos:

  1. Proporciona a la cuenta de servicio que realiza la llamada (la cuenta de servicio asociada con el código que obtiene el token de ID) el rol de creador de tokens de identidad de OpenID Connect para cuentas de servicio (roles/iam.serviceAccountOpenIdTokenCreator).

    Esto le permite a la cuenta de servicio que realiza la llamada imitar la cuenta de servicio de destino.

  2. Usa las credenciales que proporciona la cuenta de servicio que realiza la llamada para invocar el método generateIdToken en la cuenta de servicio de destino.

    Establece el campo audience en tu ID de cliente.

Para obtener instrucciones paso a paso, consulta Crea un token de ID.

Autenticación desde el encabezado de autorización de proxy

Si tu aplicación usa el encabezado de solicitud Authorization, puedes incluir el token de ID en un encabezado Proxy-Authorization: Bearer. Si se encuentra un token de ID válido en un encabezado Proxy-Authorization, la IAP autoriza la solicitud con él. Después de autorizar la solicitud, el IAP pasa el encabezado Authorization a tu aplicación sin procesar el contenido.

Si no se encuentra un token de ID válido en el encabezado Proxy-Authorization, la IAP continúa procesando el encabezado Authorization y quita el encabezado Proxy-Authorization antes de pasar la solicitud a tu aplicación.

¿Qué sigue?