Además de autenticar usuarios, es posible que debas permitir que otros servicios interactúen con tu API. Si bien las aplicaciones cliente pueden proporcionar a los usuarios un mensaje de acceso web a fin de que envíen sus credenciales, necesitas otro enfoque para una comunicación segura entre los servicios. En esta página, se muestra el enfoque que recomendamos para implementar la autenticación entre servicios y se proporciona un código de muestra.
Descripción general
Para identificar un servicio que envía solicitudes a tu API, usas una cuenta de servicio. El servicio de llamadas usa la clave privada de la cuenta de servicio para firmar un token web JSON (JWT) seguro y enviarlo en la solicitud a tu API.
Para implementar la autenticación entre servicios en tu API y en el servicio de llamadas, completa los pasos siguientes:
- Crea una cuenta de servicio y una clave para que use el servicio de llamadas.
- Agrega asistencia de autenticación en el documento de OpenAPI para tu servicio de Cloud Endpoints.
Agrega código al servicio de llamadas que realiza las tareas siguientes:
- Crea un JWT y fírmalo con la clave privada de la cuenta de servicio.
- Envía el JWT firmado en una solicitud a la API.
El ESP valida que las reclamaciones en el JWT coincidan con la configuración en tu documento de OpenAPI antes de reenviar la solicitud a tu API. El ESP no verifica los permisos de Cloud Identity que hayas otorgado en la cuenta de servicio.
Requisitos previos
En esta página, se supone que ya:
Crea una cuenta de servicio con una clave
Necesitas una cuenta de servicio con un archivo de claves privadas que el servicio de llamadas usa para firmar el JWT. Si tienes más de un servicio que envía solicitudes a tu API, puedes crear una cuenta que represente todos los servicios de llamadas. Si necesitas diferenciar entre los servicios (por ejemplo, podrían tener permisos diferentes), puedes crear una cuenta de servicio y una clave para cada servicio de llamadas.
En esta sección, se muestra cómo usar la consola de Google Cloud y la herramienta de línea de comandos de gcloud
para crear la cuenta de servicio y el archivo de claves privadas, y asignar a la cuenta de servicio el rol de Creador de tokens de la cuenta de servicio. Si deseas obtener más información sobre el uso de una API a fin de realizar esta tarea, consulta la sección para crear y administrar cuentas de servicio.
Para crear una cuenta de servicio y una clave, haz lo siguiente:
Consola de Google Cloud
Crear una cuenta de servicio:
En la consola de Google Cloud, ve a la página Crear cuenta de servicio.
Selecciona el proyecto que deseas usar.
Ingresa un nombre en el campo Nombre de cuenta de servicio.
Opcional: en el campo Descripción de la cuenta de servicio, ingresa una descripción.
Haga clic en Crear.
Haz clic en el campo Seleccionar una función. En Todas las funciones, selecciona Cuenta de servicio > Creador de tokens de cuenta de servicio.
Haga clic en Listo.
No cierres la ventana del navegador. La usarás en la próxima tarea.
Para crear una clave de cuenta de servicio, haz lo siguiente:
- En la consola de Google Cloud, haz clic en la dirección de correo electrónico de la cuenta de servicio que creaste.
- Haga clic en Claves.
- Haz clic en Agregar clave -> Crear nueva clave.
- Haz clic en Crear. Se descarga en tu computadora un archivo JSON que contiene la clave privada de la cuenta de servicio.
- Haz clic en Cerrar.
gcloud
Puedes ejecutar los siguientes comandos mediante Google Cloud CLI en tu máquina local o en Cloud Shell.
Configura la cuenta predeterminada para
gcloud
. Si tienes más de una cuenta, asegúrate de elegir la que está en el proyecto de Google Cloud que deseas usar.gcloud auth login
Muestra los ID de tus proyectos de Google Cloud:
gcloud projects list
Configura el proyecto predeterminado. Reemplaza
PROJECT_ID
con el ID del proyecto de Google Cloud que deseas usar.gcloud config set project PROJECT_ID
Crea una cuenta de servicio. Reemplaza
SA_NAME
ySA_DISPLAY_NAME
por el nombre y el nombre comercial que deseas usar.gcloud iam service-accounts create SA_NAME \ --display-name "SA_DISPLAY_NAME"
Muestra la dirección de correo electrónico de la cuenta de servicio que acabas de crear.
gcloud iam service-accounts list
Agrega la función Creador de tokens de cuenta de servicio. Reemplaza
SA_EMAIL_ADDRESS
por la dirección de correo electrónico de la cuenta de servicio.gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:SA_EMAIL_ADDRESS \ --role roles/iam.serviceAccountTokenCreator
Crea un archivo de claves de cuenta de servicio en el directorio de trabajo actual. Reemplaza
FILE_NAME
por el nombre que deseas usar para el archivo de claves. De forma predeterminada, el comando degcloud
crea un archivo JSON.gcloud iam service-accounts keys create FILE_NAME.json \ --iam-account SA_EMAIL_ADDRESS
Consulta la referencia de gcloud
para obtener más información sobre los comandos anteriores.
Si deseas obtener información sobre cómo proteger la clave privada, consulta Recomendaciones para administrar las credenciales.
Configura tu API para que sea compatible con la autenticación
Debes tener un objeto de requisitos de seguridad y un objeto de definiciones de seguridad en tu documento de OpenAPI para que el ESP valide las reclamaciones en el JWT firmado.
Agrega la cuenta de servicio como una entidad emisora en tu documento de OpenAPI.
securityDefinitions: DEFINITION_NAME: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "SA_EMAIL_ADDRESS" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS"
- Reemplaza
DEFINITION_NAME
por una string que identifique esta definición de seguridad. Es posible que desees reemplazarlo por el nombre de la cuenta de servicio o un nombre que identifique el servicio de llamadas. - Reemplaza
SA_EMAIL_ADDRESS
por la dirección de correo electrónico de la cuenta de servicio. - Puedes crear varias definiciones de seguridad en tu documento de OpenAPI, pero cada una de ellas debe tener un
x-google-issuer
diferente. Si creaste cuentas de servicio separadas para cada servicio de llamadas, puedes crear una definición de seguridad por cada cuenta de servicio, por ejemplo:
securityDefinitions: service-1: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-1@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com" service-2: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-2@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
- Reemplaza
O bien agrega
x-google-audiences
a la secciónsecurityDefinitions
. Si no agregasx-google-audiences
, el ESP requiere que la reclamación"aud"
(público) en el JWT tenga el formatohttps://SERVICE_NAME
, en el que SERVICE_NAME es el nombre de tu servicio de Endpoints, que configuraste en el campohost
de tu documento de OpenAPI, a menos que se use la marca--disable_jwt_audience_service_name_check
. Si se usa la marca y no se especificax-google-audiences
, no se verifica el campoaud
de JWT.O bien agrega
x-google-jwt-locations
a la secciónsecurityDefinitions
. Puedes usar este valor para definir una ubicación JWT personalizada. Las ubicaciones de JWT predeterminadas son el encabezadoAuthorization
(con el prefijo “Bearer”), el encabezadoX-Goog-Iap-Jwt-Assertion
o el parámetro de búsquedaaccess_token
. Nota:- Si especificas
x-google-jwt-locations
, Endpoints ignora todas las ubicaciones predeterminadas. x-google-jwt-locations
solo es compatible con ESPv2.
- Si especificas
Agrega una sección
security
al nivel superior del archivo (sin sangría ni anidado) para aplicarla en toda la API, o al nivel de los métodos a fin de aplicarla a un método específico. Si usas las seccionessecurity
en los niveles de la API y de los métodos, la configuración del nivel de los métodos anula la configuración del nivel de la API.security: - DEFINITION_NAME: []
- Reemplaza
DEFINITION_NAME
por el nombre que usaste en la secciónsecurityDefinitions
. Si tienes más de una definición en la sección
securityDefinitions
, agrégalas en la secciónsecurity
, por ejemplo:security: - service-1: [] - service-2: []
- Reemplaza
Implementa tu documento de OpenAPI actualizado. Reemplaza
OPENAPI_DOC
por el nombre de tu documento de OpenAPI.gcloud endpoints services deploy OPENAPI_DOC
Antes de reenviar una solicitud a tu API, el ESP verifica lo siguiente:
- La firma del JWT mediante la clave pública, que se encuentra en el URI especificado en el campo
x-google-jwks_uri
en tu documento de OpenAPI - Que la reclamación
"iss"
(entidad emisora) en el JWT coincida con el valor especificado en el campox-google-issuer
- Que la reclamación
"aud"
(público) en el JWT contenga el nombre de tu servicio de Endpoints o coincida con uno de los valores que especificaste en el campox-google-audiences
- Que el token no haya vencido mediante la reclamación
"exp"
(hora de vencimiento)
Para obtener más información sobre x-google-issuer
, x-google-jwks_uri
, x-google-audiences
y x-google-jwt-locations
, consulta Extensiones de OpenAPI.
Realiza una solicitud autenticada a una API de Endpoints
Para realizar una solicitud autenticada, el servicio de llamadas envía un JWT firmado por la cuenta de servicio que especificaste en el documento de OpenAPI. El servicio de llamadas debe hacer lo siguiente:
- Crear un JWT y firmarlo con la clave privada de la cuenta de servicio
- Enviar el JWT firmado en una solicitud a la API
En el siguiente código de muestra, se muestra este proceso para los lenguajes seleccionados. Si deseas realizar una solicitud autenticada en otros lenguajes, consulta jwt.io para obtener una lista de bibliotecas compatibles.
- En el servicio de llamadas, agrega la función que sigue y pásala a los parámetros siguientes:
Java saKeyfile
: La ruta de acceso completa al archivo de claves privadas de la cuenta de serviciosaEmail
: La dirección de correo electrónico de la cuenta de servicio-
audience
: Si agregaste el campox-google-audiences
a tu documento de OpenAPI, configuraaudience
como uno de los valores que especificaste parax-google-audiences
. De lo contrario, configuraaudience
comohttps://SERVICE_NAME
, en el queSERVICE_NAME
es el nombre de tu servicio de Endpoints expiryLength
: El tiempo de vencimiento del JWT, en segundos
Python -
sa_keyfile
: La ruta de acceso completa al archivo de claves privadas de la cuenta de servicio -
sa_email
: La dirección de correo electrónico de la cuenta de servicio -
audience
: Si agregaste el campox-google-audiences
a tu documento de OpenAPI, configuraaudience
como uno de los valores que especificaste parax-google-audiences
. De lo contrario, configuraaudience
comohttps://SERVICE_NAME
, en el queSERVICE_NAME
es el nombre de tu servicio de Endpoints expiry_length
: El tiempo de vencimiento del JWT, en segundos
Go saKeyfile
: La ruta de acceso completa al archivo de claves privadas de la cuenta de servicio-
saEmail
: La dirección de correo electrónico de la cuenta de servicio -
audience
: Si agregaste el campox-google-audiences
a tu documento de OpenAPI, configuraaudience
como uno de los valores que especificaste parax-google-audiences
. De lo contrario, configuraaudience
comohttps://SERVICE_NAME
, en el queSERVICE_NAME
es el nombre de tu servicio de Endpoints expiryLength
: El tiempo de vencimiento del JWT, en segundos
La función crea un JWT, lo firma con el archivo de claves privadas y muestra el JWT firmado.
Java Python Go - En el servicio de llamadas, agrega la función siguiente para enviar el JWT firmado en el encabezado
Authorization: Bearer
de la solicitud a la API:Java Python Go
Cuando envíes una solicitud con un JWT, por motivos de seguridad, te recomendamos que coloques el token de autenticación en el encabezado Authorization: Bearer
. Por ejemplo:
curl --request POST \ --header "Authorization: Bearer ${TOKEN}" \ "${ENDPOINTS_HOST}/echo"
Donde ENDPOINTS_HOST
y TOKEN
son variables del entorno que contienen el nombre del host de tu API y un token de autenticación de forma respectiva.
Recibe resultados autenticados en tu API
Por lo general, el ESP reenvía todos los encabezados que recibe. Sin embargo, anula el encabezado original Authorization
cuando la dirección de backend se especifique mediante x-google-backend
en la especificación de OpenAPI o BackendRule
en la configuración del servicio de gRPC.
El ESP enviará el resultado de la autenticación en X-Endpoint-API-UserInfo
a la API de backend. Te recomendamos usar este encabezado en lugar del encabezado Authorization
original. Este encabezado es una cadena en la que base64url
codifica un objeto JSON. El formato del objeto JSON difiere entre ESPv2 y ESP.
Para ESPv2, el objeto JSON es exactamente la carga útil original de JWT. En el caso del ESP, el objeto JSON usa nombres de campos diferentes y coloca la carga útil original de JWT en el campo claims
.
Consulta Controla JWT en el servicio de backend para obtener más información sobre el formato.