Microsoft.IdentityModel.Tokens (.NET).NET
错误信息
IDX10223: Lifetime validation failed. The token is expired.
也可能输出为
- Bearer error="invalid_token", error_description="The token expired at '10/20/2026 06:28:30'"
- IDX10222: Lifetime validation failed. The token is not yet valid.
“The token is expired.”之后的文本包含两个时间戳,格式取决于服务器的区域性设置。ASP.NET Core 的 `WWW-Authenticate` 描述由 `JwtBearerHandler` 生成。
Microsoft.IdentityModel.Tokens (.NET) — SecurityTokenExpiredException
含义
令牌的 `exp` 早于当前时间减去 `ClockSkew`(默认为 5 分钟)的结果。签名和其他声明可能都有效,只是令牌已超过有效期。消息后面接着是“ValidTo (UTC): …, Current time (UTC): …”,ASP.NET Core 会向客户端报告 `error_description="The token expired at '…'"`。IDX10222 是相反的情况:`nbf` 是一个未来的时间。
原因
令牌已超过有效期
常见Entra ID 访问令牌默认有效 60~90 分钟;其他提供商通常为 5~15 分钟。过了 `exp` 仍继续使用同一令牌的客户端,会在到期时刻准时失败。
时钟偏差超出容差
偶见如果调小了 `ClockSkew`(例如常被复制粘贴的 `TimeSpan.Zero`),颁发者与 API 之间哪怕只有几秒的时钟漂移,也会导致刚签发的令牌被拒绝。
绕过令牌库自行缓存的令牌
偶见存放在数据库、静态字段或配置文件中的令牌永远不会刷新。只要交给 MSAL 及类似的库处理,它们就会自动刷新令牌。
修复方法
- 1.
保留较小的时钟偏差容差
容忍秒级而不是分钟级的漂移,并校正时钟。切勿在生产环境中设置 `ValidateLifetime = false`。
csharp options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = "https://login.example.com/", ValidAudience = "api://orders", ClockSkew = TimeSpan.FromSeconds(30), // default is 5 minutes; lower it, do not raise it to hide expiry }; - 2.
每次调用都通过库获取令牌
`AcquireTokenSilent` 会从缓存返回有效令牌或将其刷新,因此在发出请求之前过期问题就已经处理好了。
csharp // Client side (MSAL): ask for a token every time; MSAL returns the cached one or refreshes it. var result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(); httpClient.DefaultRequestHeaders.Authorization = new("Bearer", result.AccessToken);