如何借助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
相关产品推荐
相关产品推荐

