从 TokenValidatedContext 获取签名

Ola*_*son 5 c# jwt adal .net-core

我正在为我的 .NET Core 项目使用Microsoft.AspNetCore.Authentication.JwtBearerSystem.IdentityModel.Tokens.Jwt包。

在配置服务时,我正在向OnTokenValidated事件添加逻辑。

    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(jwtBearerOptions =>
        {
            // ... set TokenValidationParameters ...

            jwtBearerOptions.Events = new JwtBearerEvents()
            {
                OnTokenValidated = (tokenValidatedContext) => 
                {
                    JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
                    string tokenWithoutSignature = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);

                    // ... full token from request? ...
                }
            };
        });
Run Code Online (Sandbox Code Playgroud)

由于我知道上下文只返回没有签名的令牌,我想知道我怎么做

  • 要么获得带有签名的完整令牌
  • 或另外签名以将其添加到tokenWithoutSignature字符串中

如果这是不可能的:

我正在以这种方式生成新令牌

public string GenerateAccessToken(IDictionary<string, object> payload)
{
    SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Convert.FromBase64String("secret from config"));

    SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
    {
        Claims = payload,
        Expires = DateTime.Now, // value from config
        SigningCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256Signature)
    };

    JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
    SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
    string token = tokenHandler.WriteToken(securityToken);

    return token;
}
Run Code Online (Sandbox Code Playgroud)

也许我可以找回

  • 没有签名的令牌字符串
  • 只有签名

在这个方法中?


如果没有任何效果:

因为我知道不记名令牌总是包含三个部分,例如

header.payload.signature

我可以将字符串段拆分为一个数组,从数组中取出第一个和第二个元素并创建一个新的字符串

第一个字符串 + 。+ 第二个字符串

那应该给我没有签名的令牌。有没有更好的想法来从完整的令牌中切断签名?


我为什么要达到这个目标?

这个问题是基于这个的

来自 OnTokenValidated 事件侦听器的 TokenValidatedContext 的安全令牌缺少最后一个字符串段

我正在处理访问和刷新令牌。在验证期间,我必须将请求中的令牌与数据库中的令牌进行比较。数据库中的令牌也包含签名。所以我面临着与上面链接相同的问题。

这就是为什么我考虑了多种解决方案并将它们写在这里。如果TokenValidatedContext无法将签名返回给我,似乎我必须将 JWT 存储到没有签名的数据库中。而且对于这种情况,我需要将签名与生成的 JWT 分开。

在不使用刷新令牌的情况下,我只将用户的最长会话生命周期存储到数据库中。流程就是基于这个思路

只将生命周期最长的 JWT 的时间存储到数据库中,而不是整个 JWT

通过使用刷新令牌,我想出了以下流程。由于您知道 OnTokenValidated 处理验证逻辑,因此以下逻辑是附加的。我有一个数据库表

用户名 | access_token | refresh_token | refresh_token_expires_at

主键是username+access_token的复合键。刷新令牌只是一些像这样生成的随机字符串

public string GenerateRefreshToken()
{
    var randomNumber = new byte[32];

    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(randomNumber);

        return Convert.ToBase64String(randomNumber);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是为什么我要为它存储一个额外的到期日期。它应该能够在一段时间后过期。

  • 登录中

    将生成的访问和刷新令牌及其用户的到期时间存储到数据库中。将完整的访问令牌或没有签名的访问令牌存储到数据库(取决于此问题的解决方案)。

  • 命中受保护的端点

    检查数据库中是否存在该用户的访问令牌。

  • 点击刷新端点

    检查数据库刷新令牌是否已过期。如果没有,请将其与请求中的刷新令牌进行比较。如果一切正常,请从数据库中删除旧的访问和刷新令牌,并将新生成的访问和刷新令牌存储到数据库中。

  • 退出

    从数据库中删除该访问权限及其连接的刷新令牌。