c# - 验证 JWT 签名时出现 SecurityTokenSignatureKeyNotFoundException

标签 c# x509certificate jwt katana openid-connect

我正尝试为我的组织实现 OpenID Connect 规范。我在测试依赖方应用程序中使用 Microsoft 的 OpenID Connect OWIN 实现来验证我的协议(protocol)实现。

我公开了以下元数据文档:

{
  "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"
  ]
}

签名 key 公开为该文档:

{
  "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"
    }
  ]
}

正在使用 JwtSecurityToken 生成身份 token 类及其关联的处理程序,使用 X509SigningCredentials 类。此代码代表如何构造 token 并将其作为响应数据的参数返回给调用系统。

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.

当我尝试将已签名的 token 传递回依赖方应用程序时,OWIN 中间件接受 POST 并尝试验证 token 的签名。这样做会抛出以下异常:

SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier ( IsReadOnly = False, Count = 1, Clause[0] = X509ThumbprintKeyIdentifierClause(Hash = 0xF8A59280B3D13777CC7541B3218480984F421450) ) ', token: '{"typ":"JWT","alg":"RS256","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-t8CAdmnbvH0nWpIB8kWbw5v8Sa0aQuxMjJYbLC_2Iw3X13dqnyVjp4fA7eSB8N7c1it0KEB-VKfUqiGD3VecyEZGGZbaGE8rvVet5QrY1lJ3V4yM8j6-xDc5Yndc4swOun0L3D6TYk-8gdVXUJDRjbv1ZuhZltsw'.

该组件仍处于预发布状态,因此这可能是实现中的一个缺陷,但在排除所有可能性之前,我想假设这是我的错误。

我在做什么明显是错误的,或者我应该做些什么来准确理解签名验证失败的原因?

最佳答案

问题出在此处的异常消息中:

Clause[0] = X509ThumbprintKeyIdentifierClause(Hash = 0xF8A59280B3D13777CC7541B3218480984F421450)

token 使用 X.509 证书的默认 key 标识符子句签名:它的指纹。元数据仅公开 RSA 参数和名称标识符。当客户端检索元数据时,它使用此信息而不是 X.509 指纹设置 RSA key 。

要更正此错误,必须更改签名凭据以包含正确的名称标识符:

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

这在签名中包含预期的标识符,并且签名已成功验证。

关于c# - 验证 JWT 签名时出现 SecurityTokenSignatureKeyNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24657307/

相关文章:

android - 无法从 Android 链中获取根 CA 证书

go - 在不同的 goroutine 中替换字符串的值时是否需要互斥锁?

.net - SignedXml.CheckSignature 引发异常 : Value cannot be null. 参数名称:名称

c# - Web API 2 不工作 (404)

C# POST JSON 请求到 Google Vision

c# - WPF MVVM - 在 "parent" View 模型中调用方法的正确方法

ios - Apple 证书对 PKCS7_verify 无效

java - 重启服务器后JWT失效

angular - Auth0 和 Angular 2 : login and routing failing using the login widget

c# - Windows 8 GridView 最大项目数(根据屏幕大小)