{"record":{"id":"7c96308aba2ae317","repo":"BerriAI/litellm","slug":"oidc-token-could-not-be-retrieved-from-secret-mana","errorCode":null,"errorMessage":"OIDC token could not be retrieved from secret manager.","messagePattern":"OIDC token could not be retrieved from secret manager\\.","errorType":"http","errorClass":"AzureOpenAIError","httpStatus":401,"severity":"error","filePath":"litellm/llms/azure/common_utils.py","lineNumber":203,"sourceCode":"\n    Returns:\n        `azure_ad_token_access_token` - str\n    \"\"\"\n    if scope is None:\n        scope = \"https://cognitiveservices.azure.com/.default\"\n    azure_authority_host: Final = os.getenv(\"AZURE_AUTHORITY_HOST\", \"https://login.microsoftonline.com\")\n    azure_client_id = azure_client_id or os.getenv(\"AZURE_CLIENT_ID\")\n    azure_tenant_id = azure_tenant_id or os.getenv(\"AZURE_TENANT_ID\")\n    if azure_client_id is None or azure_tenant_id is None:\n        raise AzureOpenAIError(\n            status_code=422,\n            message=\"AZURE_CLIENT_ID and AZURE_TENANT_ID must be set\",\n        )\n\n    oidc_token: Final = get_secret_str(azure_ad_token)\n\n    if oidc_token is None:\n        raise AzureOpenAIError(\n            status_code=401,\n            message=\"OIDC token could not be retrieved from secret manager.\",\n        )\n\n    azure_ad_token_cache_key: Final = json.dumps(\n        {\n            \"azure_client_id\": azure_client_id,\n            \"azure_tenant_id\": azure_tenant_id,\n            \"azure_authority_host\": azure_authority_host,\n            \"oidc_token\": oidc_token,\n        }\n    )\n\n    azure_ad_token_access_token = azure_ad_cache.get_cache(azure_ad_token_cache_key)\n    if azure_ad_token_access_token is not None:\n        return azure_ad_token_access_token\n\n    client: Final = litellm.module_level_client","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure/common_utils.py#L185-L221","documentation":"After client/tenant IDs are resolved, LiteLLM reads the OIDC token via get_secret_str(azure_ad_token). If the value is None — because no azure_ad_token was supplied, or the secret manager lookup returned nothing — it raises AzureOpenAIError 401. This is a guard that the workload-identity assertion JWT must be present before calling the Azure AD token endpoint.","triggerScenarios":"AZURE_CLIENT_ID and AZURE_TENANT_ID are set but azure_ad_token is None/empty, or the value passed is a secret-manager key (e.g. 'azure/oidc/token') that the configured secret manager cannot resolve. Also triggered by passing an empty string, which get_secret_str normalizes to None.","commonSituations":"Federated credentials setup where the app fetches the OIDC token lazily but LiteLLM is called before it is available; secret deleted/rotated in AWS/GCP secret manager while the key reference stayed in config; passing the literal token in one environment but only the key name in another.","solutions":["Pass a real, non-empty OIDC/JWT string as azure_ad_token when calling LiteLLM.","If using secret-manager references, verify the secret exists and the manager is configured: check get_secret() resolves it (e.g. os.environ for env-based secrets, or your secret backend).","In containers/pods, confirm the workload-identity token file (e.g. AZURE_FEDERATED_TOKEN_FILE) is mounted and your code reads it into azure_ad_token before calling LiteLLM.","If you meant to use key auth, drop azure_ad_token and pass api_key instead."],"exampleFix":"# before\nresp = litellm.completion(model=\"azure/<dep>\", messages=msgs, azure_ad_token=\"\")  # empty -> None\n\n# after\noidc = requests.get(\n    \"http://169.254.169.254/metadata/identity/oauth2/token\",\n    params={\"api-version\": \"2019-08-01\", \"resource\": \"https://cognitiveservices.azure.com\"},\n    headers={\"Metadata\": \"true\"},\n).json()[\"access_token\"]\nresp = litellm.completion(model=\"azure/<dep>\", messages=msgs, azure_ad_token=oidc)","handlingStrategy":"validation","validationCode":"import os\n\ndef resolve_oidc_token(token_or_key: str | None) -> str:\n    # resolve like LiteLLM: treat a non-JWT value as an env/secret key\n    value = os.getenv(token_or_key) if token_or_key and not token_or_key.startswith(\"ey\") else token_or_key\n    if not value:\n        raise AuthError(\"OIDC token missing: fetch it from the workload identity endpoint first\")\n    return value","typeGuard":"def is_valid_oidc_token(t: object) -> bool:\n    return isinstance(t, str) and t.count(\".\") == 2 and len(t) > 100","tryCatchPattern":"try:\n    resp = litellm.completion(..., azure_ad_token=oidc)\nexcept AzureOpenAIError as e:\n    if e.status_code == 401 and \"OIDC token\" in str(e):\n        oidc = fetch_fresh_oidc()  # metadata endpoint\n        resp = litellm.completion(..., azure_ad_token=oidc)\n    else:\n        raise","preventionTips":["Fetch the OIDC token immediately before each call chain; never cache longer than its TTL.","If using secret-manager references, test resolution in CI with the same backend.","Treat empty-string tokens as missing in your own layer (get_secret_str does)."],"tags":["azure","authentication","oidc","secrets","managed-identity"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}