AADSTS50027 on a federated client assertion whose signature verifies against the published JWKS

Ludovic V 0 Reputation points
2026-10-13T16:23:46.78+00:00

We exchange a short-lived RS256 JWT for an access token with client_credentials and a federated identity credential. Microsoft Entra returns AADSTS50027 (JWT token is invalid or malformed). The same assertion verifies with the key in the issuer JWKS, and iss, sub, and aud match the federated credential exactly.

The token request is:

POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
client_id={application-id}
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion={compact JWT, sent unchanged}
scope=https://management.azure.com/.default openid offline_access profile
client_info=1

There is no resource parameter. The SDK is azidentity v1.14.1 ClientAssertionCredential, which calls MSAL Go v1.8.0. The callback returns the minted compact JWT. MSAL places that string in client_assertion.

One failing assertion decoded as:

  • alg: RS256
  • typ: JWT
  • kid: signing-key-1
  • iss: https://issuer.example.com/organization-subject
  • sub: organization-subject
  • aud: api://AzureADTokenExchange (a string, not an array)
  • iat: 1791476489 (the same second as the mint)
  • nbf: 1791476429 (iat minus 60 seconds)
  • exp: 1791476789 (iat plus 300 seconds)
  • jti: one UUID

No other claims are present. There is no nonce. Each claim appears once. The three segment lengths are 62, 324, and 342. The signature length is a full 2048-bit RS256 signature. The issuer verified that signature with the RSA key it publishes for kid signing-key-1.

The federated credential on the application is the only credential, and it is a standard credential, not a flexible one:

  • Issuer: https://issuer.example.com/organization-subject
  • Subject: organization-subject
  • Audience: api://AzureADTokenExchange

Discovery at {issuer}/.well-known/openid-configuration returns HTTP 200. issuer and jwks_uri match that URL. The JWKS contains one RSA key: kty RSA, use sig, alg RS256, kid signing-key-1, e AQAB. The same document is served by both origins and by the CloudFront distribution in front of the issuer. The signing key has not changed.

The same failure happens for a second issuer, https://issuer-us.example.com/organization-subject, with the same token shape.

AADSTS50027 is returned by login.microsoftonline.com, so this tenant is served by the public authority. The request is far enough along for Entra to judge the assertion. Each error body includes a correlation ID and a trace ID. Those identifiers are not visible in any log in the Microsoft Entra admin center or in the Azure portal, including Service principal sign-ins after an Entra ID P2 trial and a Microsoft Graph query of auditLogs/signIns for this application. Other service principals do appear in that report.

What we need is the check Entra applies to this client assertion after the request reaches the token endpoint, and why that check returns AADSTS50027 when the published key verifies the signature and the federated credential matches iss, sub, and aud.

Checks already done
  • Public-cloud token host login.microsoftonline.com and the v2.0 token path are the ones ClientAssertionCredential uses for this tenant.
  • grant_type is client_credentials.
  • client_assertion_type is urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
  • The body is application/x-www-form-urlencoded. The JWT alphabet is not rewritten by form encoding.
  • client_id is the application (client) id, not the enterprise-application object id.
  • The assertion is a compact JWS of exactly three segments, base64url without padding, and it is posted unchanged.
  • Header is RS256 / JWT / kid signing-key-1. The signature segment is a full 2048-bit signature.
  • Claims are only iss, sub, aud, iat, nbf, exp, and jti. aud is a string. There is no nonce and no duplicate claim.
  • iss, sub, and aud match the single federated credential, with no trailing slash.
  • nbf is 60 seconds before iat on purpose. exp is 300 seconds after iat. The host clock and iat agree with UTC.
  • Discovery and JWKS return HTTP 200. jwks_uri is {issuer}/jwks. The key is RSA, use sig, alg RS256, kid signing-key-1.
  • This process verifies the signature with that published key.
  • The same mint function is used for AWS and GCP. Only the audience string differs. Azure's audience is api://AzureADTokenExchange.
  • This is not the certificate client-assertion shape (iss and sub equal to the client id, aud equal to the token endpoint, x5t in the header).
  • x5c is absent. Workload identity federation accepts a JWKS key that has only n and e. The x5c requirement belongs to External MFA method providers.
  • A missing Reader role would fail after a token is issued. This failure is the token exchange itself.
  • An issuer or subject mismatch would be AADSTS70021 or AADSTS700213, and Entra would quote the presented values. The error is AADSTS50027.
  • The correlation ID and trace ID in each Entra error are not visible in any log in the Microsoft Entra admin center or in the Azure portal, including after an Entra ID P2 trial and after new probes.
Microsoft Security | Microsoft Entra | Microsoft Entra ID
0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.