-
Notifications
You must be signed in to change notification settings - Fork 157
Description
Copilot Usage Confirmation
- I have tried using GitHub Copilot to resolve this issue.
MSAL Version
2.8.1
Description
When using MSALCIAMAuthority with federated identity providers (e.g. users from another Microsoft Entra tenant signing in via external IdP), silent token acquisition fails after the first interactive sign-in. The library sends the refresh token to the wrong authority URL, causing AADSTS500210 (domain/tenant mismatch).
In the logs, MSAL shows:
Request authority cache look up for https://< TENANT>.ciamlogin.com/<CIAM_TENANT_ID>, using https://< TENANT>.ciamlogin.com/<IDP_TENANT_ID> instead."
Root cause: MSAL/MSID uses the wrong authority for the refresh request. The tokens show that the id_token’s tid is correct (CIAM tenant <CIAM_TENANT_ID>), but the idp claim points to the federated IdP (sts.windows.net/<IDP_TENANT_ID>). The cached authority/realm appears to be derived from the IdP (<IDP_TENANT_ID>) instead of the request authority or token tid, causing the refresh to be sent to the wrong endpoint.
Error Details
- Error code: AADSTS500210
- Error message: Domain name does not match with the tenant identifier. Trace ID: <TRACE_ID> Correlation ID: <CORRELATION_ID> Timestamp: …
The refresh token is issued by CIAM and must be sent to the CIAM token endpoint. The library sends it to an authority that uses the IdP tenant (<IDP_TENANT_ID>) instead of the CIAM tenant (<CIAM_TENANT_ID>), which the server rejects.
MSAL Logs
Federated (failing) – key log lines:
(Default cache) Saving token ... for userID ... with environment <TENANT>.ciamlogin.com, realm <IDP_TENANT_ID>, clientID <CLIENT_ID>
Request authority cache look up for https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID>, using https://<TENANT>.ciamlogin.com/<IDP_TENANT_ID> instead
(Default accessor) Finding token with ... authority https://<TENANT>.ciamlogin.com/<IDP_TENANT_ID>
Trying to acquire access token using App Refresh Token for clientId https://<TENANT>.ciamlogin.com/<IDP_TENANT_ID> ...
Creating Error with description: AADSTS500210: Domain name does not match with the tenant identifier Trace ID: <TRACE_ID> Correlation ID: <CORRELATION_ID> Timestamp: 2026-02-12 08:31:22Z
Silent flow finished. Result (null), error: -51115 error domain: MSIDErrorDomain
CIAM native (working) – key log lines:
(Default cache) Saving token ... for userID ... with environment <TENANT>.ciamlogin.com, realm <CIAM_TENANT_ID>, clientID <CLIENT_ID>
Request authority cache look up for https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID>, using https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID> instead
(Default accessor) Finding token with ... authority https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID>
Trying to acquire access token using App Refresh Token for clientId https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID> ...
Silent flow finished. Result (not-null), error: 0 error domain: (null)
Log comparison – federated (failing) vs CIAM native (working):
| Step | Federated (failing) | CIAM native (working) |
|---|---|---|
| Interactive – saving tokens | realm <IDP_TENANT_ID> |
realm <CIAM_TENANT_ID> |
| Request authority cache look up | using .../<IDP_TENANT_ID> instead |
using .../<CIAM_TENANT_ID> instead (no swap) |
| Refresh token request | Finding token ... authority https://.../<IDP_TENANT_ID> |
Finding token ... authority https://.../<CIAM_TENANT_ID> |
| Trying to acquire using App Refresh Token | https://.../<IDP_TENANT_ID> → AADSTS500210 |
https://.../<CIAM_TENANT_ID> → success |
Credential cache entries show realm set to the federated IdP tenant (<IDP_TENANT_ID>) instead of the CIAM tenant (<CIAM_TENANT_ID>), even though the id_token’s tid claim is correct (see tokens below).
Note: Even when the app explicitly passes authority on MSALSilentTokenParameters (CIAM tenant), MSAL internally overrides it and uses the account's realm (IdP tenant for federated) for the refresh request.
ID Token Federated (failing case)
{
"typ": "JWT",
"alg": "RS256",
"kid": "[REDACTED]"
}.{
"aud": "<CLIENT_ID>",
"iss": "https://<CIAM_TENANT_ID>.ciamlogin.com/<CIAM_TENANT_ID>/v2.0",
"iat": 1770884710,
"nbf": 1770884710,
"exp": 1770888610,
"idp": "https://sts.windows.net/<IDP_TENANT_ID>/",
"name": "[REDACTED]",
"oid": "<OID_FEDERATED>",
"preferred_username": "<REDACTED>",
"rh": "[REDACTED]",
"sid": "[REDACTED]",
"sub": "[REDACTED]",
"tid": "<CIAM_TENANT_ID>",
"uti": "[REDACTED]",
"ver": "2.0"
}.[Signature]
Note: The id_token has tid: <CIAM_TENANT_ID> (CIAM tenant, correct) and idp: https://sts.windows.net/<IDP_TENANT_ID>/ (IdP). Despite correct tid, silent refresh fails with AADSTS500210, suggesting the wrong authority comes from somewhere other than tid (e.g. idp or account metadata).
Access Token Federated
{
"typ": "JWT",
"alg": "RS256",
"kid": "[REDACTED]"
}.{
"aud": "<CLIENT_ID>",
"iss": "https://<CIAM_TENANT_ID>.ciamlogin.com/<CIAM_TENANT_ID>/v2.0",
"iat": 1770884710,
"nbf": 1770884710,
"exp": 1770889829,
"aio": "[REDACTED]",
"azp": "<CLIENT_ID>",
"azpacr": "0",
"idp": "https://sts.windows.net/<IDP_TENANT_ID>/",
"name": "[REDACTED]",
"oid": "<OID_FEDERATED>",
"preferred_username": "<REDACTED>",
"rh": "[REDACTED]",
"scp": "User.Read",
"sid": "[REDACTED]",
"sub": "[REDACTED]",
"tid": "<CIAM_TENANT_ID>",
"uti": "[REDACTED]",
"ver": "2.0",
"xms_ftd": "[REDACTED]"
}.[Signature]
ID Token CIAM
{
"typ": "JWT",
"alg": "RS256",
"kid": "[REDACTED]"
}.{
"aud": "<CLIENT_ID>",
"iss": "https://<CIAM_TENANT_ID>.ciamlogin.com/<CIAM_TENANT_ID>/v2.0",
"iat": 1770884900,
"nbf": 1770884900,
"exp": 1770888800,
"name": "[REDACTED]",
"oid": "<OID_CIAM>",
"preferred_username": "<REDACTED>",
"rh": "[REDACTED]",
"sid": "[REDACTED]",
"sub": "[REDACTED]",
"tid": "<CIAM_TENANT_ID>",
"uti": "[REDACTED]",
"ver": "2.0"
}.[Signature]
Access Token CIAM
{
"typ": "JWT",
"alg": "RS256",
"kid": "[REDACTED]"
}.{
"aud": "<CLIENT_ID>",
"iss": "https://<CIAM_TENANT_ID>.ciamlogin.com/<CIAM_TENANT_ID>/v2.0",
"iat": 1770884900,
"nbf": 1770884900,
"exp": 1770890052,
"aio": "[REDACTED]",
"azp": "<CLIENT_ID>",
"azpacr": "0",
"name": "[REDACTED]",
"oid": "<OID_CIAM>",
"preferred_username": "<REDACTED>",
"rh": "[REDACTED]",
"scp": "User.Read",
"sid": "[REDACTED]",
"sub": "[REDACTED]",
"tid": "<CIAM_TENANT_ID>",
"uti": "[REDACTED]",
"ver": "2.0",
"xms_ftd": "[REDACTED]"
}.[Signature]
Reproduction Steps
- Configure a CIAM app with MSALCIAMAuthority (e.g.
https://<TENANT>.ciamlogin.com/<CIAM_TENANT_ID>). - Add an external identity provider (e.g. another Microsoft Entra tenant).
- Sign in interactively with a user from that federated IdP.
- Confirm both access token and refresh token are received.
- Wait for the access token to expire or trigger a silent refresh.
- Call
acquireTokenSilent(or rely on automatic refresh).
Result: Silent refresh fails with AADSTS500210.
Expected Behavior
Silent token refresh should succeed for federated users. The refresh token is issued by CIAM, so the refresh request should always go to the request authority (CIAM tenant <CIAM_TENANT_ID>), not an authority derived from the idp claim (IdP tenant <IDP_TENANT_ID>).
Regression
No response
Screenshots & Screen Recordings
No response
Additional context
Technical details:
- The id_token for federated users has
tid: <CIAM_TENANT_ID>(CIAM tenant, correct) andidp: https://sts.windows.net/<IDP_TENANT_ID>/(federated IdP). - Despite correct
tid, the refresh request is sent to an authority using tenant<IDP_TENANT_ID>(IdP tenant), causing AADSTS500210. - Root cause: The account identifier is
{uid}.{utid}fromclient_infoin the token response. MSIDClientInfo parsesuidandutidfrom the base64-decodedclient_infoJSON. MSIDCIAMOauth2FactoryresultAuthorityWithConfiguration:tokenResponse:(IdentityCore) builds the cache authority usingresponse.clientInfo.utidasrawTenant– for CIAM the library never usesid_token.tidfor the authority. For federated users, the server returnsutid= IdP tenant (<IDP_TENANT_ID>), so the cache authority and realm are wrong. MSALCIAMOauth2ProviderissuerAuthorityWithAccountreturns this cached authority viagetAuthorityURL:homeAccountId:.... - CIAM native vs federated: For CIAM-native users (no
idpclaim),client_inforeturnsutid= CIAM tenant (<CIAM_TENANT_ID>), so silent refresh works. For federated users,utid= IdP tenant (<IDP_TENANT_ID>), so silent refresh fails. - Contrast with AAD: MSIDAADOauth2Factory uses
response.idTokenObj.realm(maps totid) for the authority; CIAM usesclient_info.utidinstead. - The refresh token is issued by CIAM and must be sent to the CIAM token endpoint.
Suggested fix:
For CIAM flows, always use the request authority (or the issuer from the token response) for caching and refresh. Do not derive the refresh authority from the idp claim or the account’s home tenant when it would point to a different authority than the one that issued the token. When tid in the id_token ≠ utid in client_info (federated case), use the request authority or id_token.tid for caching and refresh instead of client_info.utid.