IdentityServer / IdentityServer3

OpenID Connect Provider and OAuth 2.0 Authorization Server Framework for ASP.NET 4.x/Katana
https://identityserver.github.io/Documentation/
Apache License 2.0
2.01k stars 764 forks source link

Token Validation - failing to match 'kid' #3040

Closed stewart-noll-q2 closed 8 years ago

stewart-noll-q2 commented 8 years ago

Successfully creating a JWT token using a cert from my local machine but when it comes time to validate the token via middleware on our my local IdentityService instance I'm getting the following exception... IDX10501: Signature validation failed. Unable to match 'kid': 'cBS9UBUP5ATqBHfEBK9p1LwuJtM' At a bit of a standstill since it's not quite obvious where I went wrong. Any direction or thoughts on next steps would be greatly appreciated. Here's my log output

2016-07-05 10:20:54 [Information] Start token request 2016-07-05 10:20:54 [Debug] Start client validation 2016-07-05 10:20:54 [Debug] Start parsing for X.509 certificate 2016-07-05 10:20:54 [Debug] client_id is not found in post body 2016-07-05 10:20:54 [Debug] Start parsing for secret in post body 2016-07-05 10:20:54 [Debug] No secet in post body found 2016-07-05 10:20:54 [Debug] Start parsing Basic Authentication secret 2016-07-05 10:20:54 [Debug] Parser found client secret: "BasicAuthenticationSecretParser" 2016-07-05 10:20:54 [Information] Client secret id found: "applicant-sso" 2016-07-05 10:20:54 [Debug] Secret validator success: "HashedSharedSecretValidator" 2016-07-05 10:20:54 [Information] Client validation success 2016-07-05 10:20:54 [Information] Start token request validation 2016-07-05 10:20:54 [Information] Start password token request validation 2016-07-05 10:20:54 [Information] Password token request validation success. 2016-07-05 10:20:54 [Information] "Token request validation success" "{ \"ClientId\": \"applicant-sso\", \"ClientName\": \"applicant-sso\", \"GrantType\": \"password\", \"Scopes\": \"applicant\", \"UserName\": \"630_sso4@test.com\", \"AuthenticationContextReferenceClasses\": [], \"Tenant\": \"2fc4a1ca-022c-4fa3-ab6f-a63500a1ede7\", \"Raw\": { \"grant_type\": \"password\", \"username\": \"630_sso4@test.com\", \"password\": \"1Password\", \"scope\": \"applicant\", \"acr_values\": \"tenant:2fc4a1ca-022c-4fa3-ab6f-a63500a1ede7\" } }" 2016-07-05 10:20:54 [Information] Creating token response 2016-07-05 10:20:54 [Information] Processing token request 2016-07-05 10:20:54 [Debug] Creating access token 2016-07-05 10:20:54 [Debug] Creating JWT access token 2016-07-05 10:20:54 [Information] End token request 2016-07-05 10:20:54 [Information] Returning token response. 2016-07-05 10:21:54 [Error] Invalid access token Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match 'kid': 'cBS9UBUP5ATqBHfEBK9p1LwuJtM', token: '{"alg":"RS256","typ":"JWT","x5t":"cBS9UBUP5ATqBHfEBK9p1LwuJtM","kid":"cBS9UBUP5ATqBHfEBK9p1LwuJtM"}.{"client_id":"applicant-sso","client_sso":"true","scope":"applicant","sub":"24970d08-b1c6-4167-9706-a6350132daf0","amr":["password"],"auth_time":1467732054,"idp":"idsrv","tenant":"2fc4a1ca-022c-4fa3-ab6f-a63500a1ede7","preferred_username":"630_sso4@test.com","email":"630_sso4@test.com","email_verified":"true","iss":"http://localhost:17005","aud":"http://localhost:17005/resources","exp":1467760854,"nbf":1467732054}'. at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)

leastprivilege commented 8 years ago

Are you sure producer and consumer use the same key material. Check our samples where it is working and compare.

jkhines commented 8 years ago

I had the same problem using ASP.NET Core 1.0, which was fixed by the solution in this article: http://stackoverflow.com/questions/38239261/cannot-validate-accesstoken-with-identityserver

Namely, manually implementing IssuerSigningKeyResolver:

var certificate = new X509Certificate2(Convert.FromBase64String("MII123...ABC"));

app.UseJwtBearerAuthentication(
    new JwtBearerOptions
    {
        TokenValidationParameters = new TokenValidationParameters
        {
            ValidAudience = "https://mydomain.com/resources",
            ValidIssuer = "https://mydomain.com",
            IssuerSigningKey = new X509SecurityKey(certificate),
            IssuerSigningKeyResolver = (string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) => new List<X509SecurityKey> { new X509SecurityKey(certificate) }
        }
    });
stewart-noll-q2 commented 8 years ago

Thanks @jkhines. Your IssuerSigningKeyResolver fix solved the problem for us as well.

pjt33 commented 7 years ago

One possible cause, which may not be your problem but which turned out to be mine with a similar issue, is disagreement over the key ID. Microsoft.IdentityModel.Tokens.X509SecurityKey uses the certificate thumbprint in base 16 as its KeyId. The KeyId in your example (and in my case, where the source was Azure Active Directory rather than IdentityServer) uses the certificate thumbprint in (a version of) base 64.

One workaround is to create a subclass of X509SecurityKey whose constructor computes the base 64 key ID and overwrites the KeyId value set by the superclass constructor. A better solution, if possible, would be to get the keys from a source which uses the same key ID format. In my case that was possible with Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever and then

myTokenValidationParameters.IssuerSigningKeys = myOpenIdConnectionConfiguration.SigningKeys;
brockallen commented 7 years ago

You can also just set the Kid manually:

https://github.com/IdentityServer/IdentityServer4.Samples/blob/dev/Clients/src/MvcManual/Controllers/HomeController.cs#L88

leastprivilege commented 7 years ago

v5 of the JWT handler require you to set the key ID explicitly for RSA keys.

That may have been the case before as well - but we always used x509 cert before where this is not necessary.

derekgreer commented 7 years ago

Check our samples where it is working and compare.

I couldn't find a sample that uses JWT (see examples). Can you provide a link to a sample that uses JWT?

leastprivilege commented 7 years ago

I am confused - why are you pointing to a different repo - our samples are here:

https://github.com/IdentityServer/IdentityServer4.Samples/tree/dev/Clients/src/SampleApi

leastprivilege commented 7 years ago

Also - please open a new issue if you still have a problem.

derekgreer commented 7 years ago

Well, that's embarrassing. Sorry about that.

larserikfinholt commented 7 years ago

We got the same error, but our problem was that the issuer and authority urls had differnet casing. https://myserver/sts and https://myserver/Sts