使用带委派的JWT令牌(ActAs)

时间:2013-01-17 14:33:49

标签: asp.net-web-api wif claims-based-identity jwt

我有一个使用WIF和.NET 4.5实现的基于声明的身份验证系统的工作实现。它包含通常的部分:

  • 具有被动和主动端点的自定义STS
  • 后端WCF服务
  • 前端MVC应用程序
  • 前端WebApi应用程序

从前端应用程序到支持的WCF服务的调用使用Delegated身份验证,因此用户在前端应用程序中进行身份验证,应用程序请求具有ActAs = BootstrapToken的新令牌,然后调用WCF服务。

这一切都与SAML令牌一起正常工作。

现在我想使用JWT令牌与WebApi通信,所以我在我的STS和WebApi项目中安装了JSON Web Token Handler For the Microsoft .Net Framework 4.5 Nuget包。

所以我让我的STS正确签发了签名的JWT令牌,我的WebApi依赖方验证了相同的令牌。一切都很好。

问题:

如果我在RST的ActAs字段中使用JWT令牌,它将被发送没有签名,因此它自然会被STS拒绝。似乎SecurityTokenHandler.ReadToken()方法返回的令牌返回没有任何签名信息的令牌。

现在我的困境是:这是JWT令牌支持的场景吗?据我所知,JWT令牌不包含验证签名的所有信息,而不是SAML令牌,那么还有其他限制吗?

另一方面,如果确实支持这个,有没有人以前实现过这个,或者有任何想法?这是一个开发者预览版,所以它可能是一个错误吗?

修改

这是一个说明问题的示例。在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中,书面令牌永远不会有签名,因为我们没有签名证书。所以这看起来不像是一个bug,而是一个实现决策。我只是不明白为什么。

由于

3 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分: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

答案 2 :(得分:0)

查看JWTSecurityToken.RawData。那包含原始的encodedToken。并且应该有原始发行人的签名。