Mensagem de erro
IDX10223: Lifetime validation failed. The token is expired.
Também aparece como
- 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.
O texto depois de “The token is expired.” contém os dois carimbos de data/hora no formato da cultura do servidor. A descrição no `WWW-Authenticate` do ASP.NET Core é gerada pelo `JwtBearerHandler`.
Microsoft.IdentityModel.Tokens (.NET) — SecurityTokenExpiredException
O que significa
O `exp` do token é anterior à hora atual menos o `ClockSkew` (cinco minutos por padrão). A assinatura e as outras claims podem ser válidas; o token simplesmente passou do tempo de vida. A mensagem continua com “ValidTo (UTC): …, Current time (UTC): …”, e o ASP.NET Core informa `error_description="The token expired at '…'"` ao cliente. O IDX10222 é o caso oposto: o `nbf` está no futuro.
Por que acontece
O tempo de vida do token acabou
comumTokens de acesso do Entra ID duram de 60 a 90 minutos por padrão; em outros provedores, muitas vezes de 5 a 15 minutos. Um cliente que continua usando o mesmo token depois do `exp` falha exatamente no horário.
Diferença de relógio acima da tolerância
ocasionalCom um `ClockSkew` reduzido (por exemplo, `TimeSpan.Zero`, um valor muito copiado e colado), mesmo alguns segundos de diferença entre os relógios do emissor e da API fazem tokens recém-emitidos serem rejeitados.
Um token em cache fora da biblioteca de tokens
ocasionalTokens guardados em um banco de dados, em um campo estático ou em um arquivo de configuração nunca são atualizados. O MSAL e bibliotecas semelhantes atualizam os tokens automaticamente, se você deixar.
Como corrigir
- 1.
Manter uma tolerância de relógio pequena
Tolere diferenças de segundos, não de minutos, e corrija os relógios. Nunca defina `ValidateLifetime = false` em produção.
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.
Obter os tokens pela biblioteca a cada chamada
O `AcquireTokenSilent` retorna um token válido do cache ou o atualiza, então a expiração é tratada antes da requisição.
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);