5 min readBy Muhammad Shahid
IDX10501 Unable to Match Key (kid) in ASP.NET Core JWT
IDX10501: Signature validation failed. Unable to match key — the token kid is not in JWKS or TokenValidationParameters. Not IDX10503, not a metadata download failure.
Part of Auth & Tokens
Quick answers
- What is IDX10501 in ASP.NET Core JWT?
- IDX10501 means IdentityModel found a kid on the token and none of the keys it loaded share that id. The signature algorithm is not the first question — the key set is.
- Is IDX10501 the same as IDX10503?
- No. IDX10503 is “I tried these keys and the signature still failed” (wrong secret, no kid, disposed RSA). IDX10501 is “I cannot even pick a key because the kid is missing from JWKS.”
- Should I add a kid header to fix IDX10501?
- Only if the issuer actually signs with a key that publishes that kid. Inventing a kid on the API side does nothing. Fix the signing credential overlap or the Authority that downloads JWKS.
IDX10501: Signature validation failed. Unable to match key: kid: '[PII is hidden]'. IdentityModel already parsed a JWT. It read the header kid. It loaded keys from TokenValidationParameters and/or OpenID JWKS. None of those keys have that id. Developers paste the line and land on signature tutorials. This URL is the kid match, not the HMAC secret.
Signature failures where keys were tried stay in IDX10503. Issuance, lifetimes, and policies stay in the JWT checklist. Cookie Data Protection is No XML encryptor found. I will not retell those.
I hit IDX10501 on a marketplace search API the morning after we rotated the OpenIddict signing certificate on the identity host. Auction accepted the new tokens. Search still served 401s. jwt.io said the token was fine. Search’s ConfigurationManager still had yesterday’s JWKS.
Read the kid before you rotate anything else
Typical Development log once PII is on:
IDX10501: Signature validation failed. Unable to match key:
kid: 'A1B2C3D4'.
Number of keys in TokenValidationParameters: '0'.
Number of keys in Configuration: '1'.
Three facts:
- The token has a
kid— otherwise you usually see IDX10503 with “Token does not have a kid” - Configuration keys came from metadata (
Authority/MetadataAddress→ JWKS) - That JWKS id is not
A1B2C3D4
Turn on PII only in Development: IdentityModelEventSource.ShowPII = true. Decode the access token header (not the refresh token) and compare kid to https://{authority}/.well-known/openid-configuration → jwks_uri.
Cause 1: Signing credential rotated, validation keys did not overlap
Duende / OpenIddict: you replaced AddSigningCredential(newCert) and recycled the identity host. New tokens carry the new thumbprint. APIs that already downloaded JWKS keep the old set until ConfigurationManager refreshes. Angular still holds a token from five minutes ago or a brand-new token the cached JWKS cannot name.
Fix I actually ship:
- Publish both certificates during overlap: current signing credential plus
AddValidationKeys(or OpenIddict’s validation key collection) for the previous cert - Keep the old cert valid until access-token lifetime has passed (if access is 15 minutes, overlap at least that plus clock skew)
- Recycle resource APIs after the identity host, or wait for automatic refresh — do not assume every App Service instance fetched JWKS at the same second
This is not Data Protection key-ring XML. Signing certs for JWT are a different pile of keys than antiforgery cookies.
Cause 2: Two identity hosts, one Angular memory
Staging IdentityServer on login-test.example.com, production API Authority still https://login.example.com. A developer signed in against test, then pointed the SPA at production APIs (or the reverse). The production JWKS never heard of the test kid.
Same shape: auction and search behind two OpenIddict containers that each generated a dev certificate on first boot because the shared cert volume was empty on one replica.
Fix: one issuer URL per environment, one signing material per issuer, tokens never cross. Authority on every AddJwtBearer must be the host that issued that access token.
Cause 3: Azure AD / Entra tenant or app registration mismatch
Authority = "https://login.microsoftonline.com/{wrong-tenant}/v2.0" downloads a JWKS that will never contain the kid from tokens issued by the tenant the SPA actually uses. The error looks like “JWT is broken.” The tenant GUID is wrong.
Fix: copy tenant id and aud from a real token payload, not from a wiki page that still has the old directory. Audience mismatches are IDX10214 — if you already confirmed aud and still see IDX10501, the JWKS tenant is the remaining suspect.
Cause 4: Metadata never loads, then a later request looks like IDX10501
If the API cannot download discovery, the first exception is usually IDX20803 / IDX20807 (“Unable to obtain configuration” / “Unable to retrieve document”). Docker DNS, HTTP instead of HTTPS, a 404 on / .well-known/openid-configuration, or App Service cannot reach the identity host.
I have seen a follow-up IDX10501 when someone “fixed” metadata by stuffing a single RSA key into IssuerSigningKeys that was not the key in the token. That is still a kid mismatch. Restore discovery, or load the JWKS document you actually serve.
Do not copy IssuerSigningKey from a symmetric Jwt:Key appsetting onto an API that is supposed to validate OpenIddict RS256 tokens. That path is how teams turn a metadata problem into a kid problem.
What IDX10501 is not
| Log | Look here instead |
|---|---|
| IDX10503, “Token does not have a kid”, wrong HMAC secret, disposed RSA | IDX10503 |
| IDX20803 / IDX20807, cannot GET discovery or JWKS | Network, Authority URL, TLS, Docker DNS — then this page if a kid still will not match |
| IDX10214 / IDX10204 | aud / iss, not JWKS |
| No XML encryptor found | Data Protection key ring |
| 403 after a valid JWT | 401 vs 403 |
Checklist I run in ten minutes
- Decode the access token header — copy
kidandalg - Open the issuer’s JWKS (from discovery
jwks_uri). Is thatkidlisted? - If no: the issuer is not publishing the key it signed with — overlap certs, fix the replica’s empty cert volume, or wait out stale
ConfigurationManager(recycle the API) - If yes on JWKS but IDX10501 on one API only: that API’s
Authorityis a different host or an old instance with a cached document - Enable PII in Development, reproduce once, turn it off
- Leave HS256
Jwt:Keytutorials ifalgisRS256/PS256
Leaving IdentityServer4? Signing keys on the new host are the OpenIddict migration checklist — after cutover, leftover IS4 tokens against OpenIddict JWKS are this error, not an audience essay.
Related reading
If only one API in a farm 401s after a cert rotation and jwt.io looks clean, send the kid and both JWKS documents — not a screenshot of the Angular network tab.