Secrets and encoding

JWT expired but ASP.NET Core still accepts it

A JWT’s exp claim and a server’s token-acceptance policy are separate. Microsoft IdentityModel exposes ClockSkew as a validation tolerance, with a documented default of five minutes. Inspect the effective server configuration before concluding that lifetime validation is broken.

A JWT contains a header, payload and signature; reading claims does not verify the signature.
Decoded timestamps are diagnostic evidence, not proof that the server validated this token.

Separate the claim from the validation window

Use a synthetic token for investigation. Read exp with JWT Decoder, then convert its seconds value with Unix Timestamp Converter. Check the server’s UTC clock as well as the browser’s time.

For a token whose exp maps to 12:00:00 UTC, a five-minute tolerance can allow lifetime validation shortly after noon. This example describes lifetime tolerance alone: signature, issuer, audience, algorithm and application policy must still succeed.

Illustrative lifetime-validation timeline
Server UTCexpInterpretation with a five-minute tolerance
11:59:0012:00:00Before expiry
12:02:0012:00:00Within the configured tolerance
12:06:0012:00:00Beyond the tolerance; lifetime should fail

Inspect the actual authentication scheme

The following fragment targets ASP.NET Core JwtBearer options backed by Microsoft.IdentityModel.Tokens.TokenValidationParameters. It is a configuration example, not a complete authentication setup. Keep your existing signing-key, issuer and audience configuration.

If the business requirement needs zero tolerance, explicitly set ClockSkew to TimeSpan.Zero and keep ValidateLifetime enabled. First confirm synchronized clocks and test the consequences for clients. Do not disable lifetime validation to make an expired token appear to work.

// Inside the AddJwtBearer options callback:
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
// Retain the configured signing keys, issuer and audience validation.

Test the validation path rather than just the decoder

Check which authentication scheme protects the endpoint. A cookie session, cached authorization result, refresh flow, custom lifetime validator or unprotected route can make a request succeed for reasons unrelated to this token’s exp. Confirm which token was actually sent without logging its full value.

In an integration test using a dedicated test signing key, issue tokens expiring clearly before, inside and beyond the chosen tolerance. Freeze or control time where the framework permits. Assert the protected endpoint’s status and authentication outcome, not merely the decoded JSON.

A local integration check for this guide used .NET 10, Microsoft.AspNetCore.Authentication.JwtBearer 10.0.12 and Microsoft.IdentityModel.Tokens 8.19.2. A protected endpoint accepted a test token expired by two minutes with default skew, rejected the same expiry with zero skew, rejected a token expired by six minutes with default skew, and accepted a future-expiring token with zero skew.

Those results verify the stated lifetime behavior for that test configuration, not your deployed authentication pipeline. Record your own installed versions and protected-endpoint outcomes. Your server remains responsible for cryptographic verification and authorization.

Local integration results, synthetic HS256 tokens
Expiry relative to requestClockSkewProtected endpoint
−2 minutesDefault 5 minutesHTTP 200
−2 minutesZeroHTTP 401
−6 minutesDefault 5 minutesHTTP 401
+2 minutesZeroHTTP 200

References

Use the linked specifications and product documentation to check behavior in your own environment.

Continue troubleshooting

Related tools

Frequently asked questions

Does a decoded exp prove server rejection?

No. The server applies its configured validation policy to the actual request.

Should I disable lifetime validation?

No. Keep lifetime validation enabled and choose an intentional clock-tolerance policy.

Can PageUtil verify my signing key?

No. PageUtil reads token segments locally and does not verify their signature.

Need help with a tool or found a bug?

Report an issue directly to engineering. No accounts required — all client data remains private on your device.

Report an Issue →