2014-07-09 55 views
10

我正在尝试为我的组织实施OpenID Connect规范。我在测试依赖方应用程序中使用Microsoft的OWIN OpenID Connect实现来验证我的协议实现。验证JWT签名时出现SecurityTokenSignatureKeyNotFoundException

我露出下面的元数据文档:

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

正在使用JwtSecurityToken类及其关联的处理产生的身份令牌,使用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 =假,计数= 1,第[0] = X509ThumbprintKeyIdentifierClause(散列= 0xF8A59280B3D13777CC7541B3218480984F421450))',令牌: “{ “典型值”: “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.xkP0RwlX3CYfU0KhFsVvLJC94WK22DTqNTm71cfjiJ8VUHv3b2YhDqfq70N8mQEyiR8vTR6OQqnO6UqXqX4RXUs6ZkfK 9Liv3n9NhCs97wJhP2jfefJYeScYtRmWcNNWSSL7vkm2JXQfwKOQTnOGp-ba04TtI6jVrjhOQXH43eCJ9vNuBUzdD-t8CAdmnbvH0nWpIB8kWbw5v8Sa0aQuxMjJYbLC_2Iw3X13dqnyVjp4fA7eSB8N7c1it0KEB-VKfUqiGD3VecyEZGGZbaGE8rvVet5QrY1lJ3V4yM8j6-xDc5Yndc4swOun0L3D6TYk-8gdVXUJDRjbv1ZuhZltsw”。

该组件仍然是预发布的,所以这可能是实现中的缺陷,但是我想假设这是我的错误,直到排除所有可能性。

有什么我正在做的事显然是错的,或者有什么我应该做的以明确为什么签名无法验证?

回答

5

问题坐落在异常的讯息:

第[0] = X509ThumbprintKeyIdentifierClause(散列= 0xF8A59280B3D13777CC7541B3218480984F421450)

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

要纠正这个错误,签名证书必须改变,以包括正确的名称标识符:

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

这包括签名预期的标识符,并且签名验证成功。

+1

请告诉我在哪里可以得到您所指的证书? –

+1

这很有道理,但是你从哪里获得证书? –

+0

我正在学习一个教程,并且使用临时证书'AddTemporarySigningCredential()',所以在刷新Web应用程序之后,它就可以工作。 – Jaider