.NET Core 2.0 Web API JWT Token过期异常技术求助
Hey there, let's tackle this tricky JWT expiration issue you're hitting—frustrating when everything else (token generation, normal auth flows) works fine! Let's break down the most likely causes and how to troubleshoot them step by step:
1. Token Generation & Validation Configuration Mismatches
First, double-check your backend setup—small oversights here often cause expiration headaches:
- Always use UTC time for token expiry: Azure App Service servers run on UTC, so if you generate tokens with
DateTime.Nowinstead ofDateTime.UtcNow, you'll end up with timezone mismatches. Verify your token creation code looks like this:var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], expires: DateTime.UtcNow.AddMinutes(30), // Critical: Use UtcNow, not Now! signingCredentials: credentials); - Check
ClockSkewin validation settings: TheTokenValidationParametersinclude aClockSkewvalue (default 5 minutes in .NET Core 2.0) that accounts for time differences between client and server. If your token has a very short lifespan (e.g., 1 minute), or if there's a larger time drift, adjust this value explicitly in yourStartup.cs:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])), ClockSkew = TimeSpan.FromMinutes(1) // Adjust based on your needs }; }); - Confirm
ValidateLifetimeis enabled: It's enabled by default, but if someone disabled it accidentally, you might see inconsistent expiration behavior.
2. Client-Side Token Handling & Renewal
Your Angular 5 app might be holding onto expired tokens or failing to renew them properly:
- Check token storage & expiration checks: Use a library like
jwt-decodeto validate the token's expiry before sending requests. Add this logic to your HTTP interceptor to avoid sending expired tokens:import * as jwt_decode from 'jwt-decode'; private isTokenExpired(token: string): boolean { const decodedToken = jwt_decode(token); const expiryDate = new Date(0); expiryDate.setUTCSeconds(decodedToken.exp); return expiryDate < new Date(); } - Implement token refresh logic: If your tokens have a short lifespan, make sure your client calls a refresh endpoint before the token expires to get a new valid token. Don't wait until the token is already expired to refresh.
3. Azure App Service Environment Quirks
Azure's platform can introduce unexpected behavior related to time or authentication:
- Verify server time zone: Azure App Service uses UTC by default, but if you've set a custom
WEBSITE_TIME_ZONEapp setting, it might cause mismatches with your UTC-generated tokens. Stick to UTC for token logic to avoid this. - Check for Easy Auth conflicts: If you've enabled App Service Authentication (Easy Auth) alongside your custom JWT setup, it might intercept requests and interfere with your token validation. Disable Easy Auth temporarily to test if this resolves the issue.
- Dig into detailed logs: Enable Application Logging in your App Service settings, then check the logs for specific exception details (e.g.,
SecurityTokenExpiredExceptionor "Clock skew exceeded"). The exact error message will point you directly to the root cause.
4. JWT Middleware Version Considerations
You're using AspnetCore.Authentication.JWTBearer 2.0.1, which is the initial release for .NET Core 2.0. There were minor bug fixes in later patch versions (like 2.0.9) related to token validation and expiration. Try upgrading to the latest patch in the 2.0.x line (avoid jumping to newer major versions unless you're ready to upgrade .NET Core) to rule out known bugs.
Start with verifying your token generation uses UTC time and checking the ClockSkew setting—these are the most common fixes for this scenario. If that doesn't work, dive into client-side logic and Azure logs for more clues.
内容的提问来源于stack exchange,提问作者Yanick Tourn

