SpyBara
Go Premium

claude-apps-gateway-deploy.md 2026-10-02 22:59 UTC to 2026-10-03 17:01 UTC

This page contains 60 additions and 45 deletions.

2026
Fri 2 22:59 Sat 3 17:57

Implementación y operaciones de la puerta de enlace de aplicaciones Claude

Registre la puerta de enlace con su IdP, construya el contenedor, implemente en Kubernetes o Cloud Run, y opérelo: verificaciones de salud, rotación de secretos, actualizaciones y seguridad.

Esta página cubre el lado operativo de ejecutar la puerta de enlace de aplicaciones Claude: registrar un cliente OAuth en su proveedor de identidad (IdP), implementar la puerta de enlace como un contenedor y ejecutarla día a día. Para cada opción en el archivo gateway.yaml que la puerta de enlace lee al iniciar, consulte la referencia de configuración.

Una implementación de producción sigue cuatro pasos en orden, y las secciones a continuación coinciden con ellos. Los dos primeros son donde usted toma decisiones; los dos segundos son material de referencia para consultar una vez que esté en funcionamiento.

  1. Configurar su proveedor de identidad: registre el cliente OAuth y verifique las notas específicas de cada IdP para Okta, Entra y Google
  2. Implementar la puerta de enlace: construya una imagen de contenedor fijada y ejecútela en Kubernetes, Cloud Run o su propia plataforma. Esta sección también cubre decisiones sobre costo, omisión, múltiples puertas de enlace y sin servidor
  3. Configurar operaciones: registros, sondeos de salud, comportamiento de interrupciones, rotación de secretos y actualizaciones. Referencia para cuando esté conectando monitoreo y runbooks
  4. Revisar la postura de seguridad: qué datos fluyen hacia dónde, el modelo de amenaza y respuestas de cumplimiento. Referencia para una revisión de seguridad

Si un inicio de sesión o arranque falla en el camino, vaya directamente a Solución de problemas, que está indexada por el error que ve.

Configuración del proveedor de identidad

Registra una aplicación web confidencial de OAuth/OpenID Connect (OIDC) con un único URI de redirección, https://<gateway>/oauth/callback, y asígnala a los usuarios o grupos que deben tener acceso al gateway. El gateway se autentica ante el IdP con el secreto de cliente del registro, o con un certificado que subes al registro si tu IdP usa credenciales de certificado en su lugar.

Cualquier IdP compatible con OIDC funciona: Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate y otros. El IdP debe cumplir tres requisitos:

  • Sirve /.well-known/openid-configuration, sobre HTTPS en producción; la puerta de enlace acepta un emisor http://, y un emisor de loopback además requiere CLAUDE_GATEWAY_ALLOW_LOOPBACK=1
  • Admite el flujo de código de autorización. PKCE (Proof Key for Code Exchange) está activado de forma predeterminada; desactívelo con oidc.use_pkce: false para IdPs que no lo admitan
  • Devuelve email y opcionalmente groups en el id_token, o los sirve desde el punto final de userinfo con oidc.userinfo_fallback: true

Para PKI privada, establezca oidc.ca_cert_pem.

Algunos proveedores manejan las reclamaciones de correo electrónico y grupo de manera diferente:

  • Okta: el servidor de autorización de la organización en https://example.okta.com devuelve un id_token delgado que omite email y groups, así que establezca oidc.userinfo_fallback: true siempre que lo use como issuer. Un servidor de autorización personalizado como https://example.okta.com/oauth2/default que incluye email y opcionalmente groups en el id_token los emite directamente y no necesita fallback. Okta emite groups solo cuando se solicita el alcance groups en oidc.scopes y el filtro de reclamación de grupos de la aplicación lo permite; userinfo_fallback no puede llenar una reclamación que el IdP no fue solicitado.
  • Microsoft Entra ID: issuer = https://login.microsoftonline.com/<tenant-id>/v2.0. Entra emite IDs de objeto de grupo en lugar de nombres, así que use los GUIDs en managed.policies.match.groups, o use App Roles para nombres legibles por humanos. Si su inquilino emite roles bajo roles en lugar de groups, establezca oidc.groups_claim: roles.
  • Google Workspace: issuer = https://accounts.google.com. El id_token de Google no lleva grupos. Para usar allowed_groups basado en grupos o managed.policies con Google como IdP, configure oidc.google_groups, que busca los grupos de cada usuario a través de la API de directorio del SDK de administración usando una cuenta de servicio con delegación en todo el dominio. Sin él, use oidc.allowed_email_domains para control de membresía y managed.policies.match.email_domain para asignación de políticas. Google también ignora el alcance estándar offline_access. Para tokens de actualización, establezca oidc.scopes: [openid, profile, email] y oidc.extra_auth_params: { access_type: offline, prompt: consent }.

Implementación

La puerta de enlace es un único binario de Linux sin estado que se coordina a través de Postgres, así que impleméntela de la manera en que implementa cualquier otro servicio sin estado en su entorno. Manténgala dentro de su red, donde sus desarrolladores e IdP puedan alcanzarla a través de HTTPS, y trátela como cualquier servicio que contiene una credencial de producción.

Algunas decisiones dan forma a la implementación más allá de dónde se ejecuta:

  • Costo: sin licencia separada ni tarifa por asiento. La puerta de enlace es parte del binario claude, así que paga por inferencia a través de su compromiso existente, más el cálculo que ejecuta.
  • Derivación: la puerta de enlace no impone que la única ruta a un modelo pase por ella. Un desarrollador con su propia credencial aún puede llamar al proveedor directamente, así que cerrar ese camino es una decisión de política de red, por ejemplo bloqueando la salida a api.anthropic.com excepto desde la puerta de enlace. Bloquear esa salida también rompe la verificación de seguridad de dominio de WebFetch, que llama a api.anthropic.com desde la máquina de cada desarrollador. Establezca skipWebFetchPreflight: true en la política administrada para deshabilitarlo.
  • Múltiples puertas de enlace: cada una es una implementación separada con su propia configuración, y el CLI almacena confianza y credenciales por nombre de host de puerta de enlace, así que los equipos pueden usar diferentes puertas de enlace sin conflicto. Para servir múltiples emisores OIDC, ejecute instancias separadas.
  • Sin servidor: Cloud Run funciona si establece min-instances: 1 para evitar descubrimiento OIDC frío. Lambda y Cloud Functions no funcionan, porque la puerta de enlace es un servidor HTTP de larga duración.

Cada topología de producción aquí coloca un proxy L7, como un Ingress, el front-end de Cloud Run o un ALB, frente a réplicas HTTP simples. Establezca listen.trusted_proxies en los rangos de origen del proxy para que la puerta de enlace lea las IPs del cliente desde X-Forwarded-For. La puerta de enlace honra el encabezado solo cuando el par TCP es confiable. Los ejemplos trabajados de Google Cloud y AWS tienen valores concretos por topología. Sin proxies confiables, cada solicitud parece provenir de la IP del proxy, lo que colapsa los límites de velocidad por IP en un cubo compartido y registra la IP del proxy en eventos de auditoría.

No redirija solicitudes a los puntos finales de autorización de dispositivo y token de la puerta de enlace, por ejemplo con una reescritura de HTTP a HTTPS o canonicalización de host en el ingress. Claude Code no sigue redirecciones en esas solicitudes, así que una regla de ingress que las redirija rompe el inicio de sesión y la actualización de token.

Dé al proxy cualquier tiempo de espera inactivo más largo que el intervalo de keepalive de la puerta de enlace, que depende del ascendente:

  • En cada ascendente excepto provider: anthropic, la puerta de enlace escribe un ping SSE una vez que una secuencia ha estado silenciosa durante aproximadamente 15 segundos.
  • En provider: anthropic, la puerta de enlace pasa la respuesta sin cambios, incluidos los pings propios de la API de Anthropic.

Un valor predeterminado como los 60 segundos del ALB es suficiente para mantener una secuencia silenciosa abierta. El ejemplo trabajado de AWS lo aumenta a una hora de todas formas, y su fila de solución de problemas cubre puertas de enlace anteriores a v2.1.229, que no enviaban nada durante períodos silenciosos en los ascendentes que ahora reciben pings.

Imagen de contenedor

Construya su propia imagen alrededor del binario nativo claude de la versión estándar de Claude Code:

  1. Descargue la compilación de Linux para la arquitectura de su imagen desde una versión fija; consulte Instalar una versión específica para la URL de descarga.
  2. Verifíquelo contra el manifest.json firmado con GPG de la versión como se describe en Integridad binaria y firma de código.
  3. Cópielo en el contexto de compilación.

Refleje la versión en su registro interno si sus compilaciones no pueden alcanzar el host de versión, y fije la versión que ejecuta su flota.

Más allá del binario, la imagen necesita:

  • Una imagen basada en glibc: las únicas dependencias dinámicas de la compilación de glibc son las bibliotecas de glibc. Las imágenes basadas en Musl necesitan la compilación linux-x64-musl o linux-arm64-musl más paquetes adicionales; consulte Configuración de Alpine Linux.
  • Un directorio de estado escribible: la puerta de enlace se ejecuta como cualquier usuario, pero las imágenes mínimas no tienen inicio escribible. Establezca CLAUDE_CONFIG_DIR en una ruta escribible como /tmp/.claude.
  • El comando del contenedor: claude gateway --config /etc/claude/gateway.yaml, con el archivo de configuración montado de solo lectura y secretos suministrados como variables de entorno; la puerta de enlace escucha en listen.port, predeterminado 8080.

Kubernetes

Ejecute la puerta de enlace como una Deployment, como cualquier servicio sin estado:

  • Monte la configuración desde un ConfigMap y secretos desde un Secret; haga referencia a secretos en el YAML a través de ${file:/path/to/secret} o como variables de entorno
  • Termine TLS en el Ingress y establezca listen.public_url en el nombre de host de Ingress
  • Apunte la sonda de preparación a GET /readyz y la sonda de vivacidad a GET /healthz

Para un ejemplo completo trabajado en AWS, cubriendo ECS Fargate o EKS, Amazon RDS y AWS Secrets Manager, consulte Implementar en AWS.

Prefiera la identidad de carga de trabajo de la plataforma sobre claves estáticas; la referencia de upstreams tiene detalles de configuración por plataforma. Para un emparejamiento entre nubes, como un ascendente de Bedrock en GKE, establezca credenciales explícitas en el bloque auth del ascendente en su lugar.

Cloud Run

Configure el servicio de la siguiente manera:

  • Deje listen.port en su predeterminado de 8080, que coincide con el PORT predeterminado de Cloud Run, o establezca port: ${PORT}
  • Establezca public_url en el origen externamente alcanzable. Para producción esto es normalmente el nombre de host de un equilibrador de carga interno, porque /login rechaza direcciones públicas y la URL *.run.app se resuelve a una, así que la URL de Cloud Run sola funciona solo para una prueba de humo curl o navegador. La excepción es una red donde *.run.app se resuelve privadamente a través de Private Service Connect y una zona privada de Cloud DNS; en esa topología la URL de Cloud Run es un public_url válido. El ejemplo trabajado de Google Cloud cubre ambos.
  • Monte la configuración como un volumen secreto
  • Establezca min-instances: 1 para evitar un descubrimiento OIDC frío en la primera solicitud

Para un ejemplo completo trabajado en Google Cloud, cubriendo Cloud Run o GKE, Cloud SQL y Secret Manager, consulte Implementar en Google Cloud.

Enviar la URL de la puerta de enlace a máquinas de desarrolladores

Una vez que la puerta de enlace está sirviendo, envíe forceLoginMethod, forceLoginGatewayUrl y parentSettingsBehavior: "merge" a la máquina de cada desarrollador a través de configuraciones administradas, a través de MDM o escribiendo directamente el managed-settings.json específico del sistema operativo. Sin esto, /login muestra el selector de cuenta estándar sin opción de puerta de enlace.

Una vez que implemente las claves, Claude Code deja de usar una clave API sobrante o un inicio de sesión de claude.ai en la máquina, así que planifique el envío junto con sus instrucciones de inicio de sesión. La política del administrador requiere un inicio de sesión de puerta de enlace en la nube describe los mensajes que ven los desarrolladores.

Consulte dónde cada mecanismo almacena la política para las rutas de archivo, y Configuraciones administradas del lado del cliente para el equivalente de bootstrapUrl de Claude Desktop.

Implementaciones a gran escala

El inicio de sesión tiene límite de velocidad por dirección IP del cliente, y los valores predeterminados se adaptan a un equipo pequeño. Cada dirección obtiene 30 inicios de sesión y 10 envíos de código cada 10 minutos. Una implementación para miles de desarrolladores puede alcanzar esos límites en la primera mañana, por una de dos razones:

  • La puerta de enlace no puede ver más allá de su equilibrador de carga. Sin listen.trusted_proxies, cada desarrollador parece provenir de la dirección del equilibrador de carga y comparte un límite. Establézcalo antes que nada. La puerta de enlace registra una advertencia la primera vez que ignora un encabezado X-Forwarded-For.
  • Muchos desarrolladores comparten pocas direcciones de salida NAT o VPN. Comparten los límites de esas direcciones incluso cuando trusted_proxies es correcto. Aumente rate_limits para ajustarse.

Para dimensionar max, divida los desarrolladores por las direcciones de salida que comparten. Estime cuántos de ellos inician sesión dentro de un período window_seconds, que es 10 minutos de forma predeterminada. Luego duplíquelo para cubrir reintentos y desarrolladores que inician sesión tanto en Claude Code como en Claude Desktop.

Por ejemplo, 10.000 desarrolladores detrás de 4 direcciones de salida inician sesión uniformemente durante una hora. Eso es 2.500 desarrolladores por dirección y aproximadamente 420 de ellos en cada 10 minutos, que duplica y redondea hasta 1.000. El ejemplo a continuación establece ambos límites en 1.000:

rate_limits:
  device_authorization: { max: 1000, window_seconds: 600 }
  device_verify: { max: 1000, window_seconds: 600 }

device_verify es lo que impide que alguien adivine el código de inicio de sesión de otro desarrollador, así que auméntelo solo en la medida que su estimación necesite. Incluso en estos límites, un código tiene 8 caracteres de un alfabeto de 20 caracteres y expira después de 10 minutos, así que adivinar sigue siendo impracticable; consulte Resistencia a fuerza bruta de código de usuario.

Cuando su IdP emite tokens de actualización, Claude Code renueva sesiones silenciosamente, así que puede volver a poner el límite después de la implementación. Sin tokens de actualización, los desarrolladores inician sesión nuevamente cada session.ttl_hours. Dimensione ambos límites para esa velocidad constante también y déjelos elevados.

Cuando se alcanza un límite, Claude Code v2.1.274 o posterior muestra The gateway is limiting sign-in attempts right now. Una puerta de enlace en v2.1.274 o posterior muestra Too many attempts came from your network address en la página de verificación, con la configuración a verificar. También escribe una línea de registro sign-in refused que nombra la configuración a cambiar.

Operaciones

Una vez que la puerta de enlace está sirviendo tráfico, la operación día a día es leer sus registros, sondear su salud y rotar sus secretos en su horario. Las subsecciones cubren cada una, más lo que Postgres contiene y cómo se comportan las actualizaciones y reversiones.

Registros

La puerta de enlace escribe dos flujos a stderr, ambos amigables con JSON:

  • Audit events: JSON de una sola línea por evento relevante para la seguridad. Canalice stderr a su agregador de registros.

    Los eventos emitidos incluyen config.load, session.mint, session.refresh, device.authorize, device.verify, device.callback, auth.denied, access.denied, access.public_client, inference, managed.serve, desktop_bootstrap.serve, desktop_bootstrap.denied, spend.blocked, admin.denied, admin.limit.upsert y admin.limit.delete. Los campos varían según el evento:

    • Los eventos de acuñación y actualización exitosos llevan sub, email, client_ip y el resultado
    • auth.denied y access.denied llevan la razón e IP del cliente, más la ruta de solicitud para auth.denied, ya que no existe identidad de usuario en esas denegaciones. Dos razones de access.denied cambian lo que el evento lleva:
      • xff_unparseable: el evento también lleva la entrada X-Forwarded-For que no se pudo leer
      • client_ip_unknown: el evento no lleva IP del cliente, porque la conexión no tenía dirección de par mientras se establecía una lista de access_control
    • access.public_client lleva la IP del cliente de la primera solicitud por proceso que llega desde una dirección pública mientras access_control.allow_cidrs está vacío. La puerta de enlace sirve la solicitud como de costumbre; el evento señala que la puerta de enlace puede ser alcanzable desde la internet pública. Vea la referencia de access_control para lo que cuenta como público y para la lista de permitidos recomendada.
    • inference registra qué ascendente sirvió la solicitud y el estado de respuesta
    • desktop_bootstrap.denied registra una búsqueda de arranque de Claude Desktop rechazada con la razón (not_configured, policy_not_opted_in o no_policy_matched) y la identidad del usuario
    • admin.denied registra un intento de autenticación de API de administrador rechazado con la IP del cliente, método, ruta y una razón, sin el material de clave presentado: invalid_key cuando se presentó una x-api-key pero no coincidió con ninguna clave configurada, bearer_rejected cuando solo se presentó un encabezado Authorization y no se verificó como una sesión de puerta de enlace en admin.admin_groups, o no_credentials cuando no se presentó ningún encabezado
  • Registros operacionales: líneas legibles por humanos con prefijo [gateway] para arranque, advertencias y errores ascendentes. La variable de entorno CLAUDE_GATEWAY_LOG_LEVEL controla la verbosidad y acepta debug, info, warn o error, con info como predeterminado. En debug, cada inicio de sesión y actualización también registra los nombres, no los valores, de los reclamos en el id_token, más los nombres de los reclamos de userinfo cuando userinfo_fallback proporcionó alguno, para que pueda diagnosticar la configuración de email_claim y groups_claim sin registrar PII. No afecta los eventos de auditoría, que siempre se emiten.

Salud

La puerta de enlace sirve GET /healthz como una sonda de vivacidad y GET /readyz como una sonda de preparación. /readyz verifica que el almacén sea alcanzable. Si establece store.readiness_grace_seconds, /readyz sigue reportando listo durante hasta esa cantidad de segundos después de que el almacén deja de responder.

Ambos extremos están exentos de access_control.allow_cidrs, así que los sondeos siguen funcionando en un oyente bloqueado.

El documento de descubrimiento de OAuth en /.well-known/oauth-authorization-server también devuelve 200 solo después de que se cargue la configuración, descubrimiento OIDC, construcción de cliente ascendente y migración de Postgres tengan éxito, así que funciona como una verificación de arranque de extremo a extremo.

Solicitudes ascendentes concurrentes

De forma predeterminada, cada réplica de puerta de enlace envía como máximo 256 solicitudes ascendentes al mismo tiempo. Una respuesta de transmisión cuenta contra el límite hasta que la transmisión termina.

Una solicitud que llega mientras una réplica está en el límite espera dentro de la puerta de enlace por un espacio libre. El desarrollador ve una respuesta que es lenta para comenzar o parece colgarse. En una puerta de enlace ascendente provider: anthropic, una solicitud que espera más tiempo que timeouts.upstream_ttfb_ms se rinde en esa puerta de enlace ascendente, y falla con un 502 cuando ninguna puerta de enlace ascendente posterior la sirve.

La línea de registro de inicio que contiene upstream requests: muestra el límite en vigor. Mientras una réplica tiene más solicitudes abiertas que el límite, también registra una advertencia que contiene client requests are open, como máximo una vez por minuto.

Para servir más solicitudes a la vez, tiene dos opciones:

  • Agregue réplicas.
  • Aumente el límite en cada réplica. Establezca la variable de entorno BUN_CONFIG_MAX_HTTP_REQUESTS en el contenedor de puerta de enlace en un número entero de 1 a 65535, luego reinicie el contenedor.

Una réplica llena su límite a una velocidad de solicitud de aproximadamente el límite dividido por el número promedio de segundos que una solicitud permanece abierta. Por ejemplo, si las solicitudes permanecen abiertas durante 10 segundos en promedio, una réplica en el límite predeterminado de 256 lo llena a aproximadamente 26 solicitudes por segundo.

Si realiza autoescalado en CPU, una réplica en el límite pone en cola solicitudes sin desencadenar un escalado horizontal, así que establezca el objetivo por debajo del nivel de CPU que sus réplicas muestran cuando registran la advertencia client requests are open.

Comportamiento de interrupciones

Si Postgres se cae, la puerta de enlace en sí sigue sirviendo desarrolladores con sesión iniciada y los nuevos inicios de sesión fallan. Si los desarrolladores realmente siguen trabajando depende de cómo su orquestador maneja la preparación:

  • Sesiones existentes: los tokens portadores se validan localmente con el secreto JWT, las actualizaciones de sesión no tocan el almacén, y el proceso de puerta de enlace aún puede servir inferencia
  • Nuevos inicios de sesión: fallan hasta que Postgres se recupere, porque el flujo de dispositivo y sus contadores de límite de velocidad viven en Postgres
  • Cumplimiento de límite de gasto: falla abierto de forma predeterminada durante la interrupción, así que la inferencia aún fluye; cámbielo a falla cerrada si preferiría bloquear que ejecutar sin medidor
  • Preparación: por defecto /readyz reporta no listo tan pronto como Postgres sea inalcanzable, así que cada réplica falla su verificación de preparación a la vez. Donde el tráfico solo llega a réplicas que pasan la verificación, todo el tráfico, incluida la inferencia que la puerta de enlace podría servir, falla hasta que Postgres se recupere. La sonda de vivacidad en /healthz sigue pasando durante todo.

Si su IdP se cae, las sesiones existentes funcionan hasta ttl_hours y los nuevos inicios de sesión fallan. Una actualización de sesión obtiene una respuesta de reintentar y funciona una vez que el IdP está de vuelta. Establezca un ttl_hours más largo si su IdP tiene ventanas de mantenimiento frecuentes.

Período de gracia de preparación

Para mantener a los desarrolladores con sesión iniciada trabajando a través de una interrupción corta de Postgres, como una conmutación por error de base de datos, establezca store.readiness_grace_seconds a más tiempo que lo que tarda la conmutación por error, por ejemplo 300. Con límites de gasto activados y el comportamiento de falla abierta predeterminado, las solicitudes a través de una réplica que permanece lista no tienen medidor hasta que Postgres se recupere, así que mantenga el valor tan bajo como cubre su conmutación por error. Si establece enforcement.fail_closed_on_error: true, la puerta de enlace rechaza la inferencia de desarrolladores con sesión iniciada con el mensaje 429 spend limit unavailable hasta que Postgres se recupere, incluso mientras las réplicas aún pasan su verificación de preparación.

La configuración requiere Claude Code v2.1.282 o posterior en el servidor de puerta de enlace. Una puerta de enlace anterior se niega a iniciar cuando encuentra la clave, así que actualice cada réplica antes de agregarla. Upgrades cubre la reversión.

Si apunta la sonda de preparación a /healthz en su lugar, las réplicas también siguen pasándola a través de una interrupción, pero /healthz nunca reporta no listo, así que una réplica cuya conexión de Postgres no se recupera sigue pasando también.

Rotación de secreto JWT

Rote el secreto de firma en etapas para que las sesiones existentes permanezcan válidas:

  1. Genere un nuevo secreto. Antepóngalo a la matriz session.jwt_secret.
  2. Despliegue la implementación. Los nuevos tokens firman con el nuevo secreto; los tokens antiguos aún se verifican.
  3. Después de ttl_hours más un margen, elimine el secreto antiguo y despliegue nuevamente.

La rotación también es la única forma de forzar sesiones antes de que expiren: los tokens portadores se validan localmente contra el secreto JWT, así que no hay revocación por sesión. Reemplazar el secreto directamente, sin mantener el antiguo en la matriz, invalida cada sesión pendiente a la vez. Para desaprovisionamiento individual, desaprovision el usuario en su IdP; su sesión termina dentro de ttl_hours.

Postgres

La puerta de enlace contiene cinco tablas de datos más una tabla _migrations, todas creadas por sus migraciones de tiempo de arranque:

Tabla Contenidos Retención
kv Concesiones de dispositivo (TTL de 10 minutos) y contadores de límite de velocidad TTL por fila
spend Contadores de gasto de período a la fecha por principal, en centavos admin.spend_retention_months, predeterminado 13
spend_limits Límites de gasto configurados Hasta eliminado a través de la API
admin_audit Rastro de mutación de API de administrador admin.audit_retention_days, predeterminado 365
principal_emails Correo electrónico de último visto de cada principal, nombre para mostrar y grupos de IdP. Contiene PII. admin.identity_retention_days desde última actividad, predeterminado 90

Un bucle de 30 segundos expira filas kv pasadas su TTL, y un barrido cada hora impone las ventanas de retención en las tablas de gasto, así que nada crece sin límite. Sin límites de gasto configurados, solo se escribe kv. La puerta de enlace aplica sus propias migraciones de esquema al arrancar y en cada actualización, así que su rol de base de datos necesita derechos para crear y alterar tablas. Apúntelo a una base de datos o esquema dedicado a la puerta de enlace para mantener ese permiso estrecho.

Con límites de gasto en uso, una base de datos perdida significa pérdida de seguimiento de gasto y límites, no solo re-inicios de sesión de desarrolladores, así que ejecute copias de seguridad regulares. Para borrar un desarrollador que se fue inmediatamente en lugar de esperar en retención, ejecute DELETE FROM principal_emails WHERE principal = '<sub>' directamente; eso elimina la única tabla que contiene su correo electrónico, nombre y grupos. Las filas spend y admin_audit hacen referencia solo al sub OIDC seudónimo.

Actualizaciones

Las réplicas son sin estado, así que un reinicio rodante no pierde ningún estado de puerta de enlace. La puerta de enlace ejecuta migraciones de esquema al arrancar, lo que significa que implementar el nuevo binario auto-migra la base de datos. Las réplicas concurrentes se serializan en un bloqueo de asesor de Postgres, así que solo una aplica cada migración.

Cuando su orquestador detiene una réplica con SIGTERM, como en un reinicio rodante o una reducción de escala, la puerta de enlace deja de aceptar nuevas conexiones y permite que las solicitudes y transmisiones ya en vuelo terminen antes de salir. Espera hasta 25 segundos, llamado la ventana de drenaje, luego cierra lo que aún esté abierto. Un SIGINT, como Ctrl+C en una terminal, inicia el mismo drenaje, y una segunda señal durante el drenaje cierra las solicitudes abiertas y sale de inmediato. El drenaje requiere puerta de enlace v2.1.274 o posterior.

Las generaciones largas pueden transmitir durante minutos. En Kubernetes y Amazon ECS, aumente ambos de estos juntos para dar a esas transmisiones más tiempo:

  • La ventana de drenaje: establezca la variable de entorno CLAUDE_GATEWAY_DRAIN_TIMEOUT_MS en el contenedor de puerta de enlace en un número entero positivo de milisegundos, como 120000. La puerta de enlace ignora un valor en cualquier otra forma, como 120s, y mantiene el predeterminado de 25 segundos
  • El período de gracia de su orquestador: terminationGracePeriodSeconds en Kubernetes, o stopTimeout en Amazon ECS

El período de gracia predeterminado es de 30 segundos en ambas plataformas. Manténgalo al menos 5 segundos más largo que la ventana de drenaje, o el orquestador matará la puerta de enlace antes de que el drenaje termine. En Kubernetes, agregue también la duración de cualquier gancho preStop, porque el período de gracia comienza a contar antes de que el gancho se ejecute en lugar de cuando la puerta de enlace recibe SIGTERM.

Su plataforma también puede limitar cuánto tiempo puede ejecutarse el drenaje:

  • Amazon ECS en Fargate: stopTimeout permite como máximo 120 segundos
  • Cloud Run: detiene una instancia 10 segundos después de SIGTERM, así que las transmisiones abiertas obtienen como máximo 10 segundos allí, sea cual sea la ventana de drenaje

Cuando la ventana de drenaje termina con solicitudes aún abiertas, la puerta de enlace registra una advertencia que contiene drain window over after, cuenta las solicitudes que cortó, y nombra ambas configuraciones para aumentar.

Las migraciones son solo anexo, así que revertir a un binario anterior que conoce menos migraciones es seguro; ignora las filas adicionales. La reversión también re-valida el YAML contra el esquema del binario más antiguo, así que una configuración que adoptó una clave introducida por la versión más nueva falla al arrancar en la más antigua. Elimine la nueva clave antes de revertir.

Porque fija la versión de la puerta de enlace en su propia imagen, las correcciones en nuevas versiones de Claude Code, incluidas las correcciones de seguridad, llegan a su implementación solo cuando actualiza el pin y redeploy. Incluya la puerta de enlace en el mismo ciclo de parches que usa para otros servicios que contienen credenciales de producción.

Seguridad

Esta sección responde las preguntas que una revisión de seguridad hace: qué datos fluyen a través de la puerta de enlace y hacia dónde van, qué ataques defiende el diseño, y qué respuestas pertenecen en un cuestionario de cumplimiento.

Flujo de datos

Datos Ruta Enviado a Anthropic por la puerta de enlace
Inferencia (indicaciones, finalizaciones) CLI → puerta de enlace → su ascendente Solo si la API de Anthropic es un ascendente configurado
Telemetría (métricas OTLP, más registros y trazas opcionales) CLI → puerta de enlace → su recopilador Nunca
Identidad (correo electrónico, grupos, sub) IdP → puerta de enlace → CLI; el CLI lo marca en exportaciones OTLP. Si activa forward_user_identity, la puerta de enlace también envía el correo electrónico del desarrollador y el asunto de IdP como encabezados a su proxy Nunca
Configuraciones administradas Su YAML de puerta de enlace → CLI Nunca
Registro de auditoría Stderr de puerta de enlace → su agregador Nunca

Resumen del modelo de amenaza

La puerta de enlace se sienta dentro de su perímetro de red, pero las máquinas portátiles de desarrolladores individuales no se tratan como confiables. El diseño cuenta para esto de tres maneras:

  • Los desarrolladores sostienen JWTs de corta duración en lugar de claves ascendentes sin procesar. La pierna CLI-a-puerta de enlace usa la concesión de dispositivo RFC 8628, y el intercambio de código de autorización de la puerta de enlace con el IdP ejecuta PKCE en la configuración predeterminada, así que un código de autorización de IdP interceptado es inútil.

  • La página de verificación de dispositivo impone POST del mismo origen y un límite de velocidad por IP por RFC 8628 §5.1. Consulte Resistencia de fuerza bruta de código de usuario.

  • Las solicitudes de la puerta de enlace a su IdP, sus recopiladores OTLP, y ascendentes provider: anthropic pasan por una protección de falsificación de solicitud del lado del servidor (SSRF) que resuelve DNS, bloquea direcciones de enlace local y metadatos en la nube más loopback de forma predeterminada, y fija la conexión a la IP resuelta, así que URLs influenciadas por el operador no pueden ser redirigidas a puntos finales de metadatos en la nube. Los rangos privados RFC 1918 se permiten deliberadamente, porque los IdPs y recopiladores OTLP comúnmente viven en IPs privadas. Para los otros proveedores, la puerta de enlace rechaza un base_url que nombre una de esas direcciones o un nombre de host de metadatos cuando carga la configuración, y el SDK del proveedor luego se conecta sin la verificación de DNS.

    Si activa egreso solo proxy, esa verificación de dirección se mueve a su proxy directo: la puerta de enlace le entrega nombres de host y la lista de permitidos del proxy debe rechazar esos destinos.

    Establezca CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 en el entorno de la puerta de enlace solo cuando algo que la puerta de enlace debe alcanzar legítimamente vive en loopback, como un IdP de desarrollo local o un recopilador OTLP sidecar en localhost. La variable relaja el bloque de loopback para cada URL configurada por el operador y también omite la advertencia de tiempo de arranque que verifica si el pod puede alcanzar el punto final de metadatos en la nube, así que prefiera dar al recopilador su propia dirección interna.

Si agrega sus propios controles de salida, la puerta de enlace debe alcanzar el servidor de metadatos siempre que use credenciales de metadatos de instancia como identidad de carga de trabajo.

Dos amenazas están fuera del alcance porque son su infraestructura para asegurar:

  • Un host de puerta de enlace comprometido: el host tanto contiene la credencial ascendente como distribuye configuraciones administradas a cada desarrollador conectado, así que el control sobre la configuración de la puerta de enlace es comparable al control sobre su MDM. El diálogo de aprobación del CLI para configuraciones capaces de shell limita cambios silenciosos pero no reemplaza la seguridad del host.
  • Un proveedor OIDC malicioso: el proveedor firma los id_tokens que la puerta de enlace confía, así que puede afirmar cualquier identidad. Verificar y asegurar su IdP es su responsabilidad.

Resistencia de fuerza bruta de código de usuario

El user_code que un desarrollador escribe en la página de verificación /device son 8 caracteres extraídos de un alfabeto de 20 caracteres, que produce 20⁸ o aproximadamente 2.56×10¹⁰ combinaciones, y expira después de 10 minutos.

La puerta de enlace aplica límites de velocidad por IP en los puntos finales de concesión de dispositivo, configurables a través de rate_limits. Aumente los límites si muchos desarrolladores inician sesión desde una única dirección NAT corporativa compartida. Los despliegues grandes muestran cómo dimensionarlos. Los límites se aplican solo al flujo de inicio de sesión, no a la inferencia.

Postura de cumplimiento

  • Residencia de datos: el plano de datos propio de la puerta de enlace no envía nada a Anthropic a menos que la API de Anthropic sea un ascendente configurado; cuando lo es, su acuerdo de manejo de datos existente se aplica a la ruta de inferencia. Telemetría, auditoría, identidad y configuraciones van solo a los destinos que configura.
  • Tráfico de proceso de host: el proceso de host es el CLI de Claude Code. claude gateway se ejecuta bajo las mismas reglas de terceros que las implementaciones de Amazon Bedrock y Google Cloud's Agent Platform y no envía nada a Anthropic. Antes de v2.1.227, el proceso de host enviaba telemetría de inicio como versión de producto y plataforma, que establecer CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 en el entorno del contenedor desactivaba. Esos lanzamientos también enviaban una solicitud HEAD al arranque, sin cuerpo ni credenciales, a /api/hello en https://api.anthropic.com, o en ANTHROPIC_BASE_URL cuando el entorno lo establecía, a menos que el entorno también estableciera una variable proxy como HTTPS_PROXY o un certificado de cliente mTLS. Ignoraban la respuesta, así que bloquear esa solicitud en el firewall de salida no afectaba la puerta de enlace.
  • Análisis del cliente: el CLI deshabilita su propio análisis de uso y reporte de errores mientras está conectado a una puerta de enlace. Antes del primer inicio de sesión, el CLI aún envía eventos de inicio a Anthropic, incluso en máquinas cuyas configuraciones administradas fuerzan el inicio de sesión de puerta de enlace. Para mantener esos también apagados, entregue DISABLE_TELEMETRY en las mismas configuraciones administradas del lado del cliente que fuerzan el inicio de sesión de puerta de enlace.
  • Reporte de errores: el CLI desactiva el reporte de errores siempre que sus solicitudes de modelo vayan a cualquier punto final que no sea la API de primera parte de Anthropic, como Amazon Bedrock o un ANTHROPIC_BASE_URL personalizado.
  • Máquinas cliente: las CLI de los desarrolladores todavía envían verificaciones de nombres de host de WebFetch y verificaciones de versión a Anthropic, a menos que se establezcan CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 y skipWebFetchPreflight: true. Las solicitudes de marketplaces de plugins tienen sus propios mecanismos para desactivarlas. Consulta uso de datos.
  • Calificaciones de encuesta: mientras está conectado a una puerta de enlace, el CLI deshabilita la carga de calificación vinculada a Anthropic junto con los flujos de análisis, así que no envía calificaciones a Anthropic.
  • Compartir transcripción: elegir Sí en el indicador de compartir transcripción de una encuesta escribe un archivo local bajo ~/.claude/feedback-bundles/ en lugar de cargar a Anthropic.
  • Actualizaciones del cliente: las verificaciones de actualización son separadas del tráfico de puerta de enlace. Fije versiones a través de su propia distribución y establezca DISABLE_UPDATES si las máquinas portátiles no deben obtener lanzamientos. DISABLE_AUTOUPDATER detiene solo actualizaciones de fondo mientras claude update aún funciona.
  • TLS: sirva public_url sobre HTTPS en producción, ya sea desde el oyente propio de la puerta de enlace a través de listen.tls o desde un ingress que termina TLS frente a réplicas HTTP simples, con listen.public_url establecido en ambos casos. La puerta de enlace no rechaza HTTP simple. El IdP debe servir HTTPS en producción, y Postgres admite ?sslmode=require. Establezca Strict-Transport-Security en su ingress.
  • Divulgación de vulnerabilidad: siga Reportar problemas de seguridad

Solicitudes de marketplaces de plugins

Claude Code obtiene los marketplaces de plugins directamente desde la máquina de cada desarrollador, no a través del gateway. Requisitos de acceso a la red enumera los hosts.

La primera vez que un desarrollador inicia una sesión interactiva en la terminal, Claude Code registra el marketplace oficial, claude-plugins-official. Descarga el catálogo desde downloads.claude.ai y, si eso falla, lo clona desde github.com. Qué marketplaces y plugins se actualizan automáticamente cubre las actualizaciones posteriores.

CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 no detiene el primer registro. Cualquiera de estos ajustes de la configuración administrada sí lo detiene:

  • Una lista de marketplaces: una lista de permitidos strictKnownMarketplaces que deje fuera el marketplace, o una entrada de blockedMarketplaces que lo indique
  • Una variable de entorno: CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL establecida en "1" en el bloque env administrado

El primer registro puede ejecutarse antes de que el desarrollador inicie sesión en el gateway, cuando todavía no ha llegado ninguna política del gateway. Para cubrir ese primer inicio, entrega tu elección en la configuración administrada del lado del cliente, además de en el bloque cli de la política del gateway.

Solución de problemas

Para preguntas y comentarios, usa el soporte de Claude Code o abre un issue en el repositorio de GitHub de Claude Code. Al reportar un problema, incluye:

  • Problema del gateway: el stderr del gateway para el intervalo correspondiente, tu gateway.yaml con los secretos ocultos, la versión del gateway, que se muestra en la página de inicio en / y en el encabezado de respuesta x-cc-gateway-version en /managed/settings, y qué cambió recientemente
  • Problema de inicio de sesión: el desarrollador ejecuta claude --debug-file ./claude-debug.txt, reproduce el problema y envía ese archivo junto con el registro de auditoría del gateway para el mismo intervalo
  • Problema de inferencia: el modelo solicitado, los upstreams configurados y el registro de auditoría del gateway para la solicitud, que registra qué upstream la atendió y el estado de la respuesta

El stderr del gateway incluye el flujo de eventos de auditoría, el registro de auditoría registra las identidades de los desarrolladores y el archivo de depuración registra la salida de hooks y servidores MCP de la máquina del desarrollador. Revísalos y oculta la información sensible antes de publicarlos en un issue público.

Síntoma Causa Solución
El /login de un desarrollador muestra el selector de cuenta estándar en lugar de la pantalla Cloud gateway forceLoginMethod o forceLoginGatewayUrl no está establecido en la configuración administrada de esa máquina Implementa el archivo de configuración administrada en el dispositivo; /login lee la URL del gateway desde allí
Las solicitudes de un desarrollador fallan con Not signed in to the Cloud gateway — run /login. La configuración administrada de la máquina establece forceLoginMethod: "gateway" o forceLoginGatewayUrl, y la sesión no tiene un inicio de sesión en el gateway. Un inicio de sesión de claude.ai que haya quedado no satisface el requisito. Pide al desarrollador que ejecute /login y complete el inicio de sesión en el gateway. Consulta también La política del administrador requiere un inicio de sesión en el Cloud gateway.
Claude Desktop informa que no se pudo obtener su configuración de arranque /user/bootstrap devolvió 404: la política que coincide con el usuario no tiene una clave desktop, o ninguna política coincidió. El registro de auditoría del gateway registra cada rechazo como desktop_bootstrap.denied con el motivo. Agrega un bloque desktop a la política que coincide con el usuario, o a la capa base match: {}; basta con un desktop: {} vacío. Consulta Superposición de Claude Desktop.
Al iniciar se muestra Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support. La compilación de Claude Code instalada es anterior al soporte del gateway Pide al desarrollador que actualice Claude Code a una versión que incluya soporte para Cloud gateway
Al iniciar, sale con Administrator policy requires a Cloud gateway sign-in on this machine El entorno del desarrollador establece ANTHROPIC_API_KEY o ANTHROPIC_AUTH_TOKEN, su configuración define un apiKeyHelper, o todavía hay guardada una clave de API de un inicio de sesión anterior en Claude Console Pide al desarrollador que elimine cada uno que aplique: quitar la variable, eliminar la entrada apiKeyHelper o ejecutar claude auth logout para eliminar la clave guardada. Una sesión que selecciona un proveedor de nube con CLAUDE_CODE_USE_* entonces inicia sin inicio de sesión; para cualquier otra sesión, pídele que inicie claude e inicie sesión con /login. Consulta también La política del administrador requiere un inicio de sesión en el Cloud gateway.
Al iniciar o en /login se informa Claude Code may not be enabled for your organization después de un 403 al cargar la configuración administrada El gateway, o algo delante de él, respondió a la solicitud /managed/settings con 403. La propia ruta de configuración del gateway nunca responde 403. El estado proviene de las verificaciones de IP de access_control o de un proxy o WAF delante del gateway. El registro de auditoría registra un rechazo por verificación de IP como access.denied con el motivo. El desarrollador sigue con la sesión iniciada. Busca access.denied en el registro de auditoría en el momento del fallo y corrige las listas de access_control o el front end; luego pide al desarrollador que inicie claude de nuevo
CLI /login: The gateway is limiting sign-in attempts right now, o Request failed with status code 429 en versiones anteriores. La página /device puede mostrar Too many attempts a desarrolladores que no lo han intentado antes Se alcanzó el rate limit de inicio de sesión por IP. O bien listen.trusted_proxies no cubre el balanceador de carga, por lo que todos los desarrolladores comparten su dirección, o muchos desarrolladores comparten una dirección de salida de NAT o VPN. Los eventos de auditoría con result: rate_limited muestran el mismo valor de client_ip o unos pocos. Primero establece listen.trusted_proxies en los rangos de origen del balanceador de carga y luego aumenta rate_limits si los desarrolladores siguen compartiendo direcciones. Consulta Despliegues a gran escala.
CLI /login: Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip> El nombre de host del gateway se resuelve en al menos una dirección IP pública. Claude Code verifica cada dirección resuelta y exige que todas sean privadas. Una causa común es un nombre de doble pila en el que una familia se resuelve en una dirección pública, incluidos los balanceadores de carga internos de doble pila de AWS, que devuelven direcciones AAAA de rango público. Haz que el nombre del gateway se resuelva solo en direcciones privadas en las máquinas de los desarrolladores. Para un nombre de doble pila, elimina el registro de rango público o sirve un nombre DNS aparte, solo interno. Consulta el requisito previo de red privada. Si la dirección pertenece a un espacio público que tu organización posee y usa internamente, declara ese bloque en su lugar.
CLI /login: Gateway login would go through proxy <proxy>, which is not on a private network Un HTTPS_PROXY o HTTP_PROXY se aplica al host del gateway y el nombre de host del proxy se resuelve en una dirección pública. Un proxy cuyo host se resuelve solo en direcciones privadas está permitido y no provoca este error Agrega el host del gateway a NO_PROXY en la máquina del desarrollador para que la conexión sea directa, o usa un proxy cuyo nombre de host se resuelva en direcciones privadas. El mensaje indica la entrada exacta de NO_PROXY que debes agregar
CLI /login: Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it El gateway está en un bloque declarado en gatewayInternalNetworks, y la máquina del desarrollador llegó a él desde una dirección fuera de ese bloque: un pool de direcciones de VPN, un segmento NAT de contenedor o de WSL2, o una red que no es tuya Pide al desarrollador que ejecute /login desde el sistema operativo anfitrión en tu red. Si la dirección mostrada también pertenece al espacio público de tu organización, reemplaza la entrada del gateway por un bloque que cubra ambos, hasta /8; una segunda entrada superpuesta se rechaza
CLI /login: Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip> El nombre del gateway se resuelve en una dirección fuera del bloque declarado en gatewayInternalNetworks: un segundo sitio, o un registro IPv6 en un nombre de doble pila. Con un bloque declarado, todos los registros deben estar dentro de ese único bloque IPv4, incluidas las direcciones privadas e IPv6 Publica solo registros dentro del bloque para el nombre del gateway en las máquinas de los desarrolladores, o sirve un nombre aparte, solo interno
CLI /login: <host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy Un HTTPS_PROXY o HTTP_PROXY se aplica a un gateway en un bloque declarado En la máquina del desarrollador, agrega la entrada de NO_PROXY que indica el mensaje
CLI /login: un mensaje que comienza con gatewayInternalNetworks in managed settings El valor infringe una de las reglas de validación, y el mensaje indica cuál. Hasta que lo corrijas, Claude Code rechaza cualquier nuevo /login de gateway en la máquina, incluidos los gateways en direcciones privadas; los inicios de sesión existentes siguen funcionando En la fuente de configuración administrada que implementas, corrige la entrada que indica el mensaje y luego vuelve a ejecutar /login
CLI /login: Could not resolve the configured HTTP proxy El nombre de host en HTTPS_PROXY o HTTP_PROXY no se resuelve desde la máquina del desarrollador, normalmente porque no está conectada a la red corporativa Pide al desarrollador que se conecte a tu red o VPN y vuelva a intentarlo, o corrige la URL del proxy
CLI /login: Could not resolve gateway host <host> La máquina no puede resolver el nombre DNS interno del gateway, normalmente porque no está en la red corporativa Pide al desarrollador que se conecte a tu red o VPN y luego reintente /login
El arranque sale con un error de validación de configuración que menciona store.postgres_url No hay Postgres configurado; el gateway requiere Postgres Establece store.postgres_url. Para desarrollo local, usa un contenedor desechable: docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres.
El arranque sale con: requires the native binary Se está ejecutando con Node en lugar del binario nativo Instala Claude Code con uno de los métodos de instalación independiente
El arranque sale con un error de descubrimiento OIDC después de config.load oidc.issuer no es accesible, o la cadena TLS no es de confianza Verifica que el emisor sea accesible desde el pod y sirva /.well-known/openid-configuration. Establece ca_cert_pem para una PKI privada. Si el pod llega al IdP solo a través de un proxy de reenvío, establece oidc.use_proxy: true; en versiones anteriores a v2.1.227, dale al pod una ruta directa a cada uno de los endpoints del IdP en su lugar. Si el pod tampoco puede resolver el nombre de host del IdP, o el proxy rechaza CONNECT a una dirección IP, consulta Salida solo por proxy, que requiere v2.1.277 o posterior.
El arranque sale con un error de permisos de Postgres El rol de la base de datos no tiene derechos DDL sobre su esquema Otorga al rol CREATE sobre el esquema del gateway para que pueda crear y modificar sus tablas al arrancar
Registro: could not connect to Postgres at boot, attempt 1 of 3 La base de datos aún no era accesible cuando se inició el gateway, por ejemplo en una instancia en frío cuya red todavía se está levantando Si el gateway luego termina de arrancar, no hace falta hacer nada. Cuando la base de datos no es accesible, el gateway intenta la conexión tres veces, con dos segundos de diferencia, antes de salir. Si sale con could not connect to Postgres, revisa store.postgres_url y la ruta de red hacia la base de datos. Si se agota el tiempo de espera de los intentos en lugar de ser rechazados, aumenta store.connect_timeout_seconds para darle más tiempo a cada uno.
/oauth/callback muestra "Sign-in could not be completed" Dominio de correo electrónico rechazado, falló la validación del id_token, o email_verified es explícitamente false, que el gateway siempre rechaza sin posibilidad de sobrescribirlo Revisa allowed_email_domains y que el IdP devuelva un claim email verificado. Para email_verified: false, corrige la verificación del lado del IdP. Si tu IdP emite el correo electrónico con un nombre de claim diferente, establece oidc.email_claim.
Registro: token exchange failed request_id=<id>: id_token missing email claim El IdP no incluye email en el id_token de forma predeterminada. Este rechazo solo se produce cuando allowed_email_domains está establecido; sin él, la falta de correo electrónico genera una sesión sin correo electrónico Configura el IdP para que emita email en el id_token. Okta: agrega email a los claims del token de ID de un servidor de autorización personalizado. Entra: agrega email como claim opcional en el registro de la aplicación. PingFederate: habilita una OpenID Connect Policy que emita email. Si el IdP sirve email desde el endpoint de userinfo pero no lo incluye en el id_token, como el servidor de autorización de organización de Okta, establece oidc.userinfo_fallback: true.
Registro: refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …), y los desarrolladores ven Cloud gateway session expired cada session.ttl_hours El IdP aceptó el token de actualización pero no devolvió ningún id_token con él, así que el gateway solicitó los claims del usuario al endpoint de userinfo del IdP. El IdP rechazó allí el token de acceso actualizado. El gateway responde temporarily_unavailable, por lo que Claude Code conserva el token de actualización pero no puede renovar la sesión. Las versiones del gateway anteriores a v2.1.260 registran la misma línea sin el detalle (at …). Establece oidc.scope_on_refresh: true, disponible en el gateway v2.1.260 o posterior, para que la solicitud de actualización pida openid de nuevo. Algunos IdP, como Okta, devuelven un id_token en la actualización solo cuando se solicita. En PingFederate, habilita Return ID Token On Refresh Grant en Applications > OAuth > OpenID Connect Policy Management en su lugar. La clave no cambia el comportamiento de PingFederate. Para otros IdP que sigan omitiéndolo, verifica si el endpoint de userinfo acepta tokens de acceso emitidos por una actualización. Como solución provisional, aumenta session.ttl_hours. Consulta Configuración del proveedor de identidad para conocer la contrapartida en cuanto al desaprovisionamiento.
Un desarrollador inicia sesión y luego todas las solicitudes de esa sesión fallan con un error 431 El token de sesión en el encabezado Authorization de cada solicitud enumera los grupos del IdP del desarrollador, por lo que, para un desarrollador que pertenece a muchos grupos, los encabezados pueden superar en total lo que acepta el gateway Consulta Encabezados de solicitud demasiado grandes después de iniciar sesión para saber qué límite aplica y qué cambiar
Todas las solicitudes a Amazon Bedrock devuelven 502; el registro muestra Could not load credentials from any providers En EC2, el límite de saltos predeterminado de IMDSv2, que es 1, bloquea la solicitud de metadatos de instancia desde dentro del contenedor. El arranque y /readyz pasan de todos modos porque el SDK de AWS resuelve las credenciales de la instancia en la primera solicitud, no al construir el cliente Aumenta el límite de saltos con aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2, o establécelo en la plantilla de lanzamiento. El cambio se aplica a todos los contenedores de la instancia. Cuando estén disponibles, prefiere los roles de tarea de ECS, que leen las credenciales desde el endpoint de credenciales de contenedor de ECS y evitan el cambio por completo, o aplica el cambio en una instancia dedicada al gateway para limitar la exposición.
Con carga máxima, las respuestas tardan en empezar o parecen colgarse, o fallan con un 502 all upstreams failed aunque el upstream esté en buen estado Una réplica tiene más solicitudes abiertas de las que envía al upstream a la vez, por lo que las solicitudes adicionales esperan dentro del gateway. En un upstream provider: anthropic, una solicitud que espera más de timeouts.upstream_ttfb_ms abandona ese upstream, lo que produce el 502 cuando ningún upstream posterior la atiende. El registro muestra una advertencia que contiene client requests are open. Agrega réplicas o aumenta el límite en cada réplica. Consulta Solicitudes upstream concurrentes.
Error del IdP: unknown or unsupported scope El IdP rechaza los alcances que no reconoce Establece oidc.scopes exactamente en la lista que acepta tu IdP; debe incluir openid. El valor predeterminado es openid profile email offline_access.
Las sesiones no se renuevan de forma silenciosa después de establecer oidc.scopes offline_access se eliminó en la sobrescritura Vuelve a agregar offline_access si tu IdP lo admite. Sin un token de actualización, los desarrolladores vuelven a hacer el inicio de sesión en el navegador cada session.ttl_hours.
El navegador muestra "This request came from another site and was blocked" POST de formulario entre sitios, bloqueado como protección contra CSRF. Es lo esperado en páginas incrustadas o servidas a través de un proxy Abre el enlace de verificación directamente
Chrome bloquea el botón Aprobar con "Refused to send form data … violates … Content Security Policy directive: form-action", pero la misma página funciona en Safari o Firefox Chrome aplica form-action a toda la cadena de redirecciones. Tu IdP redirige a continuación a un segundo host que no está en la lista de permitidos. Agrega a oidc.form_action_origins cada origen adicional de la cadena de redirecciones. Abre Chrome DevTools → Console en la página Aprobar para ver qué origen se bloqueó.
El inicio de sesión se completa en el IdP pero el callback falla, con un error de CSP en Chrome o "this sign-in link has expired" en Safari El IdP devolvió el código mediante response_mode=form_post, que lo envía automáticamente entre orígenes mediante POST a /oauth/callback. Chrome lo bloquea con una CSP estricta; Safari permite el envío, pero el callback solo lee la cadena de consulta. Asegúrate de que tu IdP respete response_mode=query, que el gateway solicita explícitamente para que el callback sea una redirección simple
El inicio de sesión funciona localmente pero falla detrás de un ALB public_url todavía indica el origen http:// local o interno, por lo que el IdP recibe un redirect_uri incorrecto Establece listen.public_url en el origen https:// externo y registra <public_url>/oauth/callback en el IdP
El desarrollador ve la solicitud de confianza repetidamente El certificado TLS cambia según la réplica o según la solicitud Usa un certificado estable en el ingress, o termina TLS una sola vez y ejecuta las réplicas internamente sobre HTTP simple
CLI /login: "Could not verify the gateway's TLS certificate" o SELF_SIGNED_CERT_IN_CHAIN La cadena TLS del gateway está firmada por una CA privada que no está en el almacén de confianza del host de la CLI Claude Code lee el almacén de confianza del sistema operativo de forma predeterminada en el binario nativo y en Node 22.15 o posterior; CLAUDE_CODE_CERT_STORE controla este comportamiento. Si la CA está instalada en el almacén de confianza del sistema operativo, asegúrate de que los desarrolladores usen un runtime actual. De lo contrario, establece NODE_EXTRA_CA_CERTS en el PEM del certificado de la CA antes de iniciar. La solicitud de confirmación de huella digital en la primera conexión sigue aplicándose.
CLI /login completa el inicio de sesión en el navegador y luego la sesión termina con Cloud gateway sign-in was not completed y una discrepancia de certificado TLS En la primera solicitud después de iniciar sesión, el gateway presentó un certificado que no coincide con la huella digital que Claude Code fijó, por lo que Claude Code no conservó ninguna credencial del gateway. Las causas habituales son réplicas detrás de una misma dirección que sirven certificados diferentes, o algo en la ruta de red que intercepta TLS. Sirve un único certificado para el nombre de host, por ejemplo terminando TLS una sola vez en el ingress, y luego pide al desarrollador que ejecute /login de nuevo. Si ese certificado difiere del fijado, Claude Code vuelve a mostrar la solicitud de confianza con una advertencia de que el certificado cambió.
CLI /login se detiene con The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted Una solicitud de inicio de sesión llegó a un servidor cuyo certificado no coincide con el que el desarrollador aceptó cuando comenzó /login: réplicas detrás de una misma dirección que sirven certificados diferentes, interceptación de TLS en la ruta, o una rotación de certificado mientras el inicio de sesión estaba en curso. Sirve un único certificado para el nombre de host y luego pide al desarrollador que vuelva a iniciar el inicio de sesión y revise el nuevo certificado en la solicitud de confianza.

El mensaje Cloud gateway sign-in was not completed indica el nombre de host del gateway. Cuando Claude Code tiene tanto la huella digital fijada como la presentada, el mensaje también muestra los primeros 16 caracteres de cada una.

Si Claude Code informa couldn't load your organization's managed settings después de un inicio de sesión en el gateway, Claude Code indica el motivo, se reinicia en el mismo lugar y reanuda la conversación. Si Claude Code no puede reiniciarse, por ejemplo en una sesión en segundo plano, Claude Code termina la sesión y conserva el inicio de sesión.

Encabezados de solicitud demasiado grandes después de iniciar sesión

Las solicitudes de un desarrollador pueden fallar con un error 431 después de iniciar sesión cuando el desarrollador pertenece a muchos grupos del IdP.

El gateway responde 431 cuando los encabezados de una solicitud suman más de 256 KiB, o más de limits.max_request_header_bytes si lo estableces. No escribe ninguna línea de registro ni evento de auditoría para estas solicitudes. Las versiones del gateway anteriores a v2.1.284 responden 431 por encima de 16 KiB.

Lo que debes cambiar depende de la versión y la configuración de tu gateway:

  • Gateway anterior a v2.1.284: actualiza el gateway
  • limits.max_request_header_bytes establecido: aumenta el valor o elimina la clave
  • No aplica ninguno de los dos, o el 431 continúa después: haz que tu IdP emita menos grupos. Configuración del proveedor de identidad explica cómo Okta, Microsoft Entra ID y Google Workspace proporcionan los grupos