🌐 Language: English Version | 中文版
While troubleshooting a session timeout issue, we encountered a typical phenomenon: the frontend had already indicated session invalidation, but when users re-entered the authorization flow, they didn’t see the login page again and were directly returned to the system. Initially, the frontend and backend explanations were completely misaligned. Later, when we broke down the chain, we realized the problem wasn’t with a single configuration value, but that what everyone called “login state” wasn’t the same layer at all.
TL;DR
This article assumes readers are already familiar with basic OAuth2/OIDC flows, focusing on the timeout boundaries most prone to confusion in production environments.
The “login state” in OAuth2/OIDC typically isn’t a single time, but rather several types of times working together:
authorization codedetermines how long the authorization code remains validaccess tokendetermines how long the current token can still invoke APIsrefresh tokendetermines how long the application can silently renew- SSO browser session determines whether password re-entry is required when re-entering the authorization flow
- Server-side session identifier determines whether issued tokens can be actively revoked
When troubleshooting, examining these layers separately is more effective than repeatedly discussing a single TTL.
I. Where Problems Usually Occur
The phenomenon we observed was quite specific:
- User is actively using the frontend application
- After some time, the frontend prompts that the session has expired
- User clicks to re-login
- Browser redirects to the authorization server, but the login page doesn’t appear
- After authorization completes, the user is directly returned to the system
This phenomenon typically indicates that both of the following are true:
- The
access tokenheld locally by the frontend has expired, or has been determined by the frontend to be about to expire - The authorization server’s browser session is still valid, so the authorization server still recognizes this user
Therefore, the “re-login required” prompt from applications often just means “need to obtain a new set of tokens,” not equivalent to “user must re-enter username and password.”
If this distinction isn’t clarified first, troubleshooting can easily go astray.
II. First, Distinguish Protocol Layer from Engineering Layer
In the standard OAuth2/OIDC authorization code flow, there are only four core roles:
- User
- Client Application
- Authorization Server
- Resource Server
A simplified flow is as follows:
sequenceDiagram
participant User as User
participant Client as Client App
participant AS as Authorization Server
participant RS as Resource Server
User->>Client: Open app
Client->>AS: Redirect to /authorize
AS->>User: Login and authorize
AS-->>Client: Callback redirect_uri?code=...
Client->>AS: Exchange code for token
AS-->>Client: Return access token / refresh token
Client->>RS: Call API with access token
RS-->>Client: Return business data
The protocol layer mainly defines:
- How to initiate authorization
- How to exchange tokens
- How to validate tokens
But in production environments, systems typically overlay some engineering implementations:
- API Gateway uniformly handles token validation
- Authorization servers use browser sessions to maintain login memory
- Server-side introduces session identifiers to support immediate token invalidation after logout
- Frontends avoid boundary jitter by determining tokens as expired tens of seconds early
These mechanisms are all common, but they don’t belong to the same layer. Mixing protocol concepts with engineering strategies directly affects judgment of “login state.”
III. How We Initially Misdiagnosed
Such issues easily lead to a wrong direction first: modifying the access token TTL.
The reason isn’t complex. When the frontend prompts session invalidation, the most intuitive understanding is that the token is too short; and from the phenomenon, making it longer seems to alleviate the problem.
But this line of thinking typically only explains part of the表象, not these situations:
- Why no password re-entry is required when re-authorizing after token expiration
- Why some requests first receive
401, but the page doesn’t truly exit - Why after logout, certain old tokens can continue accessing for a short time
In other words, only modifying access token TTL can at most affect “how quickly the frontend perceives invalidation,” but cannot cover “whether silent renewal is still possible,” “whether password re-entry is still required,” “whether old tokens can be immediately invalidated.”
After separating these boundaries, subsequent phenomena become consistent.
IV. A More Practical Mental Model: Three-Layer Tickets
Understanding login state as three-layer tickets makes troubleshooting much simpler.
1. access token
This is the ticket directly presented when accessing the resource server.
- Typically has a short lifecycle
- Largest exposure surface
- Direct performance after expiration is API returning
401
2. refresh token
This is the ticket used by applications to exchange for new access tokens.
- Typically has a longer lifecycle than access token
- Should not appear frequently in business requests
- It determines whether the application can still renew silently
3. SSO Session
This layer is typically divided into two parts:
- Browser-side login session, such as
JSESSIONIDtype cookies - Server-side session identifier, used for governance capabilities like revocation, kick-out, single sign-out
These two parts often appear simultaneously, but have different responsibilities:
- Browser session determines whether password re-entry is required when re-entering
/authorize - Server-side session identifier determines whether issued tokens can still be accepted
V. Several Most Confusing Time Parameters
| Parameter | Layer | Performance After Expiration | Common Recommendations |
|---|---|---|---|
authorization_code TTL |
Authorization code | Fails to exchange code for token | Short, typically around 5 minutes |
access_token TTL |
API access token | API call failure or frontend determines invalidation | Short, typically 10 to 15 minutes |
refresh_token TTL |
Renewal token | Cannot renew silently, requires re-authorization | Medium to long, stratified by application risk |
| SSO browser session timeout | Authorization server login memory | Login page appears again during re-authorization | Consistent with platform session policy |
| Server-side session identifier TTL | Revocation and logout governance | Whether old tokens can be immediately intercepted | Consistent with session governance policy |
Frontend skewSeconds |
Local premature expiration judgment | Token determined as invalid slightly early | Keep small, e.g., 30 seconds |
5.1 authorization code
The authorization code is a one-time short-term credential, primarily used for the frontend callback to exchange with the authorization server for tokens. Its responsibility is very single and typically doesn’t participate in “long session” discussions.
Extending this time typically neither improves user experience nor expands the exposure window.
5.2 access token
This is the layer with the most obvious user perception.
- Time too short, frontend easily experiences frequent not-logged-in, API retries, boundary jitter
- Time too long, risk window after leakage significantly expands
For most backend systems, 10-15 minutes is often more balanced than a few minutes.
5.3 refresh token
Many demands like “7 days免登录” or “30 days continuous availability” should essentially be borne by refresh token, rather than directly extending access token to several days.
Short access token combined with longer refresh token is generally more stable than long-term access token.
5.4 SSO Browser Session
This layer determines: when users go through the authorization flow again, whether the authorization server still remembers that this browser has already logged in.
Thus this situation occurs:
- Application local token has already expired
- User re-initiates authorization
- Authorization server checks that browser session is still valid
- Thus directly issues new authorization result, user doesn’t need to re-enter password
This isn’t bypassing authentication, but rather normal SSO experience.
5.5 Server-side Session Identifier
Many production systems maintain a server-side session identifier outside of tokens, such as sid type claims or session keys. Its purpose isn’t to replace tokens, but to supplement “active revocation” capability.
Typical uses include:
- After user actively exits, old tokens immediately invalidate
- Administrator kicks out a certain session
- After password modification, force old sessions offline
- Same browser multiple tabs share one invalidation state
Without this layer mechanism, systems typically can only wait for token natural expiration.
If only discussing concepts, this layer still easily appears somewhat虚. Using a minimal implementation to illustrate is more direct:
1 | // When signing token, write sid into claim together |
The focus of this approach isn’t Redis itself, but adding a server-side handle for “active revocation.” Relying only on JWT’s exp, systems typically can only wait for it to naturally expire.
VI. Why Frontend and Backend Often Don’t Match
Login state issues are prone to debate because different roles observe different layers:
- Frontend focuses on whether local tokens are still available
- Gateway or resource server focuses on whether bearer token can pass validation
- Authorization server focuses on whether browser session still exists
- Security governance focuses on whether old sessions can be actively revoked
If these layers aren’t described separately, teams easily develop two seemingly contradictory but individually correct statements:
- “It’s obviously expired, why did it go straight in again?”
- “It’s obviously already exited, why can old tokens still call one more API?”
The first sentence usually says SSO browser session is still valid, the second sentence usually says server-side revocation chain didn’t catch.
VII. Long Sessions Don’t Mean Just Modifying One TTL
If an application wants to achieve “continuous availability for several days,” typically at least the following several things need to be simultaneously satisfied.
7.1 Frontend Actually Integrated Refresh Token Renewal
If frontend directly clears state and jumps back to login page once access token expires, then even if refresh token is configured to 7 days, experience won’t improve.
7.2 When Logging Out, Server-side Can Also Revoke Sessions
Only clearing frontend local storage isn’t enough. As long as old tokens are within validity period, they may continue to be accepted by gateway or resource server. This is particularly important in long session scenarios.
7.3 Sensitive Events Must Support Forced Invalidation
For example:
- Modify password
- User disabled
- Major permission changes
- Administrator kicks out session
These scenarios shouldn’t purely rely on natural expiration.
7.4 Long-term Refresh Token Best Uses Rotation Strategy
If refresh token can be repeatedly reused until natural expiration, once leaked, risk window will be very long.
Rotation strategy idea is: after each refresh, immediately invalidate old refresh token, and issue new refresh token. This is more suitable for long session scenarios.
VIII. A More Stable Time Configuration Strategy
Below is a set of common reference stratifications:
| Scenario | access token |
refresh token |
Browser Session |
|---|---|---|---|
| Ordinary backend system | 10-15m |
8-12h |
Half day or one work day |
| Low-risk long session application | 10-15m |
7d |
Evaluate according to login policy |
| Very few whitelist applications | 10-15m |
30d |
Must配套 revocation and risk control |
Here are two key points:
- Long experience优先 implemented through
refresh token access tokenstill remains short-term
If directly extending access token to several hours or days, impact surface after leakage significantly expands, and many systems themselves don’t have配套 immediate revocation capability.
IX. What Order to View When Troubleshooting
When encountering problems like “re-login,” “auto-renewal failure,” “still accessible after logout,” viewing in the following order is typically more efficient:
- First look at
access token‘sexp - Then look at whether frontend actually executed refresh token renewal
- Then confirm whether
refresh tokenitself is still valid, whether it uses rotation - Then look at whether authorization server’s browser session still exists
- Finally look at whether server-side revocation identifier is still valid, whether logout chain truly deleted it
This order can quickly distinguish:
- Is it API ticket expired
- Is it renewal chain not properly connected
- Or is SSO session still alive
- Or revocation governance not complete
X. A Sufficiently Practical Judgment Formula
If only keeping one sentence, can directly remember this set of boundaries:
- Whether can still call API, look at
access token - Whether can still silently renew, look at
refresh token - Whether still need to re-enter password, look at SSO browser session
- Whether can make old tokens immediately invalidate, look at server-side session revocation mechanism
After these boundaries are straightened out, many seemingly contradictory phenomena become very direct.
XI. Conclusion
OAuth2/OIDC itself isn’t complex, what’s truly confusing is production systems overlaying tokens, browser sessions, gateway validation, server-side revocation. Discussing these mechanisms collectively as one “login state,” conclusions easily go astray.
A more stable approach is typically:
- Use short-term
access tokento control API access risk - Use
refresh tokento provide continuous experience - Use browser session to carry SSO login memory
- Use server-side revocation mechanism to handle logout, kick-out, and forced offline
After these layer boundaries are clear, frontend, backend, and security sides will have much easier discussions when discussing timeout strategies.