3

我有一个使用 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 中永远不会有其签名,因为我们没有签名凭证。所以这看起来不像是一个错误,而是一个实施决定。我只是不明白为什么。

谢谢

4

3 回答 3

3

这既不是安全(或任何其他)错误,也不是实现决策。Write 可以生成带有签名的 JWT 的唯一位置是发布点。令牌发行者以外的任何一方都不应该尝试重新创建它(这就是您所说的读写往返)。当您收到签名的 JWT 时,您只能验证和阅读它。您可以按原样自由地重新传输原始 JWT,但您将无法“正确”重建它,因为您不是颁发者并且没有适当的签名密钥。

这就是签署令牌背后的原因:只有原始发行人才能正确签署它。

如果您愿意,我可以尝试帮助您使用安全令牌和 STS 设计正确的场景,但为此,请分享您正在实施的场景的序列图。

于 2013-02-10T12:01:11.227 回答
2

如果这是一个错误,我不会感到惊讶 - JWT 处理程序仍处于预览模式。

但也许你不想为 Web API 服务做全面的 ActAs - 看看这里:

http://blogs.msdn.com/b/vbertocci/archive/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas.aspx

于 2013-01-17T20:14:23.847 回答
0

看看 JWTSecurityToken.RawData。其中包含原始编码令牌。并且应该有原始发行人的签名。

于 2013-01-18T17:21:20.963 回答