SecurityTokenSignatureKeyNotFoundException при проверке подписи JWT

Я пытаюсь реализовать спецификацию OpenID Connect для своей организации. Я использую реализацию OpenID Connect от Microsoft OWIN в тестовом приложении проверяющей стороны, чтобы проверить мою реализацию протокола.

Я представил следующий документ метаданных:

{
  "issuer": "https://acs.contoso.com/",
  "authorization_endpoint": "http://localhost:53615/oauth2/auth",
  "token_endpoint": "http://localhost:53615/oauth2/token",
  "userinfo_endpoint": "http://localhost:53615/connect/userinfo",
  "jwks_uri": "http://localhost:53615/connect/keys",
  "ui_locales_supported": [
    "en-GB"
  ]
}

Ключ подписи представлен в виде этого документа:

{
  "keys": [
    {
      "n": "xpXxl3M-YkZlzQJdArO1TfOGT2no-UL4dbZ7WuSCNIsSfyGDaqUXjMMHNyq9yD3vp-NCyk8kmn7d5XqHufnceXJM8q4xTrhN3lvywdBSbR-dwXsA-B-MJVgfiK0d_z-mxP9ew2Hj9-KkWbWCzsswlWp3gZ4mB4RGutB1IRSzXVIbvZ-MtKUb6XUDU4LDb_c1xCEXWZxhR-o1a1dLfObH2hHJ-w5y6odGlKtOFx4i4h0u7-Oj5R6k5b2YXEHM0IuYeN0u0sQvrTecokntGzPrvhnKy69I7Z_az5rC5kgloh25D9lTbe4vcRU7FXlYCFYDZsT0_IkGIXRi7brOS4f1ow",
      "e": "AQAB",
      "kty": "RSA",
      "use": "sig",
      "alg": "RS256",
      "kid": "F8A59280B3D13777CC7541B3218480984F421450"
    }
  ]
}

Маркер удостоверения создается с помощью _ 3_ и связанный с ним обработчик, используя класс X509SigningCredentials. Этот код представляет, как создается маркер и возвращается в вызывающую систему в качестве параметра данных ответа.

var credentials = new X509SigningCredentials(cert); // My certificate.
var issuedTime = DateTime.UtcNow;
var expiresTime = issuedTime.AddMinutes(5);
var epoch = new DateTime(1970, 01, 01, 0, 0, 0);

var claims = new[]
{
    new Claim("sub", Guid.NewGuid().ToString()),
    new Claim("iat" Math.Floor((issuedTime - epoch).TotalSeconds).ToString()),
    new Claim("nonce", nonce), // Value from client
}

var token = new JwtSecurityToken(
    "https://acs.contoso.com",
    client_id, // Value from client
    claims,
    new Lifetime(issuedTime, expiresTime),
    credentials);

var handler = new JwtSecurityTokenHandler();
parameters.Add("id_token", handler.WriteToken(token)); // Outgoing parameters.

Когда я пытаюсь передать подписанный токен обратно в приложение проверяющей стороны, промежуточное ПО OWIN принимает POST и пытается проверить подпись токена. При этом возникает следующее исключение:

SecurityTokenSignatureKeyNotFoundException: IDX10500: ошибка проверки подписи. Невозможно разрешить SecurityKeyIdentifier: 'SecurityKeyIdentifier (IsReadOnly = False, Count = 1, Clause [0] = X509ThumbprintKeyIdentifierClause (Hash = 0xF8A59280B3D13777CC7541B3218480984F421450)', тип: "RSW6", ", token:" JG6 ",", ", token:", "," "x5t": "- KWSgLPRN3fMdUGzIYSAmE9CFFA"}. {"iss": "https://test.accesscontrol.net/ "," aud ":" test "," nbf ": 1404917162," exp ": 1404917462," sub ":" 60eb55ec-0699-4068-bfa6-41666fc2b2e9 "," iat ":" 1404917162 "} RawData : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ii1LV1NnTFBSTjNmTWRVR3pJWVNBbUU5Q0ZGQSJ9.eyJpc3MiOiJodHRwczovL2Fjcy5zdXJlY2xvdWQuY29tLyIsImF1ZCI6InRlc3QiLCJuYmYiOjE0MDQ5MTcxNjIsImV4cCI6MTQwNDkxNzQ2Miwic3ViIjoiNjBlYjU1ZWMtMDY5OS00MDY4LWJmYTYtNDE2NjZmYzJiMmU5IiwiaWF0IjoiMTQwNDkxNzE2MiJ9.xkP0RwlX3CYfU0KhFsVvLJC94WK22DTqNTm71cfjiJ8VUHv3b2YhDqfq70N8mQEyiR8vTR6OQqnO6UqXqX4RXUs6ZkfK9Liv3n9NhCs97wJhP2jfefJYeScYtRmWcNNWSSL7vkm2JXQfwKOQTnOGp-ba04TtI6jVrjhOQXH43eCJ9vNuBUzdD-t8CAdmnbvH0nWpIB8kW bw5v8Sa0aQuxMjJYbLC_2Iw3X13dqnyVjp4fA7eSB8N7c1it0KEB-VKfUqiGD3VecyEZGGZbaGE8rvVet5QrY1lJ3V4yM8j6-xDc5Ynd0c4swOffy

Компонент все еще находится в стадии предварительного выпуска, поэтому это может быть недостатком в реализации, однако я хочу считать, что это моя ошибка, пока не будут исключены все возможности.

Есть ли что-то, что я делаю явно неправильно, или я должен что-то сделать, чтобы точно понять, почему подпись не проходит проверку?


person Paul Turner    schedule 09.07.2014    source источник


Ответы (2)


Проблема содержится в сообщении об исключении здесь:

Пункт [0] = X509ThumbprintKeyIdentifierClause (Hash = 0xF8A59280B3D13777CC7541B3218480984F421450)

Маркер подписан предложением идентификатора ключа по умолчанию для сертификата X.509: его отпечатком. Метаданные предоставляют только параметры RSA и идентификатор имени. Когда клиент получает метаданные, он устанавливает ключ RSA, используя эту информацию, а не отпечаток X.509.

Чтобы исправить эту ошибку, необходимо изменить учетные данные для подписи, чтобы включить в них правильный идентификатор имени:

var credentials = new X509CertificateCredentials(
    cert,
    new SecurityKeyIdentifier(
        new NamedKeySecurityKeyIdentifierClause(
            "kid",
            "F8A59280B3D13777CC7541B3218480984F421450")));

Это включает ожидаемый идентификатор в подписи, и подпись успешно проверена.

person Paul Turner    schedule 09.07.2014
comment
Скажите, пожалуйста, где взять сертификат, о котором вы говорите? - person Jaffer Wilson; 06.07.2015
comment
В этом есть смысл, но откуда вы взяли сертификат? - person Sergey Akopov; 19.01.2016
comment
Я следил за учебником и использовал временный сертификат AddTemporarySigningCredential(), поэтому после обновления веб-приложения он работает. - person Jaider; 25.01.2017

Я столкнулся с этим исключением. В моем случае наше приложение кэшировало ключи подписи из нашей среды Azure, поскольку они не меняются часто, но не было механизма для обновления ключей. Поскольку в конечном итоге ключи подписи меняются, мы получали действительные JWT, но у нас был старый список ключей подписи, и в этом случае ни один из них не мог проверить подпись JWT.

person Ryan D    schedule 14.01.2021