{"record":{"id":"94928a27a74315ed","repo":"crewAIInc/crewAI","slug":"invalid-token-issuer","errorCode":null,"errorMessage":"Invalid token issuer","messagePattern":"Invalid token issuer","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"lib/crewai/src/crewai/a2a/auth/server_schemes.py","lineNumber":324,"sourceCode":"            raise HTTPException(\n                status_code=HTTP_401_UNAUTHORIZED,\n                detail=\"Token has expired\",\n            ) from None\n        except jwt.InvalidAudienceError:\n            logger.debug(\n                \"OIDC authentication failed\",\n                extra={\"reason\": \"invalid_audience\", \"scheme\": \"oidc\"},\n            )\n            raise HTTPException(\n                status_code=HTTP_401_UNAUTHORIZED,\n                detail=\"Invalid token audience\",\n            ) from None\n        except jwt.InvalidIssuerError:\n            logger.debug(\n                \"OIDC authentication failed\",\n                extra={\"reason\": \"invalid_issuer\", \"scheme\": \"oidc\"},\n            )\n            raise HTTPException(\n                status_code=HTTP_401_UNAUTHORIZED,\n                detail=\"Invalid token issuer\",\n            ) from None\n        except jwt.MissingRequiredClaimError as e:\n            logger.debug(\n                \"OIDC authentication failed\",\n                extra={\"reason\": \"missing_claim\", \"claim\": e.claim, \"scheme\": \"oidc\"},\n            )\n            raise HTTPException(\n                status_code=HTTP_401_UNAUTHORIZED,\n                detail=f\"Missing required claim: {e.claim}\",\n            ) from None\n        except jwt.PyJWKClientError as e:\n            logger.error(\n                \"OIDC authentication failed\",\n                extra={\n                    \"reason\": \"jwks_client_error\",\n                    \"error\": str(e),","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai/src/crewai/a2a/auth/server_schemes.py#L306-L342","documentation":"Raised by OIDCAuth.authenticate() when jwt.decode() throws InvalidIssuerError: the JWT's `iss` claim does not equal the scheme's configured issuer URL. This guards against tokens signed by a trusted key but minted by a different authority (e.g. a sibling tenant). It maps to HTTP 401 and logs reason='invalid_issuer'.","triggerScenarios":"Scheme configured with issuer='https://idp.example.com' while the token's iss is 'https://tenant.idp.example.com/' (or differs only by trailing slash); multi-tenant IdPs where each tenant has a distinct issuer; mixing issuer URLs between prod and staging tenants.","commonSituations":"Trailing-slash mismatch between the configured issuer and the actual iss claim; Azure AD where the issuer includes a {tenantid} GUID; environment promotion carrying a staging issuer into a prod config.","solutions":["Decode the token and read its iss claim verbatim, then set the scheme's issuer to exactly that string (including scheme, host, path, trailing slash).","For Azure AD, use the tenant-specific issuer (https://login.microsoftonline.com/<tenant-id>/v2.0) matching the token.","Treat issuer/audience/jwks_url as one unit per environment and validate them together at startup.","Never disable issuer validation to 'make it work'; fix the configured value instead."],"exampleFix":"# before\nauth = OIDCAuth(jwks_url=jwks, issuer=\"https://idp.example.com\", ...)  # token has \"https://idp.example.com/\"\n\n# after\nauth = OIDCAuth(jwks_url=jwks, issuer=\"https://idp.example.com/\", ...)  # exact match with `iss` claim","handlingStrategy":"validation","validationCode":"import jwt\n\nclaims = jwt.decode(access_token, options={\"verify_signature\": False})\nassert claims.get(\"iss\") == configured_issuer, (\n    f\"iss mismatch: token={claims.get('iss')!r} scheme={configured_issuer!r}\"\n)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy the issuer from a real token's iss claim, not from IdP marketing URLs.","Watch for trailing-slash mismatches.","For Azure AD, use the tenant-specific v2.0 issuer URL."],"tags":["a2a","oidc","jwt","issuer","http-401"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}