Bug
FastMCP 3.2.1 changed the audience parameter in AzureProvider's JWTVerifier from client_id to self.identifier_uri. This breaks upstream token validation for Azure apps with accessTokenAcceptedVersion: 2 in their app manifest.
Root Cause
In fastmcp/server/auth/providers/azure.py, the JWTVerifier is initialized with:
# 3.2.0 (works)
audience=client_id, # e.g. "db89b6dd-adf7-4183-b315-6b11aa19e14e"
# 3.2.1 (broken)
audience=self.identifier_uri, # e.g. "api://db89b6dd-adf7-4183-b315-6b11aa19e14e"
Azure AD v2 tokens set the aud claim to the Application (client) ID (a bare GUID), not the Application ID URI. So the JWTVerifier rejects every upstream token with an audience mismatch.
The same issue applies to AzureJWTVerifier, which changed from audience=client_id to audience=self._identifier_uri.
Evidence
Debug output from a production deployment:
token_aud=db89b6dd-adf7-4183-b315-6b11aa19e14e
expected=api://db89b6dd-adf7-4183-b315-6b11aa19e14e
The Azure app registration has accessTokenAcceptedVersion: 2 and the default identifier URI api://{client_id}.
Suggested Fix
Accept both formats:
token_verifier = JWTVerifier(
...
audience=[client_id, self.identifier_uri],
...
)
JWTVerifier already supports list audiences, so this is a one-line fix. This handles both accessTokenAcceptedVersion: 1 (where aud = identifier URI) and accessTokenAcceptedVersion: 2 (where aud = client ID).
Workaround
After creating the AzureProvider, patch the audience:
auth_provider = AzureProvider(...)
auth_provider._token_validator.audience = [client_id, f"api://{client_id}"]
Versions
- Works: FastMCP 3.2.0 and earlier
- Broken: FastMCP 3.2.1
Bug
FastMCP 3.2.1 changed the
audienceparameter inAzureProvider'sJWTVerifierfromclient_idtoself.identifier_uri. This breaks upstream token validation for Azure apps withaccessTokenAcceptedVersion: 2in their app manifest.Root Cause
In
fastmcp/server/auth/providers/azure.py, theJWTVerifieris initialized with:Azure AD v2 tokens set the
audclaim to the Application (client) ID (a bare GUID), not the Application ID URI. So the JWTVerifier rejects every upstream token with an audience mismatch.The same issue applies to
AzureJWTVerifier, which changed fromaudience=client_idtoaudience=self._identifier_uri.Evidence
Debug output from a production deployment:
The Azure app registration has
accessTokenAcceptedVersion: 2and the default identifier URIapi://{client_id}.Suggested Fix
Accept both formats:
JWTVerifieralready supports list audiences, so this is a one-line fix. This handles bothaccessTokenAcceptedVersion: 1(whereaud= identifier URI) andaccessTokenAcceptedVersion: 2(whereaud= client ID).Workaround
After creating the
AzureProvider, patch the audience:Versions