{"record":{"id":"24af8f15a7c7d84a","repo":"BerriAI/litellm","slug":"oidc-userinfo-endpoint-returned-status-response-s","errorCode":null,"errorMessage":"OIDC UserInfo endpoint returned status {response.status_code}: {response.text}","messagePattern":"OIDC UserInfo endpoint returned status (.+?): (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/proxy/auth/handle_jwt.py","lineNumber":767,"sourceCode":"\n        if cached_userinfo is not None:\n            verbose_proxy_logger.debug(\"Returning cached OIDC UserInfo\")\n            return cached_userinfo\n\n        verbose_proxy_logger.debug(\"Calling OIDC UserInfo endpoint: %s\", self.litellm_jwtauth.oidc_userinfo_endpoint)\n\n        try:\n            # Call the UserInfo endpoint with the access token\n            response: Final = await self.http_handler.get(\n                url=self.litellm_jwtauth.oidc_userinfo_endpoint,\n                headers={\n                    \"Authorization\": f\"Bearer {token}\",\n                    \"Accept\": \"application/json\",\n                },\n            )\n\n            if response.status_code != 200:\n                raise Exception(f\"OIDC UserInfo endpoint returned status {response.status_code}: {response.text}\")\n\n            userinfo: Final = response.json()\n            verbose_proxy_logger.debug(\"Received OIDC UserInfo: %s\", userinfo)\n\n            # Cache the userinfo response\n            await self.user_api_key_cache.async_set_cache(\n                key=cache_key,\n                value=userinfo,\n                ttl=self.litellm_jwtauth.oidc_userinfo_cache_ttl,\n            )\n\n            return userinfo\n\n        except Exception as e:\n            verbose_proxy_logger.error(\"Error fetching OIDC UserInfo: %s\", e)\n            raise Exception(f\"Failed to fetch OIDC UserInfo: {e}\")\n\n    _unscoped_jwt_warning_emitted = False","sourceCodeStart":749,"sourceCodeEnd":785,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/auth/handle_jwt.py#L749-L785","documentation":"Raised in get_userinfo when the OIDC UserInfo endpoint answers with a non-200 status. The response body is included in the message, so the IdP's own error text (e.g. 'invalid token', 'insufficient scope') is visible. Successful responses are cached per-token-hash for oidc_userinfo_cache_ttl, so this only fires on cache misses.","triggerScenarios":"The proxy calls GET <oidc_userinfo_endpoint> with Authorization: Bearer <access token> and the IdP returns 401 (token expired/revoked or lacking the openid scope), 403 (forbidden), or 5xx - most commonly an expired access token that still passed local JWT verification, or a token without the openid scope.","commonSituations":"See trigger scenarios.","solutions":["Reproduce manually: curl -H 'Authorization: Bearer <token>' <userinfo_endpoint> and read the IdP's error body included in the message","If the token is expired or revoked, obtain a fresh access token and retry","Ensure the requested scopes include openid when the token is minted","Confirm oidc_userinfo_endpoint matches the realm/tenant that issued the token"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import time, jwt as pyjwt\n\ndef token_is_fresh(token: str, skew_seconds: int = 30) -> bool:\n    payload = pyjwt.decode(token, options={\"verify_signature\": False})\n    exp = payload.get(\"exp\")\n    return exp is None or exp - skew_seconds > time.time()","typeGuard":null,"tryCatchPattern":"# the IdP's error body is embedded in the message - surface it\nt\ntry:\n    await proxy_call_with_jwt(token)\nexcept Exception as e:\n    if \"OIDC UserInfo endpoint returned status 401\" in str(e):\n        token = await refresh_access_token()  # expired/revoked at the IdP\n    else:\n        raise","preventionTips":["Request the openid scope when minting tokens used for UserInfo","Refresh access tokens before their exp - UserInfo checks happen at the IdP, not just locally","Match oidc_userinfo_endpoint to the exact realm/tenant that issued the token"],"tags":["oidc","userinfo","http-status","authentication","token-expired"],"backgroundTag":"oidc-userinfo-endpoint-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}