Nesta página, você vai aprender a 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. Para mais informações, consulte Contas 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. Para mais informações, consulte 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
- Crie ou use um ID do cliente OAuth 2.0 para o app para dispositivos móveis. Para usar um ID do cliente OAuth 2.0, siga as etapas em Como compartilhar clientes OAuth.
- Adicione o ID do cliente OAuth à lista de permissões para acesso programático do aplicativo.
- Receba um token de código para o ID do cliente protegido pelo IAP.
- Android: use a API Google Sign-in para solicitar um token do OpenID Connect (OIDC). Defina o ID do cliente
requestIdToken
como o do recurso a que você está se conectando. - iOS: use o Login do Google para receber um token de ID.
- Android: use a API Google Sign-in para solicitar um token do OpenID Connect (OIDC). Defina o ID do cliente
- 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.
- Para permitir que os desenvolvedores acessem seu aplicativo na linha de comando, crie um ID do cliente OAuth 2.0 para computador ou compartilhe um ID do cliente OAuth para computador já existente.
- Adicione o ID do cliente OAuth à lista de permissões para acesso programático do aplicativo.
Como fazer login no aplicativo
Cada desenvolvedor que quiser acessar um app protegido pelo IAP precisa fazer login primeiro. É possível empacotar o processo em um script, por exemplo, 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:
- Faça login na conta que tem acesso ao recurso do Google Cloud.
-
Inicie um servidor local que possa repetir as solicitações recebidas.
OBSERVAÇÃO: o comando usa o utilitário NetCat. Você pode usar o utilitário de sua preferência.$ nc -k -l 4444
-
Acesse o seguinte URI, em que
DESKTOP_CLIENT_ID
é o ID do cliente do 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
-
Na saída do servidor local, procure os parâmetros de solicitação. Você vai ver algo parecido com 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 CODE para substituirAUTH_CODE
abaixo com o ID do cliente e a chave secreta do app para computador:curl --verbose \ --data client_id=DESKTOP_CLIENT_ID \ --data client_secret=DESKTOP_CLIENT_SECRET \ --data code=AUTH_CODE \ --data redirect_uri=http://localhost:4444 \ --data grant_type=authorization_code \ 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.
Como acessar o aplicativo
Para acessar o app, use o
id_token
da seguinte maneira:
curl --verbose --header 'Authorization: Bearer ID_TOKEN' URL
Token de atualização
É possível usar o token de atualização gerado durante o fluxo de login para receber novos tokens de ID. Isso é útil quando o token de ID original expira. Cada token de ID é válido por cerca de uma hora. Durante esse período, é possível fazer várias solicitações a um app específico.
Confira abaixo um exemplo de uso do curl para usar o token de atualização e receber um novo token de ID. No exemplo abaixo,
REFRESH_TOKEN
é o token
do fluxo de login.
DESKTOP_CLIENT_ID
e
DESKTOP_CLIENT_SECRET
são os
mesmos usados no fluxo de login:
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
Esse código retorna um objeto JSON com um novo
campo id_token
, que pode ser
usado para acessar o app.
Como autenticar uma conta de serviço
É possível usar um JWT da conta de serviço ou um token do OpenID Connect (OIDC) para autenticar uma conta de serviço com um recurso protegido pelo IAP. A tabela a seguir descreve algumas diferenças entre os diferentes tokens de autenticação e os respectivos recursos.
Recursos do Authentication | JWT da conta de serviço | Token do OpenID Connect |
---|---|---|
Suporte ao acesso baseado no contexto | ||
Requisitos do ID do cliente OAuth 2.0 | ||
Escopo do token | URL do recurso protegido pelo IAP | ID do cliente OAuth 2.0 |
Como autenticar com um JWT de conta de serviço
A autenticação de uma conta de serviço usando um JWT compreende as seguintes etapas principais:
Conceda à conta de serviço que faz a chamada o papel Criador de token da conta de serviço (
roles/iam.serviceAccountTokenCreator
).O papel concede aos principais a permissão para criar credenciais de curta duração, como JWTs.
Crie um JWT para o recurso protegido pelo IAP.
Assine o JWT usando a chave privada da conta de serviço.
Como criar o JWT
O JWT criado precisa ter um payload semelhante ao exemplo abaixo:
{ "iss": SERVICE_ACCOUNT_EMAIL_ADDRESS, "sub": SERVICE_ACCOUNT_EMAIL_ADDRESS, "aud": TARGET_URL, "iat": IAT, "exp": EXP, }
Para os campos
iss
esub
, especifique o endereço de e-mail da conta de serviço. Ele está no campoclient_email
do arquivo JSON da conta de serviço ou é transmitido. Formato típico:service-account@PROJECT_ID.iam.gserviceaccount.com
No campo
aud
, especifique o URL do recurso protegido pelo IAP.Para o campo
iat
, especifique o horário atual da época do Unix e, para o campoexp
, especifique um horário dentro de 3600 segundos depois. Isso define quando o JWT expira.
Assinaturar o JWT
Use um dos seguintes métodos para assinar o JWT:
- Use a API de credenciais do IAM para assinar um JWT sem exigir acesso direto a uma chave privada.
- Use um arquivo de chave de credenciais local para assinar o JWT localmente.
Como assinar o JWT usando a API Service Account Credentials do IAM
Use a API Service Account Credentials do IAM para assinar um JWT de conta de serviço. O método busca a chave privada associada à sua conta de serviço e a usa para assinar o payload do JWT. Isso permite a assinatura de um JWT sem acesso direto a uma chave privada.
Para autenticar no IAP, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
gcloud
Execute o comando a seguir para preparar uma solicitação com o payload do 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
Use o comando da Google Cloud CLI a seguir para assinar o payload em
request.json
:gcloud iam service-accounts sign-jwt --iam-account=SERVICE_ACCOUNT_EMAIL_ADDRESS claim.json output.jwt
Após uma solicitação bem-sucedida,
output.jwt
contém um JWT assinado.Use o JWT para acessar o recurso protegido pelo IAP.
Python
import datetime
import json
import google.auth
from google.cloud import iam_credentials_v1
import jwt
def generate_jwt_payload(service_account_email: str, resource_url: str) -> str:
"""Generates JWT payload for service account.
The resource url provided must be the same as the url of the IAP secured resource.
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:
A signed-jwt that can be used to access IAP protected applications.
Access the application with the JWT in the Authorization Header.
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
"""
iat = datetime.datetime.now(tz=datetime.timezone.utc)
exp = iat + 3600
return json.dumps({
'iss': service_account_email,
'sub': service_account_email,
'aud': resource_url,
'iat': iat,
'exp': exp,
})
def sign_jwt(target_sa: str, resource_url: str) -> str:
"""Signs JWT payload using ADC and IAM credentials API.
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:
A signed-jwt that can be used to access IAP protected apps.
"""
source_credentials, _ = google.auth.default()
iam_client = iam_credentials_v1.IAMCredentialsClient(credentials=source_credentials)
return iam_client.sign_jwt(
name=iam_client.service_account_path('-', target_sa),
payload=generate_jwt_payload(target_sa, resource_url),
).signed_jwt
Após uma solicitação bem-sucedida, o script retorna um JWT assinado. Use o JWT para acessar o recurso protegido pelo IAP.
curl
Execute o comando a seguir para preparar uma solicitação com o payload do JWT:
cat << EOF > request.json { "payload": JWT_PAYLOAD } EOF
Assine o JWT usando a API Service Account Credentials do IAM:
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 uma solicitação bem-sucedida, um JWT assinado estará na resposta.
Use o JWT para acessar o recurso protegido pelo IAP.
Assinar o JWT de um arquivo de chave de credencial local
Os JWTs são assinados usando a chave privada da conta de serviço.
Se você tiver um arquivo de chave de conta de serviço, o JWT poderá ser assinado localmente.
O script envia 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 está no
campo private_key_id
do arquivo JSON da credencial da conta de serviço.
A chave também é usada para assinar o JWT.
Python
import time
import jwt
import json
def generate_jwt_payload(service_account_email, resource_url):
"""Generates JWT payload for service account.
The resource url provided must be the same as the url of the IAP secured resource.
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:
A signed-jwt that can be used to access IAP protected applications.
Access the application with the JWT in the Authorization Header.
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
"""
iat = datetime.datetime.now(tz=datetime.timezone.utc)
exp = iat + 3600
return json.dumps({
'iss': service_account_email,
'sub': service_account_email,
'aud': resource_url,
'iat': iat,
'exp': exp,
})
def sign_jwt_with_key_file(credential_key_file_path, resource_url):
"""Signs JWT payload using local service account credential key file.
Args:
credential_key_file_path (str): Path to the downloaded JSON credentials of the service
account the JWT is being created for.
resource_url (str): Scope of JWT token, This is the url of the IAP protected application.
Returns:
A service account JWT created with a downloaded private key.
"""
with open(credential_key_file_path, 'r') as credential_key_file:
key_data = json.load(credential_key_file)
PRIVATE_KEY_ID_FROM_JSON = key_data["private_key_id"]
PRIVATE_KEY_FROM_JSON = key_data["private_key"]
SERVICE_ACCOUNT_EMAIL = key_data["client_email"]
# Sign JWT with private key and store key id in the header
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
payload = generate_jwt_payload(service_account_email=SERVICE_ACCOUNT_EMAIL, resource_url=resource_url)
signed_jwt = jwt.encode(
payload,
PRIVATE_KEY_FROM_JSON,
headers=additional_headers,
algorithm='RS256',
)
return signed_jwt
O resultado é um JWT assinado.
Como acessar o aplicativo
Em todos os casos, para acessar o app, use o
signed-jwt
da seguinte maneira:
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
Como autenticar com um token OIDC
- Crie ou use um ID do cliente OAuth 2.0. Para usar um ID do cliente OAuth 2.0, siga as etapas em Como compartilhar clientes OAuth.
- Adicione o ID do cliente OAuth à lista de permissões para acesso programático do aplicativo.
Você também precisa adicionar a conta de serviço à lista de acesso
do projeto protegido pelo IAP. Os exemplos de código abaixo mostram
como receber um token OIDC. Inclua
o token em um cabeçalho Authorization: Bearer
para fazer a solicitação de autenticação
ao recurso protegido pelo IAP.
Como conseguir um token OIDC para a conta de serviço padrão
Se você quiser receber um token do OIDC para a conta de serviço padrão do Compute Engine, do App Engine ou do Cloud Run, use a exemplo de código a seguir para gerar o token para acessar um recurso protegido pelo IAP:
C#
Go
Para autenticar no IAP, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Java
Node.js
PHP
Para autenticar no IAP, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Python
Para autenticar no IAP, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Ruby
Para autenticar no IAP, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Como conseguir um token OIDC de um arquivo de chave de conta de serviço local
Se você tiver um arquivo de chave de conta de serviço, adapte 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 + 600))"
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 ID token.
ID_TOKEN=$(get_token "${SERVICE_ACCOUNT_KEY}" "${IAP_CLIENT_ID}")
# Access the application with the 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 falsificando uma conta de serviço de destino antes de acessar um recurso protegido pelo IAP: Esse processo envolve as seguintes etapas:
Forneça à conta de serviço de chamada (a conta de serviço associada ao código que está recebendo o token de ID) o papel de Criador do token de identidade do OpenID Connect da conta de serviço (
roles/iam.serviceAccountOpenIdTokenCreator
).Isso permite que a conta de serviço de chamada imite a conta de serviço de destino.
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
como o ID do cliente.
Para instruções passo a passo, consulte Criar um token de ID.
Como autenticar usando o cabeçalho Proxy-Authorization
Se o aplicativo usar o cabeçalho de solicitação Authorization
, é possível
incluir o token de ID em um cabeçalho Proxy-Authorization: Bearer
. Se um
token de ID válido for encontrado em um cabeçalho Proxy-Authorization
,
o IAP vai autorizar a solicitação com ele. Depois de autorizar a
solicitação, o IAP transmite o cabeçalho Authorization
ao
app sem processar o conteúdo.
Se nenhum token de ID válido for encontrado no cabeçalho Proxy-Authorization
,
o IAP vai continuar processando o cabeçalho Authorization
e
retirar o cabeçalho Proxy-Authorization
antes de transmitir a solicitação para o
app.
A seguir
- Saiba mais sobre Autorização: tokens do portador.
- Tente fazer login no Android ou no iOS.