Сбой проверки Okta OAuth2 токена в AspNetCore
Я хотел бы проверить токен доступа JWT из Okta в заголовке носителя на моем API, но проверка всегда завершается неудачей, что приводит к ошибке ниже:
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()
Мне интересно, может быть причина в том, что открытый ключ 'kid' в токене отличается от открытого ключа в конечной точке Keys на 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"}]}
Это настройка в WebAPI:
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme,
Audience = "http://api.azurewebsites.net",
Authority = "https://dev-606497.oktapreview.com"
});
2 ответа
Чтобы получить ключи для токена доступа через открытые ключи, необходимо включить некоторые функции для своей организации Okta. Пожалуйста, отправьте электронное письмо по адресу developers@okta.com
Вы правы - ребенок отличается от открытого ключа - это идентификатор ключа, который определяет, какой открытый ключ использовать из ответа Keys. Если мы посмотрим на пример ответа для 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
]
Мы видим, что есть свойство kid - если вы делаете это вручную, вам нужно перебрать ключи, чтобы найти ключ, соответствующий ребенку, в вашем ответе / token и использовать его в своей проверке JWT.
Есть несколько примеров, которые демонстрируют этот поток проверки в ASP.net - например, вот соответствующий код в образце потока кода авторизации.
Также, возможно, полезно проверить наш документ Валидация токенов доступа для более общего понимания процесса.
Обновление: только что заметил, что ребенок, которого вы пытаетесь найти, не находится в ответе ключей - это похоже на токены доступа, возвращенные через OIDC (они непрозрачны). Здесь есть пара вариантов:
- Если OpenId Connect, вы должны проверить возвращенный токен доступа через конечную точку /userinfo
- Или, если вы ищете API Access Management, вам нужно связаться с developers@okta.com, чтобы включить эту функцию для вас (как предложил Сохаиб). Это откроет открытые ключи для ваших токенов доступа через конечную точку ключей.