Autenticação programática

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Nesta página, você aprenderá como fazer a autenticação em um recurso protegido pelo Identity-Aware Proxy (IAP) usando uma conta de usuário ou uma conta de serviço.

  • A conta de usuário pertence a um usuário individual. Ela é usada na autenticação quando o aplicativo precisa acessar recursos protegidos pelo IAP em nome de um usuário. Leia sobre as credenciais de conta de usuário.
  • A conta de serviço pertence a um aplicativo, e não a um usuário individual. Ela é usada na autenticação quando você quer permitir que um aplicativo acesse seus recursos protegidos pelo IAP. Conheça as noções básicas sobre contas de serviço.

Antes de começar

Antes de começar, você precisará de:

  • um aplicativo protegido pelo IAP a que você quer se conectar de maneira programática usando uma conta de desenvolvedor, uma conta de serviço ou credenciais de app para dispositivos móveis.

Como autenticar uma conta de usuário

É possível liberar o acesso de usuários a seu aplicativo por meio de um app para computador ou dispositivos móveis para permitir que um programa interaja com um recurso protegido pelo IAP.

Como autenticar usando um app para dispositivos móveis

  1. Crie um ID do cliente OAuth 2.0 para seu aplicativo para dispositivos móveis no mesmo projeto que o recurso protegido pelo IAP:
    1. Acesse a página Credenciais.
      Acessar a página "Credenciais"
    2. Selecione o projeto com o recurso protegido pelo IAP.
    3. Clique em Criar credenciais e selecione ID do cliente OAuth.
    4. Selecione o Tipo de aplicativo para que você quer criar credenciais.
    5. Inclua as informações de Nome e Restrições, se apropriado, e clique em Criar.
  2. Uma janela Cliente OAuth será exibida. Anote o ID do cliente do recurso protegido pelo IAP a que você quer se conectar.
  3. receber um token do código para o ID do cliente protegido pelo IAP:
  4. Inclua o token de ID em um cabeçalho Authorization: Bearer para fazer a solicitação autenticada ao recurso protegido pelo IAP.

Como autenticar usando um app para computador

Esta seção descreve como autenticar uma conta de usuário de uma linha de comando de um desktop.

Como configurar o ID do cliente

Para permitir que os desenvolvedores acessem seu aplicativo a partir da linha de comando, primeiro é necessário criar credenciais de ID do cliente OAuth do tipo app para computador:

  1. Acesse a página Credenciais.
    Acessar a página "Credenciais"
  2. Selecione o projeto com o recurso protegido pelo IAP.
  3. Clique em Criar credenciais e selecione ID do cliente OAuth.
  4. Em Tipo de aplicativo, selecione app para computador, adicione um Nome e clique em Criar.
  5. Na janela Cliente OAuth que é exibida, anote o ID do cliente e a chave secreta do cliente. Você precisará usá-los em um script para gerenciar credenciais ou compartilhar com seus desenvolvedores.
  6. Na janela Credenciais, as novas credenciais app para computador aparecem junto com o ID do cliente principal que é usado para acessar o aplicativo.

Como fazer login no aplicativo

Cada desenvolvedor que quiser acessar um app protegido pelo IAP precisará fazer login nele. É possível empacotar o processo em um script, como usando a CLI gcloud. Veja abaixo um exemplo que usa a curl para fazer login e gerar um token que pode ser usado para acessar o aplicativo:

  1. Faça login na sua conta que tem acesso ao recurso do Google Cloud.
  2. Inicie um servidor local que possa transmitir as solicitações recebidas. $ nc -k -l 4444 OBSERVAO: o comando usa o utilitário [NetCat](http://netcat.sourceforge.net/). Use o utilitário da sua escolha.
  3. Acesse o seguinte URI, em que DESKTOP_CLIENT_ID é o ID do cliente do app para computador que você criou acima:

    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

  4. Na saída do servidor local, procure os parâmetros da solicitação. Você verá algo como o seguinte: GET /?code=\$CODE&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email&hd=google.com&prompt=consent HTTP/1.1 copie o CDIGO para substituir AUTH_CODE abaixo, além do ID do cliente do app para computador e da chave secreta que você criou acima:

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

    Esse código retorna um objeto JSON com um campo refresh_token, que você pode salvar como token de login para acessar o aplicativo.

Como acessar o aplicativo

Para acessar o aplicativo, troque o valor de refresh_token gerado durante o fluxo de login por um token de ID. O token de ID permanece válido por cerca de uma hora. Durante esse período, é possível fazer várias solicitações a um app específico. Veja abaixo um exemplo de como usar a curl para utilizar o token e acessar o aplicativo:

  1. Use o código abaixo, em que REFRESH_TOKEN é o token do fluxo de login, IAP_CLIENT_ID é o ID principal do cliente usado para acessar o aplicativo, e DESKTOP_CLIENT_ID e DESKTOP_CLIENT_SECRET são o ID do cliente e o segredo que você criou quando configurou o ID do cliente acima:

    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

    Esse código retorna um objeto JSON com um campo id_token, que pode ser usado para acessar o aplicativo.

  2. Para acessar o app, use o id_token da seguinte maneira:

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

Como autenticar uma conta de serviço

Use um token do OpenID Connect (OIDC) para autenticar uma conta de serviço em um recurso protegido pelo IAP. Siga estas etapas para encontrar seu ID do cliente:

  1. Acesse a página do IAP.
  2. Encontre o recurso que você quer acessar e clique em Mais > Editar cliente OAuth.
    editar cliente OAuth no menu "Mais"

  3. Na página Credenciais que aparece, anote o ID do cliente.

Você também precisa adicionar a conta de serviço à lista de acesso do projeto protegido pelo IAP. Os exemplos de código a seguir mostram como receber um token OIDC. Independentemente da opção escolhida, inclua o token em um cabeçalho Authorization: Bearer para fazer a solicitação autenticada ao recurso protegido pelo IAP.

Como conseguir um token OIDC para a conta de serviço padrão

Se você quiser receber um token OIDC para a conta de serviço padrão do Compute Engine, do App Engine ou do Cloud Run, use o exemplo de código a seguir para gerar o token e acessar um recurso protegido pelo IAP:

C#


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

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

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

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

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

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

Go

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.
 */
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

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

Como conseguir um token OIDC de um arquivo de chave de conta de serviço local

Se você tiver um arquivo de chave da conta de serviço, poderá adaptar os exemplos de código anteriores para fornecer o arquivo de chave da conta de serviço.

Bash

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

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

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

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

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

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

  main "$@"

Como conseguir um token OIDC em todos os outros casos

Em todos os outros casos, use a API de credenciais do IAM para gerar um token OIDC com base em um token de acesso de outra conta de serviço antes de acessar um recurso protegido pelo IAP:

  1. Adicione a conta no token de acesso com o papel service account token creator na conta de destino. Isso garante que ele tenha a permissão do IAM necessária para criar um token OIDC para a conta de serviço de destino.
  2. Chame generateIdToken na conta de serviço de destino com o token de acesso. Preste muita atenção para definir o campo audience como o ID do cliente.

Como autenticar usando o cabeçalho Proxy-Authorization

Se seu aplicativo ocupar o cabeçalho de solicitação Authorization, inclua o token de código em um cabeçalho Proxy-Authorization: Bearer. Se um token de ID válido for encontrado em um cabeçalho Proxy-Authorization, o IAP autorizará a solicitação com ele. Depois de autorizar a solicitação, o IAP transmite o cabeçalho Authorization para o aplicativo sem processar o conteúdo.

Se nenhum token de ID válido for encontrado no cabeçalho Proxy-Authorization, o IAP continuará a processar o cabeçalho Authorization e retirará o cabeçalho Proxy-Authorization antes de transmitir a solicitação para o aplicativo.

A seguir