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 programático se refiere a la llamada a aplicaciones protegidas por IAP desde clientes que no son navegadores, como herramientas de línea de comandos, llamadas de servicio a servicio y aplicaciones móviles. En función de tu caso práctico, 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.

Incluye estas credenciales en IAP en el encabezado HTTP Authorization o Proxy-Authorization de la solicitud.

Antes de empezar

Antes de empezar, asegúrate de que tienes una aplicación protegida por 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 permitir que los usuarios accedan a tu aplicación desde una aplicación móvil o de escritorio para que un programa pueda interactuar con un recurso protegido con IAP.

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 Cómo compartir clientes de OAuth. Añade el ID de cliente de OAuth a la lista de permitidos para el acceso programático a la aplicación.
  2. Obtiene un token de ID para el ID de cliente de OAuth 2.0 del recurso 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

Cada desarrollador debe iniciar sesión para acceder a una aplicación protegida por compras en la aplicación. Puedes empaquetar el proceso en una secuencia de comandos, por ejemplo, con gcloud CLI. 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 de escritorio:

      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 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, sigue estos pasos:

  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. La dirección de correo se encuentra en el campo client_email del archivo JSON de la cuenta de servicio o se proporciona como entrada. Formato habitual: service-account@PROJECT_ID.iam.gserviceaccount.com

  • En el campo aud, especifique la URL exacta o la URL con un comodín de ruta (/*) del recurso protegido por la compra en la aplicación. Por ejemplo, https://example.com/ o https://example.com/*. Un JWT con la URL exacta en el campo aud solo puede acceder a esa URL específica. Un JWT con el comodín de ruta (/*) en el campo aud puede acceder a todas las URLs que tengan el prefijo de la cadena aud sin el * final.

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

Puede 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 el artículo 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 the service account that the
        JWT is created for.
        resource_url (str): Specifies the 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-secured application.

    Returns:
        str: A signed JWT that can be used to access IAP-secured applications.
            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.
    # Project should always be "-".
    # Replacing the wildcard character with a project ID is invalid.
    name = iam_client.service_account_path("-", 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 la gestión de identidades y accesos

    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.

Al firmar el JWT de forma local, incluye un encabezado de JWT 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 privada del archivo se usa para firmar el JWT.

Acceder a la aplicación

Para acceder a la aplicación, incluye el JWT firmado en el encabezado Authorization:

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

Autenticarse con un token OIDC de cuenta de servicio

  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 envíes 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.