我有一个使用 WIF 和 .NET 4.5 实现的基于声明的身份验证系统的工作实现。它包含通常的部分:
- 具有被动和主动端点的自定义 STS
- 后端 WCF 服务
- 前端 MVC 应用程序
- 前端 WebApi 应用程序
从前端应用程序到后端 WCF 服务的调用使用委托身份验证,因此用户在前端应用程序中进行身份验证,应用程序使用 ActAs=BootstrapToken 请求新令牌,然后调用 WCF 服务。
这一切都与 SAML 令牌一起正常工作。
现在我想使用 JWT 令牌与 WebApi 对话,因此我在我的 STS 和 WebApi 项目中安装了 Microsoft .Net Framework 4.5 Nuget 包的 JSON Web 令牌处理程序。
所以我让我的 STS 正确地发出签名的 JWT 令牌,而我的 WebApi 依赖方验证了相同的令牌。一切都好。
问题:
如果我在我的 RST 的 ActAs 字段中使用 JWT 令牌,它将在没有签名的情况下发送,因此它自然会被 STS 拒绝。似乎 SecurityTokenHandler.ReadToken() 方法返回的令牌返回一个没有任何签名信息的令牌。
现在我的困境是:这是 JWT 令牌支持的场景吗?据我了解,与 SAML 令牌相反,JWT 令牌不携带验证签名的所有信息,那么还有其他限制吗?
另一方面,如果确实支持,那么之前是否有人实施过,或者有什么想法?这是开发人员预览版,所以它可能是一个错误吗?
编辑
这是说明问题的示例。该代码在 STS(可以访问签名密钥)和依赖方(可以访问证书的公钥)中运行时产生相同的结果:
System.Diagnostics.Debug.WriteLine("Raw Token : {0}", (object)rawToken);
var readToken = this.identityConfiguration.SecurityTokenHandlers.ReadToken(rawToken);
this.identityConfiguration.SecurityTokenHandlers.ValidateToken(readToken);
var serializedToken = this.identityConfiguration.SecurityTokenHandlers.WriteToken(readToken);
System.Diagnostics.Debug.WriteLine("Serialized Token: {0}", (object)serializedToken);
产生以下
Raw Token : eyJAi(...)x3a9.eyJvYXB(...)DYzWiJ9.y-lT(...)PyBUTw
Serialized Token: eyJAi(...)x3a9.eyJvYXB(...)DYzWiJ9.
因此,很明显,读/写往返会丢失签名信息。我可以理解为什么这会发生在 RP 中,但不会发生在 STS 中。
编辑 2
所以这是当前的JWTSecurityTokenHandler.WriteToken(SecurityToken token)
实现:
public override string WriteToken(SecurityToken token)
{
Utility.VerifyNonNullArgument("token", token);
JWTSecurityToken jWTSecurityToken = token as JWTSecurityToken;
if (jWTSecurityToken == null)
{
throw new SecurityTokenException(string.Format(CultureInfo.InvariantCulture, "JWT10200: This instance of JWTSecurityTokenHandler can only write SecurityTokens of type '{0}', a SecurityToken of type '{1}' was received.", new object[]
{
typeof(JWTSecurityToken),
token.GetType()
}));
}
string text = string.Empty;
string text2 = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[]
{
jWTSecurityToken.EncodedHeader,
jWTSecurityToken.EncodedPayload
});
if (jWTSecurityToken.SigningCredentials != null)
{
text = this.Sign(text2, jWTSecurityToken.SigningCredentials);
}
return string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[]
{
text2,
text
});
}
通过研究,很明显,写入的令牌在 RP 中永远不会有其签名,因为我们没有签名凭证。所以这看起来不像是一个错误,而是一个实施决定。我只是不明白为什么。
谢谢