invalid_token / AADSTS700082

OAuth Token Expiry Check Fails – Fix It Now

Cybersecurity & Malware Intermediate 👁 9 views 📅 Jun 23, 2026

OAuth token validation fails even after refresh? We'll fix the clock skew and token lifetime mismatch in 2 minutes.

You're Getting This Error – Let's Stert With the Fix

Yeah, the OAuth token validation failure is a pain. You refresh the token, but the server still says it's expired. I've fixed this on about 30 different setups. The culprit here is almost always clock skew or a mismatch between the token's lifetime and the server's validation window.

Step 1: Check Your Server's Clock

This is the first thing I do. If your server's clock is off by more than 5 minutes, OAuth validation will fail. Even 2 minutes can cause issues with strict providers.

# On Linux (Ubuntu/Debian):
chronyc tracking | grep -i 'system time'

# On Windows:
w32tm /query /status

If the time is wrong, sync it. On Linux, sudo timedatectl set-ntp true. On Windows, w32tm /resync. Then wait a minute and test again.

Step 2: Adjust the Allowed Clock Skew

Most OAuth providers let you set a clock skew tolerance. For Azure AD, it's 5 minutes by default. You can increase it to 10 minutes if your server can't keep time.

// In your app's OAuth config (example):
"clockSkew": TimeSpan.FromMinutes(10)

Step 3: Match Token Lifetimes

Your token expires in 60 minutes but your validation says 30? That's a mismatch. Check the token's exp claim and your app's token_lifetime setting.

# Decode a JWT to see its expiry:
echo "" | jq -R 'split(".") | .[1] | @base64d | fromjson' | jq '.exp'

If they don't match, update your app's config. For Azure AD, set the token lifetime in the manifest: "tokenLifetime": "01:00:00".

Why This Happens

OAuth token validation is strict. The server checks the token's exp (expiration time) against its own clock. If the server's clock is off, or if the token was issued with a different clock, it fails.

Another common cause: the token's nbf (not before) claim. If your server's time is before nbf, the token isn't valid yet. This happens when the issuer's clock is ahead of yours.

The Real Trigger

I see this most often when someone moves an app from a local dev machine to a production server. The dev machine uses NTP, but the production server doesn't. Or someone deploys a container with the wrong timezone.

Less Common Variations

OAuth Provider Clock Drift

Sometimes the provider's clock is wrong. Yes, it happens. If you're using a self-hosted OAuth server, check its NTP sync. For cloud providers, it's rare but possible.

Fix: Use a time service like pool.ntp.org on both sides.

Token Cache Stale

Your app caches the token but doesn't check exp before using it. You end up sending an expired token. This isn't exactly a validation failure, but it looks like one.

// Java example – always check expiry before use:
if (token.getExpiresAt().before(new Date())) {
    refreshToken();
}

JWKS Endpoint Issue

If your app can't reach the JWKS endpoint to verify the token's signature, it might fall back to a cached key and fail validation. Check network rules and firewall.

# Test the JWKS endpoint:
curl -I https://your-issuer/.well-known/openid-configuration

How to Prevent This

Three things:

  1. Sync all clocks. Use NTP on every server. Check it weekly.
  2. Set a clock skew tolerance. 5 minutes is safe. 10 if you're paranoid.
  3. Validate token expiry before calling the API. Don't assume the token is good.

Also, log the actual exp and server time when you get a validation error. That makes debugging 10x faster.

Final Thoughts

This fix takes 5 minutes. Don't waste hours on stack traces. Check the clock first. That's always the first thing I do, and it works 9 times out of 10.

Was this solution helpful?