You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助SecurityTokenDescriptor和ClaimsIdentity添加JWT的auth_time声明

解决JWT添加auth_time时间戳声明的问题

我来帮你搞定这个需求!要给JWT添加和iat/nbf/exp格式一致的auth_time秒级Unix时间戳声明,有两种常用实现方式,下面一步步给你说明:

方法1:让auth_time与iat(签发时间)完全同步

如果你的auth_time需要和JWT自动生成的iat保持一致,只需要在构建Claims时计算当前UTC时间的Unix秒级时间戳,再添加对应的Claim即可:

首先可以封装一个工具方法来获取标准Unix时间戳:

private static long GetUnixUtcTimestamp()
{
    // 必须用UTC时间,避免时区差异导致时间戳不符合JWT规范
    return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
}

然后在你的GetIdTokenString方法中,在添加sub声明的位置前后,加入auth_time的Claim:

// 获取当前UTC时间的Unix时间戳
long currentUnixTime = GetUnixUtcTimestamp();
// 指定Claim类型为Integer64,确保JWT中是数字格式而非字符串
claims.Add(new Claim("auth_time", currentUnixTime.ToString(), ClaimValueTypes.Integer64));

// 原有sub声明
claims.Add(new Claim("sub", Guid.NewGuid().ToString()));

这样生成的JWT里,auth_time就会和自动生成的iat拥有完全相同的时间戳数值。

方法2:自定义auth_time的时间(比如用户实际登录时间)

如果auth_time需要对应特定时间(比如用户登录的时间,而非Token签发时间),只需要将目标时间转换为UTC的Unix秒级时间戳即可:

// 示例:假设用户5分钟前完成登录,确保时间是UTC格式
DateTime userLoginTime = DateTime.UtcNow.AddMinutes(-5);
long authTimeStamp = new DateTimeOffset(userLoginTime).ToUnixTimeSeconds();
claims.Add(new Claim("auth_time", authTimeStamp.ToString(), ClaimValueTypes.Integer64));

完整修改后的代码片段

把上述逻辑整合到你的原有代码中,最终版本如下:

public string GetIdTokenString(Dictionary<string, object> inputClaims, string secret) {
    string result = null;
    try {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(secret);
        List<Claim> claims = new List<Claim>();
        foreach (var o in inputClaims) {
            string val = null;
            if (o.Value != null) {
                Type t = o.Value.GetType();
                bool isDict = t.IsGenericType;
                if (isDict) {
                    val = JsonSerializer.Serialize(o.Value);
                } else {
                    val = o.Value.ToString();
                }
            }
            claims.Add(new Claim(o.Key, val));
        }

        // 添加auth_time声明(与iat同步的版本)
        long currentUnixTime = GetUnixUtcTimestamp();
        claims.Add(new Claim("auth_time", currentUnixTime.ToString(), ClaimValueTypes.Integer64));

        claims.Add(new Claim("sub", Guid.NewGuid().ToString()));
        var tokenDescriptor = new SecurityTokenDescriptor {
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.UtcNow.AddSeconds(60 * 5), // 建议改为UTC时间,避免时区问题
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
            Audience = ObjInitialRequest.JwtData.ContainsKey("client_id") ? ObjInitialRequest.JwtData["client_id"] : null,
            Issuer = "...",//from well known configuration issuer
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        if (token != null && token is JwtSecurityToken) {
            result = (token as JwtSecurityToken).RawData;
        }
    } catch (Exception ex) {
        //Logger
    }
    return result;
}

// 复用的Unix时间戳工具方法
private static long GetUnixUtcTimestamp()
{
    return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
}

关键注意事项

  • 强制使用UTC时间:JWT的时间戳规范基于UTC,必须用DateTime.UtcNow而非DateTime.Now,否则会因为时区差异导致时间戳不符合预期。
  • 指定Claim数据类型:添加auth_time时必须指定ClaimValueTypes.Integer64,这样JWT中的auth_time会是数字类型(和iat/nbf/exp格式一致),而非字符串,符合JWT标准。

内容的提问来源于stack exchange,提问作者Kamran Shahid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:27:44