Okta puede actuar como un proveedor de identidad de cargas de trabajo emitiendo tokens de acceso OIDC a una aplicación de servicio mediante el grant client_credentials de OAuth 2.0. Tu carga de trabajo se autentica ante Okta (normalmente con private_key_jwt, de modo que no se almacena ningún secreto compartido), recibe un "JSON Web Token" (token web JSON), o JWT, firmado, e intercambia ese JWT con Anthropic por un token de acceso de corta duración.
La URL del emisor del servidor de autorización de Okta tiene la forma https://<your-domain>.okta.com/oauth2/<auth-server-id>. Si usas el servidor predeterminado integrado, la ruta es /oauth2/default.
Debes usar un servidor de autorización personalizado de Okta (incluido el default). Los tokens emitidos directamente por el servidor de autorización de la organización de Okta (el endpoint /oauth2/v1/token sin un ID de servidor de autorización en la ruta) no pueden ser validados por terceros externos porque Okta no publica claves de firma para ellos.
Existen muchas formas de configurar Okta y autenticarse ante él que quedan fuera del alcance de esta documentación. Asegúrate de que tu configuración y tus mecanismos de autenticación sigan las directrices y prácticas de seguridad de tu empresa.
/v1/token de Okta y acceder a api.anthropic.com.A grandes rasgos, necesitas:
La navegación exacta depende de la configuración de tu organización de Okta y de la versión de la consola de administración. Los pasos numerados a continuación recorren una ruta común:
private_key_jwt) y registra la JWK pública de tu carga de trabajo. Como alternativa, usa un client secret si tu entorno puede almacenarlo de forma segura. Para el siguiente ejemplo, es posible que debas deshabilitar el requisito de DPoP en la aplicación; asegúrate de que tu configuración de producción cumpla con los requisitos de seguridad de tu organización.https://api.anthropic.com para que los tokens de acceso emitidos incluyan ese claim aud. Anthropic valida aud contra este valor fijo.anthropic.access). Okta rechaza las solicitudes client_credentials que no incluyen un scope concedido.Para una aplicación de servicio que usa client_credentials, Okta establece el claim sub del token de acceso emitido en el Client ID de la aplicación, e iss en la URL del emisor del servidor de autorización.
Sigue la guía de configuración para registrar un emisor de federación, crear una cuenta de servicio de Anthropic y crear una regla de federación en Claude Console. Usa estos valores específicos de Okta.
Emisor de federación: Usa la URL de tu servidor de autorización personalizado de Okta y el modo de descubrimiento. Anthropic lee el documento de descubrimiento .well-known/openid-configuration de Okta y obtiene el JWKS desde el jwks_uri que este anuncia.
{
"name": "okta-prod",
"issuer_url": "https://acme.okta.com/oauth2/aus1a2b3c4d5e6f7g8h9",
"jwks_source": "discovery"
}Regla de federación: Haz coincidir con el claim sub de Okta, que es el Client ID de la aplicación de servicio. Si definiste claims personalizados en Okta, puedes hacer coincidir con ellos en su lugar mediante el mapa claims o una condition CEL.
{
"name": "okta-pipeline",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "0oa1b2c3d4e5f6g7h8i9",
"audience": "https://api.anthropic.com"
},
"target": { "type": "service_account", "service_account_id": "svac_..." },
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}A diferencia de los proveedores nativos de plataforma (AWS, Google Cloud, Kubernetes), que ponen un token a disposición dentro del entorno de ejecución de la carga de trabajo (a través de un archivo proyectado o un endpoint de metadatos local), Okta no lo hace. Tu carga de trabajo debe llamar al endpoint de token de Okta para obtener un JWT y luego pasar ese JWT al SDK de Anthropic como el token de identidad.
Cada pestaña de SDK muestra el patrón invocable: el SDK de Anthropic vuelve a llamar a tu proveedor de token de identidad cada vez que el token de acceso de Anthropic se acerca a su expiración, por lo que tu función de obtención de Okta debe devolver un token nuevo en cada llamada en lugar de almacenar uno en caché indefinidamente. La CLI ant vuelve a leer ANTHROPIC_IDENTITY_TOKEN_FILE en cada intercambio, así que actualiza ese archivo con un temporizador para shells de larga duración.
Un intercambio exitoso devuelve un access_token que comienza con sk-ant-oat01- y un valor expires_in en segundos. Si recibes 400 invalid_grant, consulta Solucionar problemas de un intercambio fallido; la causa más común del lado de Okta es una discrepancia en issuer_url (debe incluir la ruta /oauth2/<auth-server-id>; el servidor de autorización de la organización de Okta no es utilizable).
Varias aplicaciones de servicio bajo el mismo servidor de autorización de Okta comparten el mismo
emisor. Una regla que omite subject_prefix coincide con todas las aplicaciones de servicio de ese
servidor, por lo que cualquier equipo que pueda registrar una podría obtener un token federado de Anthropic.
Restringe el bloque match de la regla al alcance más estrecho que se ajuste a tu caso de uso:
subject_prefix en el Client ID completo de la aplicación de servicio sin un * al final.audience que configuraste en el servidor de autorización para que se rechacen los tokens emitidos para una audiencia diferente.claims de la regla o una condition CEL.Was this page helpful?
import os
import httpx
import anthropic
from anthropic import WorkloadIdentityCredentials
def fetch_okta_token() -> str:
response = httpx.post(
f"{os.environ['OKTA_ISSUER']}/v1/token",
data={
"grant_type": "client_credentials",
"scope": "anthropic.access",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
# Construye el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de Okta
"client_assertion": build_signed_client_assertion(),
},
)
response.raise_for_status()
return response.json()["access_token"]
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=fetch_okta_token,
federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
),
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(message.content[0].text)