0%

OAuth2/OIDC Session Timeout Boundaries: Frontend Tokens, Refresh Tokens, and SSO Sessions

🌐 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 code determines how long the authorization code remains valid
  • access token determines how long the current token can still invoke APIs
  • refresh token determines 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:

  1. User is actively using the frontend application
  2. After some time, the frontend prompts that the session has expired
  3. User clicks to re-login
  4. Browser redirects to the authorization server, but the login page doesn’t appear
  5. After authorization completes, the user is directly returned to the system

This phenomenon typically indicates that both of the following are true:

  • The access token held 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 JSESSIONID type 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// When signing token, write sid into claim together
const sid = randomSessionId();
await redis.set(`session:sid:${sid}`, "1", { EX: 43200 });

const accessToken = signJwt({
sub: userId,
sid,
exp: now + 900
});

// When validating token, simultaneously check whether sid still exists
async function validateAccessToken(token) {
const payload = verifyJwt(token);
const exists = await redis.exists(`session:sid:${payload.sid}`);

if (!exists) {
throw new Error("session revoked");
}

return payload;
}

// When logout or kicking people, delete sid
async function revokeSession(sid) {
await redis.del(`session:sid:${sid}`);
}

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 token still 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:

  1. First look at access token‘s exp
  2. Then look at whether frontend actually executed refresh token renewal
  3. Then confirm whether refresh token itself is still valid, whether it uses rotation
  4. Then look at whether authorization server’s browser session still exists
  5. 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 token to control API access risk
  • Use refresh token to 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.

Further Reading