AADSTS50146 fix: custom claims need an app signing key
Short answer: AADSTS50146 means Microsoft Entra ID refused to issue a token because the app's claims were customized but the app hasn't accepted that: it has no app-specific signing key (or the key expired), and it doesn't set acceptMappedClaims. It usually starts right after someone adds a claim to an app. It is a configuration error and a deliberate safeguard. Low attack value.
Fix: Developer, single-tenant app: set `acceptMappedClaims` to `true` in the app manifest and use a verified-domain Application ID URI. Multitenant app: add a custom signing key to the service principal and validate tokens with `?appid=`. Expired key: renew it. User: contact the app owner. Full steps
| Code | AADSTS50146 |
|---|---|
| Microsoft name | MissingCustomSigningKey |
| Category | App configuration |
| Type | Configuration error |
| Attack signal | Low: usually configuration or user error |
| Microsoft lookup | login.microsoftonline.com/error?code=50146 |
What does AADSTS50146 mean?
Section titled “What does AADSTS50146 mean?”Microsoft’s description:
MissingCustomSigningKey: This app is required to be configured with an app-specific signing key. It’s either not configured with one, or the key has expired or isn’t yet valid. Please contact the owner of the application.
The trigger is claims customization: someone changed which claims Entra ID puts in the app’s tokens. Microsoft explains why that needs an extra step: “Applications that receive tokens rely on claim values that can’t be tampered with. When you modify the token contents through claims customization, these assumptions may no longer be correct. Applications must explicitly acknowledge that tokens have been modified.”
The app can acknowledge it in one of two ways:
- A custom signing key on the service principal. By default an app “is using the Azure global sign-in key, which can’t be used for customizing claims in tokens.”
acceptMappedClaimsset totruein the app manifest. This is for single-tenant apps only.
“Without this, Microsoft Entra ID returns an AADSTS50146 error code.” The description also covers a custom key that exists but has expired or isn’t valid yet.
Is it an attack?
Section titled “Is it an attack?”No. 50146 is the safeguard working. Microsoft’s warning on the alternative shows what it protects against: “Do not set the acceptMappedClaims property to true for multi-tenant apps, which can allow malicious actors to create claims-mapping policies for your app.”
Users report it after ordinary changes:
- In a Microsoft Q&A thread, a developer added the optional claim
onpremisessamaccountnameto a single-tenant app with a SPA and an API scope, and sign-in started failing with 50146. - Auth0’s knowledge base covers it on an Auth0 connection to Entra ID, where the token request fails with “failed to obtain access token”.
| Pattern | Likely meaning |
|---|---|
| One app, every user, starting right after a claim was added | Claims customization without a signing key or acceptMappedClaims. Configuration. |
| An app that worked for months starts failing for everyone | The custom signing key has expired. |
| A claims-mapping policy appears on an app nobody on your team changed | Not 50146 itself, but worth a look. Our interpretation: someone is changing what tokens for that app contain. |
How do I find it in my logs (KQL)?
Section titled “How do I find it in my logs (KQL)?”Microsoft doesn’t document which sign-in table 50146 lands in. Check your workspace:
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs| where TimeGenerated > ago(30d)| where ResultType == "50146"| summarize Rows = count(), Apps = dcount(AppId), FirstSeen = min(TimeGenerated) by SourceTableWhich apps fail and since when:
union SigninLogs, AADNonInteractiveUserSignInLogs| where TimeGenerated > ago(30d)| where ResultType == "50146"| summarize Rows = count(), Users = dcount(UserPrincipalName), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Resources = make_set(ResourceDisplayName, 5) by AppDisplayName, AppId| sort by Users descRecent policy and app changes, to find the change that started it. Microsoft lists Add policy to service principal, Add policy to application and Update application as audit activities. Our assumption: assigning a claims-mapping policy appears as one of the first two, and a manifest change as the third; Microsoft doesn’t map them explicitly.
AuditLogs| where TimeGenerated > ago(30d)| where Category == "ApplicationManagement"| where OperationName in ("Add policy to service principal", "Add policy to application", "Update application")| extend Target = tostring(TargetResources[0].displayName), ByUser = tostring(InitiatedBy.user.userPrincipalName)| project TimeGenerated, OperationName, Target, ByUser, Result| sort by TimeGenerated descResultType is a string column, so compare it with "50146".
How do I fix AADSTS50146?
Section titled “How do I fix AADSTS50146?”For the user: you can’t fix this. As Microsoft’s description says, contact the owner of the application.
For developers, single-tenant app:
- In the app manifest, set
acceptMappedClaimstotrue. Microsoft: “Setting the property allows an application to use claims mapping without specifying a custom signing key.” - Set the Application ID URI to a verified domain of your tenant, for example
https://contoso.com/my-api. If you don’t, you trade 50146 for AADSTS501461: “AcceptMappedClaims is only supported for a token audience matching the application GUID or an audience within the tenant’s verified domains.” The Q&A thread above hit exactly this with anapi://<appid>URI.
For developers, multitenant app:
- Don’t use
acceptMappedClaims. Microsoft: “For multitenant apps, a custom signing key should be used.” - Create a key from a certificate and add it to the service principal: the private key and public key as key credentials, and the password as a password credential, with matching
keyIdvalues. The private key must be in PKCS#12 format. - Validate tokens against the app’s own keys. Apps with claims mapping “must validate their token signing keys by appending
appid={client_id}to their OpenID Connect metadata requests”:https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?appid={client-id}.
For admins:
- Check the app’s recent changes (third query). If a claim was added, the developer needs one of the two fixes above.
- If the app already has a custom signing key, check whether it has expired. The description names an expired or not-yet-valid key as a cause. Replace it with a new certificate.
- Some settings only work with a custom key. Microsoft says the Issuer With Application ID and Audience Override settings are “ignored if a custom signing key isn’t configured for the application.”
Sources
- Microsoft Entra authentication and authorization error codes
- Customize claims issued in the JSON web token (JWT) for enterprise applications
- Claims customization using a policy
- Microsoft Entra audit log categories and activities
- After adding a new claim to an app I am getting AADSTS50146 (Microsoft Q&A, user report)
- Failed to obtain access token and error AADSTS50146 (Auth0 KB, user report)