4

I would like to validate a JWT access token from Okta in bearer header on my API, but the validation always fails giving the error below:

2016-12-16 10:12:30.451 +00:00 [Information] Failed to validate the token "eyJhbGciOiJSUzI1NiIsImtpZCI6Il95EVnTTc3MkRHSFdtV19ETDNJYUUyNlUifQ.eFULi1ET2htZFhUalFmcmV5bHdaZkI5aFVobFJ5VlRTenRvRTc1cHVSNUYwUlEiLCJpc3MiOLCJjaWQiOiJZTFpSUUZoWEY1RlpTd2xrbDlwVCIsInVpZCI6IjAwdTkxYXdpZmthZzZYcFE5MGg3Iiwic2NwIjpbIm9wZW5pZCIsInByb2ZpbGUiXX0.K50-cdNI1_m1GLglguCvpiinhxKYNwy0ieAABP7lfO2briaT29mzPeQx07a8F_CyJtQbEtOsPkYviCSK309m8n70WoM51B7FxYTebAxIvWZNrdB_Nsid4YrQHoOoM5b54Fzr4FE-7510TJxvKPg8lWViTQG5cfijE6AL-JXuPYlmdikByZbLwg57P4sUBWByF-pTcRqE2l03VOdkyQOJJ4v22jSUSgKFSYdaXH4ufFt2iTv_sbnNTTtXz4tKLLgfzsKZuxo7-N6-QB7Zuhn7g".
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match 'kid': '_yomDqFziFzjpiI-OZmeDEgM772DGHWmW_DL3IaE26U', 
token: '{"alg":"RS256","typ":"JWT","kid":"_yomDqFziFzjpiI-OZmeDEgM772DGHWmW_DL3IaE26U"}.{"ver":1,"jti":"AT.-DOhmdXTjQfreylwZfB9hUhlRyVTSztoE75puR5F0RQ","iss":"https://dev-606497.oktapreview.com","aud":"https://dev-606497.oktapreview.com","sub":"myemail@email.com","iat":1481883065,"exp":1481886665,"cid":"YLZRQFhXF5FZSwlkl9pT","uid":"00u91awifkag6XpQ90h7","scp":["openid","profile"]}'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.<HandleAuthenticateAsync>d__1.MoveNext()

I'm wondering if the reason could be, that the public key 'kid' in token is different than the public key in Keys endpoint on Okta?

{"keys": [{"alg": "RS256","e": "AQAB","n": "wtkBXocJLBE-ArN56pLzSiR3x2w99R2d_rlCpFN__3k1I6P0vcfE4SKwoafzucaG-kEwy9pn4p49z0O24UHX0NmdxOMhyFmJsfss0tK0AkBhXB-e9kk5r316ePRtb7eo8uAnjNP7w2T6sSqwdppw7I8NQa4KrFIYFVDx4xDcYMfnGrKjKFdghxSpG2dP7vcQsjJHkMyEHYj7nTTyplReX21_Et2F5zHqvqQZ1JRuL_Ol-JrSEeM0Hznpb7kpggnFUA_xnzcR4AhT5P2WNNNenlfurjM_AN1ymV8DT04Tx7tp6G60N1AkDw4t4Q0LfuevQ","kid": "gtUiz-YdlCSRpr0Ue7LRuEtqgVqRmDWpe5ZuvBaWgVk","kty": "RSA","use": "sig"}]}

This is the setup on WebAPI:

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme,
    Audience = "http://api.azurewebsites.net",
    Authority = "https://dev-606497.oktapreview.com"
});
dieselcz
  • 163
  • 8
  • dieselcz, I am calling OKTA OPENID API and pulling back the JWT after the user logins. Passing that JWT to my API. It seems that signature is null. I read that I have to use both OPENID along with an OKTA Authorization Server to be able to validate the token? Is this your approach, can you provide any insight? – Patrick Aug 07 '17 at 14:09

2 Answers2

1

In order to get keys for access token via public keys url some features need to be enabled for your Okta org. Please send email to developers@okta.com

Sohaib Ajmal
  • 251
  • 1
  • 4
1

You are correct - the kid is different from the public key - it's the key id that identifies which public key to use from the Keys response. If we look at the response example for v1/keys:

"keys": [
  {
    "alg": "RS256",
    "e": "AQAB",
    "n": "iKqiD4cr7FZKm6f05K4r-GQOvjRqjOeFmOho9V7SAXYwCyJluaGBLVvDWO1XlduPLOrsG_Wgs67SOG5qeLPR8T1zDK4bfJAo1Tvbw
          YeTwVSfd_0mzRq8WaVc_2JtEK7J-4Z0MdVm_dJmcMHVfDziCRohSZthN__WM2NwGnbewWnla0wpEsU3QMZ05_OxvbBdQZaDUsNSx4
          6is29eCdYwhkAfFd_cFRq3DixLEYUsRwmOqwABwwDjBTNvgZOomrtD8BRFWSTlwsbrNZtJMYU33wuLO9ynFkZnY6qRKVHr3YToIrq
          NBXw0RWCheTouQ-snfAB6wcE2WDN3N5z760ejqQ",
    "kid": "U5R8cHbGw445Qbq8zVO1PcCpXL8yG6IcovVa3laCoxM",
    "kty": "RSA",
    "use": "sig"
  },
  ... more
]

We can see that there is a kid property - if you're doing it manually, you have to iterate over the keys to find the key that matches the kid in your /token response, and use that in your JWT validation.

There are a couple samples that demonstrate this validation flow in ASP.net - for example, here's the relevant code in an Authorization Code flow sample.

It's also probably helpful to check out our Validating Access Tokens doc for a more general understanding of the flow.

Update: Just noticed that the kid you're trying to lookup is not in the keys response - this is as designed for access tokens returned through OIDC (they are opaque). There are a couple options here:

  1. If OpenId Connect, you have to validate the returned access token through the /userinfo endpoint
  2. Or, if you're looking into API Access Management, you'll need to contact developers@okta.com to turn on that feature for you (as Sohaib suggested). This will expose the public keys for your access tokens through the keys endpoint.
remanc
  • 195
  • 10
  • Just to confirm: the recommended strategy for validating OIDC JWTs is to check whether the /userinfo endpoint returns a successful response, and there is no way to verify the token signature in my own code, even if I did want to. Is this documented anywhere else? – giraffe.guru Oct 19 '18 at 03:01