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. Obtén información sobre las credenciales de 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. Obtén más Información sobre las 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 un ID de cliente de OAuth 2.0 para tu aplicación para dispositivos móviles en el mismo proyecto que el recurso protegido con IAP:
    1. Ve a la página Credenciales.
      Ir a la página Credenciales
    2. Selecciona el proyecto con el recurso protegido con IAP.
    3. Haz clic en Crear credenciales y, luego, selecciona ID de cliente de OAuth.
    4. Selecciona el tipo de aplicación para la que quieres crear credenciales.
    5. Agrega un Nombre y Restricciones si corresponden y, luego, haz clic en Crear.
  2. En la ventana Cliente de OAuth que aparece, toma nota del ID de cliente del recurso protegido con IAP al que deseas conectarte.
  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.

Configuración del ID de cliente

Para permitir que los desarrolladores accedan a tu aplicación desde la línea de comandos, primero deberás crear credenciales para el ID de cliente de OAuth del tipo app de escritorio:

  1. Ve a la página Credenciales.
    Ir a la página Credenciales
  2. Selecciona el proyecto con el recurso protegido con IAP.
  3. Haz clic en Crear credenciales y selecciona ID de cliente de OAuth.
  4. En Tipo de aplicación, selecciona App de escritorio, agrega un Nombre y, a continuación, haz clic en Crear.
  5. En la ventana del cliente OAuth que aparece a continuación, toma nota del ID de cliente y del secreto del cliente. Los necesitarás en una secuencia de comandos para poder administrar las credenciales o compartirlos con los desarrolladores.
  6. En la ventana Credenciales, podrás ver tus nuevas credenciales de App de escritorio junto con el ID de cliente principal que se utiliza para acceder a tu aplicación.

Accede a la aplicación

Todos los desarrolladores que quieran tener acceso a una aplicación protegida con IAP deberán primero acceder. Puedes empaquetar el proceso en una secuencia de comandos, por ejemplo, mediante el SDK de Cloud. 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. Ve al URI siguiente, en el que DESKTOP_CLIENT_ID es el ID de cliente de la app de escritorio que creaste anteriormente:

    https://accounts.google.com/o/oauth2/v2/auth?client_id=DESKTOP_CLIENT_ID&response_type=code&scope=openid%20email&access_type=offline&redirect_uri=urn:ietf:wg:oauth:2.0:oob

  3. En la ventana que aparece, toma nota del código de autorización para reemplazar AUTH_CODE con el ID de cliente de la app de escritorio y el secreto que creaste anteriormente:

    curl --verbose \
          --data client_id=DESKTOP_CLIENT_ID \
          --data client_secret=DESKTOP_CLIENT_SECRET \
          --data code=AUTH_CODE \
          --data redirect_uri=urn:ietf:wg:oauth:2.0:oob \
          --data grant_type=authorization_code \
          https://oauth2.googleapis.com/token

    Este código muestra un objeto JSON con un campo refresh_token que puedes guardar como un token de acceso a la aplicación.

Accede a la aplicación

Para acceder a la aplicación, intercambiarás el refresh_token generado durante el flujo de acceso por un token de ID. El token de ID es válido durante aproximadamente una hora, durante la cual puedes realizar varias solicitudes a una aplicación específica. A continuación se muestra un ejemplo con curl para usar el token y acceder a la aplicación:

  1. Usa el código que aparece a continuación, donde REFRESH_TOKEN es el token del flujo de acceso, IAP_CLIENT_ID es el principal ID de cliente utilizado para acceder a tu aplicación y DESKTOP_CLIENT_ID y DESKTOP_CLIENT_SECRET son el ID de cliente y el secreto que creaste después de la configuración del ID de cliente que aparece antes:

    curl --verbose \
          --data client_id=DESKTOP_CLIENT_ID \
          --data client_secret=DESKTOP_CLIENT_SECRET \
          --data refresh_token=REFRESH_TOKEN \
          --data grant_type=refresh_token \
          --data audience=IAP_CLIENT_ID \
          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.

  2. Usa el id_token de la siguiente manera a fin de acceder a la aplicación:

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

Autenticación desde una cuenta de servicio

Usa un token de OpenID Connect (OIDC) para autenticar una cuenta de servicio con un recurso protegido con IAP. Sigue estos pasos para encontrar tu ID de cliente:

  1. Ve a la página de IAP.
  2. Encuentra el recurso al que deseas acceder y, luego, haz clic en Más > Editar cliente de OAuth.
    editar el cliente OAuth en el menú Más

  3. En la página Credenciales que aparece a continuación, toma nota del ID de cliente.

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 indica cómo obtener un token de OIDC. Sin importar cuál elijas, debes incluir el token en un encabezado Authorization: Bearer para realizar la solicitud autenticada al recurso protegido con IAP.

Obtén 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 código de muestra a fin de generar el token para 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="credentialsFilePath">Path to the credentials .json file
    /// downloaded from 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 credentialsFilePath, 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, credentialsFilePath, cancellationToken).ConfigureAwait(false);

        // 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).ConfigureAwait(false);

        // 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).ConfigureAwait(false);
    }

    /// <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="credentialsFilePath">Path to the credentials .json file
    /// downloaded from 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, string credentialsFilePath, CancellationToken cancellationToken)
    {
        // Read credentials from the credentials .json file.
        GoogleCredential credential = await GoogleCredential
            .FromFileAsync(credentialsFilePath, cancellationToken).ConfigureAwait(false);

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

Go

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: %v", err)
	}

	response, err := client.Do(request)
	if err != nil {
		return fmt.Errorf("client.Do: %v", err)
	}
	defer response.Body.Close()
	if _, err := io.Copy(w, response.Body); err != nil {
		return fmt.Errorf("io.Copy: %v", 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 signed JWT 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 signed jwt token.
   * @throws IOException exception creating signed JWT
   */
  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

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.
 *
 * @return The response body.
 */
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
    return $client->get($url);
}

Python

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

# 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

Obtén un token de OIDC desde un archivo de claves de una 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.

Obtén 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 basado en un token de acceso para otra cuenta de servicio justo antes de acceder a un recurso protegido con IAP:

  1. Agrega la cuenta en el token de acceso con la función service account token creator a la cuenta de destino. Esto garantiza que tenga el permiso de IAM requerido a fin de crear un token de OIDC para la cuenta de servicio de destino.
  2. Llama a generateIdToken en la cuenta de servicio de destino con el token de acceso. Presta especial atención para configurar el campo audience con el ID de cliente.

¿Qué sigue?