How to identify if the OAuth token has expired?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Knowing whether an OAuth access token has expired is important for both security and user experience. If you wait until every protected API call fails, your application becomes noisy and unpredictable. If you refresh too early, you add unnecessary traffic and complexity.
The correct approach depends on the kind of token you have. Some access tokens are self-contained JWTs, while others are opaque strings that only the authorization server can interpret.
Start by Understanding the Token Type
A common mistake is assuming every OAuth token is a JWT. That is not guaranteed by OAuth. Many providers issue JWT access tokens, but others issue opaque tokens that look like random strings.
This distinction matters because:
- A JWT may contain an
expclaim that tells you when it expires - An opaque token does not expose expiration data locally
- Some providers support token introspection for opaque tokens
- Some client applications should simply handle a
401 Unauthorizedresponse and refresh
So the first question is not "how do I parse expiration?" It is "can this token be inspected safely on the client or server at all?"
Checking Expiration for JWT Access Tokens
If your provider issues JWTs, the token payload often contains the exp claim as a Unix timestamp. On a trusted backend, you should validate the token signature and then compare exp with the current time.
Here is a Python example using PyJWT:
If you only need to read the timestamp for client-side refresh scheduling, you might decode without signature verification, but that should never be treated as an authorization decision. An unverified payload is useful for UX hints, not for trust.
The extra buffer helps avoid race conditions where the token expires between the client check and the API request.
Handling Opaque Tokens
If the access token is opaque, you usually cannot determine expiration by inspecting the string. In that case, the usual options are:
- Track the expiry time returned during token issuance
- Call the provider’s introspection endpoint if supported
- Retry with a refresh token when the API returns
401
Many OAuth token responses include expires_in, which tells you how many seconds the access token remains valid. If you store the token issuance time, you can compute a local expiry deadline without decoding anything.
This is often the simplest and most reliable method for non-JWT tokens.
Using Introspection on the Server
Some providers implement RFC 7662 token introspection. Your backend sends the token to the authorization server, and the server responds with metadata such as whether the token is active and when it expires.
If the response says the token is inactive, treat it as expired or otherwise unusable. Introspection is especially useful when tokens can be revoked before their nominal expiry time.
The Most Practical Application Pattern
In production systems, a good strategy usually combines proactive and reactive checks:
- Store the expiry time when the token is issued.
- Refresh slightly before expiration, not exactly at the last second.
- Still handle
401 Unauthorizedbecause clocks drift and tokens can be revoked. - Keep refresh logic on the backend when possible.
That last point is important. Refresh tokens and client secrets should not be exposed to untrusted frontends. Browser applications often rely on the identity provider’s SDK or a backend-for-frontend pattern to avoid handling sensitive token flows directly.
Common Pitfalls
The first pitfall is treating every OAuth token as a JWT. If the token is opaque, local decoding will not tell you anything meaningful.
Another mistake is trusting an unverified JWT payload on the server. You can read exp without verification for convenience, but only signature-verified claims should influence security decisions.
Clock skew is also easy to miss. A token that looks valid on one machine may already be expired on another. Add a safety margin before expiry instead of using the exact timestamp as a hard edge.
Finally, do not assume expiration is the only reason a token stops working. Revocation, audience mismatch, missing scopes, or issuer changes can all produce failures that look similar at the API boundary.
Summary
- The right expiration check depends on whether the access token is a JWT or an opaque token.
- For JWTs, validate the token and compare the
expclaim to the current time. - For opaque tokens, rely on
expires_in, token introspection, or401handling. - Add a refresh buffer to avoid race conditions near the expiration boundary.
- Expiration checks improve reliability, but API error handling is still required in real systems.
Related reading
- How to implement a high performance asynchronous socket server application in PHP?
- How to implement an asynchronous REST request to a controller using Springboot?
- How to implement authorization using a Telegram API?
- how to implement outbox like pattern with third party api
- How to ignore SSL certificate errors in Apache HttpClient 4.0
- How to implement a customized principal builder in Kafka and use it for authorization using ACLs?
- How to implement REST token-based authentication with JAX-RS and Jersey
- How to install Kubernetes cluster behind proxy with Kubeadm?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.