【问题标题】:Generate JWT with certificate thumbprint with JSON Web Token Handler for .Net使用 JSON Web Token Handler for .Net 生成带有证书指纹的 JWT
【发布时间】:2016-03-08 01:58:05
【问题描述】:

我正在开始一项新任务,我必须处理来自 JWT 的指纹。我们为 Microsoft .Net 框架使用 JSON Web 令牌处理程序。已经有一个在测试中使用的实现,它生成 JWT,而在标头中没有 x5t 文件。它看起来像这样:

var handler = new JwtSecurityTokenHandler();
      var securityKey = new InMemorySymmetricSecurityKey(Any.Array<byte>(1024));
      var desc = new SecurityTokenDescriptor
      {
        TokenIssuerName = "MSI",
        Lifetime = new Lifetime(null, DateTime.UtcNow.AddDays(10)),
        SigningCredentials = new SigningCredentials(securityKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", "http://www.w3.org/2001/04/xmlenc#sha256"),
      };

      var identity = new ClaimsIdentity();
      identity.AddClaim(new Claim("scope", "msi_unsapi_presence.watch"));
      identity.AddClaim(new Claim("scope", "msi_unsapi_location.watch"));
      identity.AddClaim(new Claim("scope", "msi_unsapi_groupmgt.read"));
      identity.AddClaim(new Claim("scope", "msi_unsapi_groupmgt.write"));
      var jwtToken = handler.CreateToken(desc);
      return jwtToken;

它产生的令牌:{"typ":"JWT","alg":"HS256"}.{"scope":["msi_unsapi_presence.watch","msi_unsapi_location.watch","msi_unsapi_groupmgt.read","msi_unsapi_groupmgt.write"]} 我尝试将 SecurityTokenDescriptor 的 AttachedReference 属性设置为以下AttachedReference = new X509ThumbprintKeyIdentifierClause(Any.Array&lt;byte&gt;(1024)) 以在令牌中填充 x5t 字段(我不关心确切的值,我只需要它出于测试目的存在于令牌中)但生成的令牌仍然没有设置此字段。如何在标头中生成非空 x5t 的令牌,最好修改现有代码?

【问题讨论】:

  • 我不熟悉您的 JwtSecurityTokenHandler 类,但我在实现中所做的是创建自己的 jsonWebTokenFormat 来实现 ISecureDataFormat (实现保护/取消保护方法),诀窍在于您需要调用 JwtPayload() 类,它是 Dictionary() 的超类,因此您可以将 x5t 字段添加到您想要的任何值,只要它是 json 格式。那么您将需要配置您的 JwtSecurityTokenHandler 以使用您的新 JwtFormat 然后继续您的身份和声明。
  • 我无法修改 JwtSecurityTokenHandler 类,因为它是一个库类 (nuget.org/packages/System.IdentityModel.Tokens.Jwt) 而且我真的找不到可以根据需要配置它的方式。
  • 好的,我很快就会向您展示一个实现。

标签: c# .net jwt


【解决方案1】:

这是您的 customJsonWebTokenFormat 的实现:

您真的可以使用 payload.add() 向其中添加任何内容。

          public class yourJsonWebTokenFormat: ISecureDataFormat<AuthenticationTicket>
            {
                public string Protect(AuthenticationTicket data)
                {
                DateTime notBefore = DateTime.UtcNow;
                DateTime expires = notBefore + TimeSpan.FromHours(1); //validity timer.

         SigningCredentials cred= new SigningCredentials(); // your signing credentials.
                    JwtHeader header = new JwtHeader(cred);
header.add("x5t","your value");
                    JwtPayload payload = newJwtPayload(ConfigurationManager.AppSettings["Issuer"],data.Properties.Dictionary["audience"], data.Identity.Claims, notBefore, expires);
        payload.add("x5t","your x5t to json property");

                    var jwtToken = new JwtSecurityToken(header, payload);
                    var handler = new JwtSecurityTokenHandler();
                    var jwt = handler.WriteToken(jwtToken);
                    return jwt;
                }
    }

然后在您的 OAuth 配置中:

     OAuthAuthorizationServerOptions OAuthServerOptions = new 

    OAuthAuthorizationServerOptions()
                {
    // provider configuration, token authentication expiracy, etc...
Provider = new SampleAuthorizationServerProvider()
                    AccessTokenFormat = new JsonWebTokenFormat()
                };

请求令牌现在将调用您的 yourJsonWebTokenFormat.protect() 方法。

您应该在您自己的 OAuthAuthorizationServerProvider 的 AuthenticationTicket 中设置您在示例中构建的身份。

类似的东西:

        public class SampleAuthorizationServerProvider : OAuthAuthorizationServerProvider, IOAuthAuthorizationServerProvider
        {
           public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
                {
        // do AD check or other stuff needed to validate the user here
            var ticket = new AuthenticationTicket(identity, props); // props here is a AuthenticationProperties Dictionnary with other stuff that you want in your JwtToken
    context.Validated(ticket);
        }

        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
//do some check...
context.Validated();
}
    }

所以你最终需要实现 2 个类:ISecureDataFormat&lt;AuthenticationTicket&gt;

OAuthAuthorizationServerProvider, IOAuthAuthorizationServerProvider

【讨论】:

  • 1) 当我向有效负载添加任何内容时,该值不会添加到 jwt 标头。 2)我不想从头开始创建 jwt,而是使用现有方法。现在我只是将 CreateToken 结果向下转换为 JwtSecurityToken 并将值添加到标题中,就像普通字典一样,这很难看
  • 不仅丑陋,而且你得到的令牌现在应该是无效的。 CreateToken 负责将签名添加到令牌。如果您之后修改它,我认为签名不会更新。因此您的签名将不再与有效负载匹配。
  • 同样它并没有解决这个文件不在你的方法标题中的问题
  • 实际上确实如此,Body/ 有效负载可以做什么,header 也一样,所以 header.add("x5t","your Value");将在标题中添加一个带有 x5t 的字段。
  • 这与我之前写的简单地设置值没有什么不同。签名似乎以相同的方式更新。
猜你喜欢
  • 2017-04-12
  • 2016-11-24
  • 2016-04-07
  • 1970-01-01
  • 2019-04-12
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
相关资源
最近更新 更多