Autenticación programática

En este documento se describe cómo autenticarse en un recurso protegido por IAP desde una cuenta de usuario o una cuenta de servicio.

El acceso automático es el caso en el que llamas a aplicaciones protegidas por compras en aplicaciones desde clientes que no son navegadores. Esto incluye herramientas de línea de comandos, llamadas de servicio a servicio y aplicaciones móviles. En función de tu caso de uso, puede que quieras autenticarte en IAP con credenciales de usuario o de servicio.

  • Una cuenta de usuario pertenece a un usuario concreto. Autenticas una cuenta de usuario cuando tu aplicación requiere acceso a recursos protegidos mediante IAP en nombre de un usuario. Para obtener más información, consulta el artículo Cuentas de usuario.

  • Una cuenta de servicio representa una aplicación en lugar de a un usuario concreto. Autenticas una cuenta de servicio cuando quieres permitir que una aplicación acceda a tus recursos protegidos con IAP. Para obtener más información, consulta el artículo Cuentas de servicio.

IAP admite los siguientes tipos de credenciales para el acceso programático:

  • Token de ID de OAuth 2.0: token emitido por Google para un usuario humano o una cuenta de servicio con la reclamación de audiencia definida como el ID de recurso de la aplicación IAP.
  • JWT firmado por una cuenta de servicio: un token JWT autofirmado o emitido por Google para una cuenta de servicio.

Transfiere estas credenciales a IAP en el encabezado HTTP Authorization o Proxy-Authorization.

Antes de empezar

Antes de empezar, necesitarás una aplicación protegida con compras en la aplicación a la que quieras conectarte mediante programación con una cuenta de desarrollador, una cuenta de servicio o credenciales de aplicación móvil.

Autenticar una cuenta de usuario

Puedes habilitar el acceso de los usuarios a tu aplicación desde una aplicación para ordenadores o móviles para permitir que un programa interactúe con un recurso protegido por una compra en la aplicación.

Autenticar desde una aplicación móvil

  1. Crea o usa un ID de cliente de OAuth 2.0 para tu aplicación móvil. Para usar un ID de cliente de OAuth 2.0, sigue los pasos que se indican en el artículo Cómo compartir clientes de OAuth. Añade el ID de cliente de OAuth a la lista de permitidos para el acceso programático de la aplicación.
  2. Obtén un token de ID para el ID de cliente protegido por IAP.
  3. Incluye el token de ID en un encabezado Authorization: Bearer para hacer la solicitud autenticada al recurso protegido mediante IAP.

Autenticar 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 aplicaciones de escritorio o comparte un ID de cliente de OAuth para aplicaciones de escritorio que ya tengas.
  2. Añade el ID de OAuth a la lista de permitidos para el acceso programático de la aplicación.

Iniciar sesión en la aplicación

Todos los desarrolladores que quieran acceder a una aplicación protegida por compras en la aplicación deberán iniciar sesión primero. Puedes empaquetar el proceso en una secuencia de comandos, por ejemplo, con la CLI de gcloud. En el siguiente ejemplo se usa curl para iniciar sesión y generar un token que se puede usar para acceder a la aplicación:

  1. Inicia sesión en la cuenta que tiene acceso al Google Cloud recurso.
  2. Inicia un servidor local que pueda replicar las solicitudes entrantes.

      # Example using Netcat (http://netcat.sourceforge.net/)
      nc -k -l 4444
    
  3. Ve al siguiente URI, donde DESKTOP_CLIENT_ID es el ID de cliente de la aplicación para ordenadores:

      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 la salida del servidor local, busca los parámetros de la solicitud:

      GET /?code=CODE&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email&hd=google.com&prompt=consent HTTP/1.1
    
  5. Copia el valor de CODE para sustituir AUTH_CODE en el siguiente comando, junto con el ID y el secreto de cliente de la aplicación de escritorio:

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

    Este comando devuelve un objeto JSON con un campo id_token que puedes usar para acceder a la aplicación.

Acceder a la aplicación

Para acceder a la aplicación, usa el id_token:

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

Token de actualización

Puedes usar el token de actualización generado durante el flujo de inicio de sesión para obtener nuevos tokens de ID. Esto resulta útil cuando caduca el token de ID original. Cada token de ID es válido durante aproximadamente una hora, tiempo durante el cual puedes hacer varias solicitudes a una aplicación específica.

En el siguiente ejemplo se usa curl para usar el token de actualización y obtener un nuevo token de ID. En este ejemplo, REFRESH_TOKEN es el token del flujo de inicio de sesión. DESKTOP_CLIENT_ID y DESKTOP_CLIENT_SECRET son los mismos que se usan en el flujo de inicio de sesión:

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 comando devuelve un objeto JSON con un nuevo campo id_token que puedes usar para acceder a la aplicación.

Autenticar 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 por IAP. En la siguiente tabla se describen algunas de las diferencias entre los distintos tokens de autenticación y sus funciones.

Funciones de Authentication JWT de cuenta de servicio Token de OpenID Connect
Cuándo se puede usar el acceso contextual
Requisito de ID de cliente de OAuth 2.0
Ámbito del token URL del recurso protegido mediante IAP ID de cliente de OAuth 2.0

Autenticarse con un JWT de cuenta de servicio

IAP admite la autenticación JWT de cuentas de servicio para identidades de Google, Identity Platform y aplicaciones configuradas con federación de identidades de los empleados.

Para autenticar una cuenta de servicio mediante un JWT, se deben seguir estos pasos principales:

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

    Este rol concede a las entidades principales permiso para crear credenciales de corta duración, como JWTs.

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

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

Crear el JWT

El JWT creado debe tener una carga útil similar a la del 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 de la cuenta de servicio. Se encuentra en el campo client_email del archivo JSON de la cuenta de servicio o se transfiere. Formato habitual: service-account@PROJECT_ID.iam.gserviceaccount.com

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

  • En el campo iat, especifica la hora actual de la época de Unix y, en el campo exp, especifica una hora que sea 3600 segundos posterior. Define cuándo caduca 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 acceder directamente a una clave privada.
  • Usa un archivo de clave de credenciales local para firmar el JWT de forma local.
Firmar el JWT con la API Service Account Credentials de Gestión de Identidades y Accesos

Usa la API de credenciales de cuenta de servicio de IAM para firmar un JWT de cuenta de servicio. El método obtiene la clave privada asociada a 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. Para obtener más información, consulta Configurar la autenticación en 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
  1. Usa el siguiente comando de Google Cloud CLI para firmar la carga útil en claim.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 que puedes usar para acceder a tu recurso protegido mediante IAP.

Python

import datetime
import json

import google.auth
from google.cloud import iam_credentials_v1

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

    Creates a properly formatted JWT payload with standard claims (iss, sub, aud,
    iat, exp) needed for IAP authentication.

    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:
        str: JSON string containing the JWT payload with properly formatted claims.
    """
    # Create current time and expiration time (1 hour later) in UTC
    iat = datetime.datetime.now(tz=datetime.timezone.utc)
    exp = iat + datetime.timedelta(seconds=3600)

    # Convert datetime objects to numeric timestamps (seconds since epoch)
    # as required by JWT standard (RFC 7519)
    payload = {
        "iss": service_account_email,
        "sub": service_account_email,
        "aud": resource_url,
        "iat": int(iat.timestamp()),
        "exp": int(exp.timestamp()),
    }

    return json.dumps(payload)

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

    Uses Google Cloud's IAM Credentials API to sign a JWT. This requires the
    caller to have iap.webServiceVersions.accessViaIap permission on the target
    service account.

    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:
        str: A signed JWT that can be used to access IAP protected apps.
            Use in Authorization header as: 'Bearer <signed_jwt>'
    """
    # Get default credentials from environment or application credentials
    source_credentials, project_id = google.auth.default()

    # Initialize IAM credentials client with source credentials
    iam_client = iam_credentials_v1.IAMCredentialsClient(credentials=source_credentials)

    # Generate the service account resource name
    # If project_id is None, use '-' as placeholder as per API requirements
    project = project_id if project_id else "-"
    name = iam_client.service_account_path(project, target_sa)

    # Create and sign the JWT payload
    payload = generate_jwt_payload(target_sa, resource_url)

    # Sign the JWT using the IAM credentials API
    response = iam_client.sign_jwt(name=name, payload=payload)

    return response.signed_jwt

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

    API Service Account Credentials:

    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"
    

    Si la solicitud se realiza correctamente, se devuelve un JWT firmado en la respuesta.

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

Firmar el JWT desde un archivo de clave de credenciales local

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

Si tienes un archivo de clave 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. En el campo kid del encabezado, usa el ID de la clave privada de la cuenta de servicio, que se encuentra en el campo private_key_id del archivo JSON de las credenciales de la cuenta de servicio. La clave también se usa para firmar el JWT.

Acceder a la aplicación

En todos los casos, para acceder a la aplicación, usa signed-jwt:

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

Autenticarse con un token de OIDC

  1. Crea o usa un ID de cliente de OAuth 2.0. Para usar un ID de cliente de OAuth 2.0 que ya tengas, sigue los pasos que se indican en el artículo Cómo compartir clientes de OAuth.
  2. Añade el ID de OAuth a la lista de permitidos para el acceso programático de la aplicación.
  3. Asegúrate de que la cuenta de servicio predeterminada se haya añadido a la lista de acceso del proyecto protegido por IAP.

Cuando hagas solicitudes al recurso protegido mediante IAP, debes incluir el token en el encabezado Authorization: Authorization: 'Bearer OIDC_TOKEN'

En los siguientes ejemplos de código se muestra cómo obtener un token de OIDC.

Obtener un token de OIDC para la cuenta de servicio predeterminada

Para obtener un token de OIDC de la cuenta de servicio predeterminada de Compute Engine, App Engine o Cloud Run, consulta el siguiente ejemplo de código para generar un token con el que acceder a un recurso protegido por IAP:

C#

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


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. Para obtener más información, consulta el artículo Configurar la autenticación en 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

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.


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

Para autenticarte en IAP, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

/**
 * 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.fetch(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. Para obtener más información, consulta el artículo Configurar la autenticación en 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. Para obtener más información, consulta el artículo Configurar la autenticación en 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. Para obtener más información, consulta el artículo Configurar la autenticación en 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

Obtener un token de OIDC de un archivo de clave de cuenta de servicio local

Para generar un token de OIDC con un archivo de clave de cuenta de servicio, usarás el archivo de clave para crear y firmar una aserción JWT. Después, intercambiarás esa aserción por un token de ID. La siguiente secuencia de comandos de Bash muestra este proceso:

Bash

#!/usr/bin/env bash
#
# Example script that generates an OIDC token using a service account key file
# and uses it to access an IAP-secured resource

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}"

  # Define the scope and token endpoint
  local iam_scope="https://www.googleapis.com/auth/iam"
  local oauth_token_uri="https://www.googleapis.com/oauth2/v4/token"

  # Extract data from service account key file
  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')"

  # Set token timestamps (current time and expiration 10 minutes later)
  local issued_at="$(date +%s)"
  local expires_at="$((issued_at + 600))"

  # Create JWT header and payload
  local header="{'alg':'RS256','typ':'JWT','kid':'${private_key_id}'}"
  local header_base64="$(echo "${header}" | base64 | tr -d '\n')"
  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 | tr -d '\n')"

  # Create JWT signature using the private key
  local signature_base64="$(printf %s "${header_base64}.${payload_base64}" | openssl dgst -binary -sha256 -sign <(printf '%s\n' "${private_key}")  | base64 | tr -d '\n')"
  local assertion="${header_base64}.${payload_base64}.${signature_base64}"

  # Exchange the signed JWT assertion for an ID token
  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)"

  # Extract just the ID token from the response
  local bearer_id_token="$(echo "${token_payload}" | jq -r '.id_token')"
  echo "${bearer_id_token}"
}

main() {
  # Check if required arguments are provided
  if [[ $# -lt 3 ]]; then
    echo "Usage: $0 <service_account_key_file.json> <iap_client_id> <url>"
    exit 1
  fi

  # Assign parameters to variables
  SERVICE_ACCOUNT_KEY="$1"
  IAP_CLIENT_ID="$2"
  URL="$3"

  # Generate the ID token
  echo "Generating token..."
  ID_TOKEN=$(get_token "${SERVICE_ACCOUNT_KEY}" "${IAP_CLIENT_ID}")

  # Access the IAP-secured resource with the token
  echo "Accessing: ${URL}"
  curl --header "Authorization: Bearer ${ID_TOKEN}" "${URL}"
}

# Run the main function with all provided arguments
main "$@"

Este script realiza los siguientes pasos:

  1. Extrae la información de la clave de la cuenta de servicio de tu archivo de claves JSON.
  2. Crea un JWT con los campos necesarios, incluido el ID de cliente de IAP como audiencia objetivo.
  3. Firma el JWT con la clave privada de la cuenta de servicio.
  4. Intercambia este JWT por un token de OIDC a través del servicio OAuth de Google.
  5. Usa el token resultante para hacer una solicitud autenticada a tu recurso protegido por IAP.

Para usar esta secuencia de comandos, haz lo siguiente:

  1. Guárdalo en un archivo. Por ejemplo: get_iap_token.sh
  2. Haz que sea ejecutable: chmod +x get_iap_token.sh
  3. Ejecútalo con tres parámetros:
  ./get_iap_token.sh service-account-key.json \
    OAUTH_CLIENT_ID \
    URL

Donde:

  • service-account-key.json es el archivo de clave de cuenta de servicio que has descargado.
  • OAUTH_CLIENT_ID es el ID de cliente de OAuth de tu recurso protegido con IAP
  • URL es la URL a la que quieres acceder

Obtener un token de OIDC en el resto de los casos

En el resto de los casos, usa la API de credenciales de IAM para generar un token de OIDC suplantando la identidad de una cuenta de servicio de destino justo antes de acceder a un recurso protegido por IAP. Este proceso implica los siguientes pasos:

  1. Asigna a la cuenta de servicio que hace la llamada (la cuenta de servicio asociada al código que obtiene el token de ID) el rol Creador de tokens de identidad OpenID Connect de cuenta de servicio (roles/iam.serviceAccountOpenIdTokenCreator).

    De esta forma, la cuenta de servicio que llama puede suplantar la identidad de la cuenta de servicio de destino.

  2. Usa las credenciales proporcionadas por la cuenta de servicio que llama para invocar el método generateIdToken en la cuenta de servicio de destino.

    Asigna al campo audience el valor de tu ID de cliente.

Para obtener instrucciones detalladas, consulta el artículo Crear un token de ID.

Autenticar desde el encabezado Proxy-Authorization

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, IAP autoriza la solicitud con él. Después de autorizar la solicitud, la compra en la aplicación pasa el encabezado Authorization a tu aplicación sin procesar el contenido.

Si no se encuentra ningún token de ID válido en el encabezado Proxy-Authorization, IAP sigue procesando el encabezado Authorization y elimina el encabezado Proxy-Authorization antes de enviar la solicitud a tu aplicación.

Siguientes pasos