Autenticação programática

Este documento descreve como autenticar um recurso protegido pelo IAP a partir de uma conta de utilizador ou uma conta de serviço.

O acesso programático é o cenário em que chama aplicações protegidas por IAP a partir de clientes não baseados no navegador. Isto inclui ferramentas de linha de comandos, chamadas de serviço para serviço e aplicações para dispositivos móveis. Consoante o seu exemplo de utilização, pode querer autenticar-se no IAP através de credenciais de utilizador ou credenciais de serviço.

  • Uma conta de utilizador pertence a um utilizador individual. Autentica uma conta de utilizador quando a sua aplicação requer acesso a recursos protegidos pelo IAP em nome de um utilizador. Para mais informações, consulte o artigo Contas de utilizador.

  • Uma conta de serviço representa uma aplicação em vez de um utilizador individual. Autentica uma conta de serviço quando quer permitir que uma aplicação aceda aos seus recursos protegidos pelo IAP. Para mais informações, consulte o artigo Contas de serviço.

As IAP suportam o seguinte tipo de credenciais para acesso programático:

  • Token de ID do OAuth 2.0: um token emitido pela Google para um utilizador humano ou uma conta de serviço com a reivindicação de público-alvo definida para o ID do recurso da aplicação IAP.
  • JWT assinado pela conta de serviço: um token JWT autoassinado ou emitido pela Google para uma conta de serviço.

Transmita estas credenciais para a IAP no cabeçalho HTTP Authorization ou Proxy-Authorization.

Antes de começar

Antes de começar, precisa de uma aplicação protegida por IAP à qual quer ligar programaticamente através de uma conta de programador, uma conta de serviço ou credenciais de app para dispositivos móveis.

Autentique uma conta de utilizador

Pode ativar o acesso do utilizador à sua app a partir de uma app para computador ou dispositivo móvel para permitir que um programa interaja com um recurso protegido por IAP.

Autentique a partir de uma app para dispositivos móveis

  1. Crie ou use um ID de cliente OAuth 2.0 existente para a sua app para dispositivos móveis. Para usar um ID de cliente OAuth 2.0 existente, siga os passos em Como partilhar clientes OAuth. Adicione o ID de cliente OAuth à lista de autorizações para acesso programático à aplicação.
  2. Obtenha um token de ID para o ID de cliente protegido pelo IAP.
  3. Inclua o token de ID num cabeçalho Authorization: Bearer para fazer o pedido autenticado ao recurso protegido pelo IAP.

Autentique a partir de uma app para computador

Esta secção descreve como autenticar uma conta de utilizador a partir de uma linha de comandos do computador.

  1. Para permitir que os programadores acedam à sua aplicação a partir da linha de comandos, crie um ID de cliente OAuth 2.0 para computador ou partilhe um ID de cliente OAuth para computador existente.
  2. Adicione o ID OAuth à lista de autorizações para acesso programático para a aplicação.

Inicie sessão na aplicação

Cada programador que queira aceder a uma app protegida por CAs tem de iniciar sessão primeiro. Pode agrupar o processo num script, por exemplo, usando a CLI gcloud. O exemplo seguinte usa o curl para iniciar sessão e gerar um token que pode ser usado para aceder à aplicação:

  1. Inicie sessão na sua conta com acesso ao recurso Google Cloud .
  2. Inicie um servidor local que possa repetir os pedidos recebidos.

      # Example using Netcat (http://netcat.sourceforge.net/)
      nc -k -l 4444
    
  3. Aceda ao seguinte URI, onde DESKTOP_CLIENT_ID é o ID de cliente da app para computador:

      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. Na saída do servidor local, procure os parâmetros do pedido:

      GET /?code=CODE&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email&hd=google.com&prompt=consent HTTP/1.1
    
  5. Copie o valor CODE para substituir AUTH_CODE no seguinte comando, juntamente com o ID de cliente e o segredo da app para computador:

      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 devolve um objeto JSON com um campo id_token que pode usar para aceder à aplicação.

Aceda à aplicação

Para aceder à app, use o id_token:

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

Símbolo de atualização

Pode usar o token de atualização gerado durante o fluxo de início de sessão para obter novos tokens de ID. Isto é útil quando o token de ID original expira. Cada token de ID é válido durante cerca de uma hora, durante a qual pode fazer vários pedidos a uma app específica.

O exemplo seguinte usa o curl para usar o token de atualização para obter um novo token de ID. Neste exemplo, REFRESH_TOKEN é o token do fluxo de início de sessão. DESKTOP_CLIENT_ID e DESKTOP_CLIENT_SECRET são iguais aos usados no fluxo de início de sessão:

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 devolve um objeto JSON com um novo campo id_token que pode usar para aceder à app.

Autentique uma conta de serviço

Pode usar um JWT de conta de serviço ou um token OpenID Connect (OIDC) para autenticar uma conta de serviço com um recurso protegido pelo IAP. A tabela seguinte descreve algumas das diferenças entre os diferentes tokens de autenticação e as respetivas funcionalidades.

Funcionalidades de autenticação JWT da conta de serviço Token OpenID Connect
Suporte do acesso sensível ao contexto
Requisito do ID de cliente OAuth 2.0
Âmbito do token URL do recurso protegido pelo IAP ID de cliente OAuth 2.0

Autentique com um JWT de conta de serviço

O IAP suporta a autenticação JWT de contas de serviço para identidades Google, Identity Platform e aplicações configuradas com a federação de identidades da força de trabalho.

A autenticação de uma conta de serviço através de um JWT compreende os seguintes passos principais:

  1. Conceda à conta de serviço de chamada a função de criador de tokens de conta de serviço (roles/iam.serviceAccountTokenCreator).

    A função concede aos principais autorização para criar credenciais de curta duração, como JWTs.

  2. Crie um JWT para o recurso protegido pelo IAP.

  3. Assine o JWT com a chave privada da conta de serviço.

Crie o JWT

O JWT criado deve ter um payload semelhante ao seguinte exemplo:

{
  "iss": SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "sub": SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "aud": TARGET_URL,
  "iat": IAT,
  "exp": EXP,
}
  • Para os campos iss e sub, especifique o endereço de email da conta de serviço. Este valor encontra-se no campo client_email do ficheiro JSON da conta de serviço ou é transmitido. Formato típico: service-account@PROJECT_ID.iam.gserviceaccount.com

  • Para o campo aud, especifique o URL do recurso protegido pelo IAP.

  • Para o campo iat, especifique a hora atual da época Unix e, para o campo exp, especifique uma hora até 3600 segundos mais tarde. Isto define quando o JWT expira.

Assine o JWT

Pode usar um dos seguintes métodos para assinar o JWT:

  • Use a API de credenciais da IAM para assinar um JWT sem precisar de acesso direto a uma chave privada.
  • Use um ficheiro de chave de credenciais local para assinar o JWT localmente.
Assine o JWT com a API de credenciais da conta de serviço do IAM

Use a API IAM Service Account Credentials para assinar um JWT de conta de serviço. O método obtém a chave privada associada à sua conta de serviço e usa-a para assinar a carga útil JWT. Isto permite a assinatura de um JWT sem acesso direto a uma chave privada.

Para fazer a autenticação no IAP, configure as credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.

gcloud

  1. Execute o seguinte comando para preparar um pedido com o payload 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. Use o seguinte comando da CLI do Google Cloud para assinar a carga útil em claim.json:
gcloud iam service-accounts sign-jwt --iam-account="SERVICE_ACCOUNT_EMAIL_ADDRESS" claim.json output.jwt

Após um pedido bem-sucedido, output.jwt contém um JWT assinado que pode usar para aceder ao seu recurso protegido pelo 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. Execute o seguinte comando para preparar um pedido com a carga útil JWT:

    cat << EOF > request.json
    {
      "payload": JWT_PAYLOAD
    }
    EOF
    
  2. Assine o JWT com o 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"
    

    Após um pedido bem-sucedido, é devolvido um JWT assinado na resposta.

  3. Use o JWT para aceder ao recurso protegido pelo IAP.

Assine o JWT a partir de um ficheiro de chave de credenciais local

Os JWTs são assinados com a chave privada da conta de serviço.

Se tiver um ficheiro de chave de conta de serviço, o JWT pode ser assinado localmente.

Quando assinar o JWT localmente, inclua um cabeçalho JWT com o payload. Para o campo kid no cabeçalho, use o ID da chave privada da conta de serviço, que se encontra no campo private_key_id do ficheiro JSON das credenciais da conta de serviço. A chave privada do ficheiro é usada para assinar o JWT.

Aceda à aplicação

Em todos os casos, para aceder à app, use o signed-jwt:

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

Autentique com um token OIDC

  1. Crie ou use um ID de cliente OAuth 2.0 existente. Para usar um ID de cliente OAuth 2.0 existente, siga os passos em Como partilhar clientes OAuth.
  2. Adicione o ID OAuth à lista de autorizações para acesso programático para a aplicação.
  3. Certifique-se de que a conta de serviço predefinida é adicionada à lista de acesso do projeto protegido pelo IAP.

Quando fizer pedidos ao recurso protegido pelo IAP, tem de incluir o token no cabeçalho Authorization: Authorization: 'Bearer OIDC_TOKEN'

Os seguintes exemplos de código demonstram como obter um token OIDC.

Obtenha um token OIDC para a conta de serviço predefinida

Para obter um token OIDC para a conta de serviço predefinida do Compute Engine, App Engine ou Cloud Run, consulte o seguinte exemplo de código para gerar um token para aceder a um recurso protegido pelo IAP:

C#

Para se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 se autenticar no IAP, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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

Obter um token OIDC a partir de um ficheiro de chave de conta de serviço local

Para gerar um token OIDC através de um ficheiro de chave da conta de serviço, vai usar o ficheiro de chave para criar e assinar uma afirmação JWT e, em seguida, trocar essa afirmação por um token de ID. O seguinte script Bash demonstra este processo:

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 executa os seguintes passos:

  1. Extrai as informações da chave da conta de serviço do seu ficheiro de chave JSON
  2. Cria um JWT com os campos necessários, incluindo o ID do cliente da IAP como público-alvo
  3. Assina o JWT com a chave privada da conta de serviço
  4. Troca este JWT por um token OIDC através do serviço OAuth da Google
  5. Usa o token resultante para fazer um pedido autenticado ao seu recurso protegido pelo IAP

Para usar este script:

  1. Guardá-lo num ficheiro, por exemplo: get_iap_token.sh
  2. Torná-lo executável: chmod +x get_iap_token.sh
  3. Execute-o com três parâmetros:
  ./get_iap_token.sh service-account-key.json \
    OAUTH_CLIENT_ID \
    URL

Onde:

  • service-account-key.json é o ficheiro de chave da conta de serviço transferido
  • OAUTH_CLIENT_ID é o ID de cliente OAuth do seu recurso protegido pelo IAP
  • URL é o URL ao qual quer aceder

Obtenha um token OIDC em todos os outros casos

Em todos os outros casos, use a API IAM Credentials para gerar um token OIDC através da representação de uma conta de serviço de destino imediatamente antes de aceder a um recurso protegido pelo IAP. Este processo envolve os seguintes passos:

  1. Conceda à conta de serviço de chamada (a conta de serviço associada ao código que está a obter o token de ID) a função Criador de tokens de identidade OpenID Connect da conta de serviço (roles/iam.serviceAccountOpenIdTokenCreator).

    Isto dá à conta de serviço de chamada a capacidade de usar a identidade da conta de serviço de destino.

  2. Use as credenciais fornecidas pela conta de serviço de chamada para chamar o método generateIdToken na conta de serviço de destino.

    Defina o campo audience para o seu ID do cliente.

Para instruções passo a passo, consulte o artigo Crie um token de ID.

Autenticação a partir do cabeçalho Proxy-Authorization

Se a sua aplicação usar o cabeçalho de pedido Authorization, pode incluir o token de ID num cabeçalho Proxy-Authorization: Bearer. Se for encontrado um token de ID válido num cabeçalho Proxy-Authorization, o IAP autoriza o pedido com o mesmo. Depois de autorizar o pedido, a IAP transmite o cabeçalho Authorization à sua aplicação sem processar o conteúdo.

Se não for encontrado nenhum token de ID válido no cabeçalho Proxy-Authorization, a IAP continua a processar o cabeçalho Authorization e remove o cabeçalho Proxy-Authorization antes de transmitir o pedido à sua aplicação.

O que se segue?