fix(client): handle missing access token + delayed autoRefresh timer #1

Open
mohiit1502 wants to merge 6 commits from fix/token-refresh-lifecycle into main
Owner

Problem

Three bugs caused hourly logouts in NebulaOS:

  1. getAccessToken() returned null when access token was absent — even if a valid refresh token existed, it bailed immediately instead of attempting a silent refresh.

  2. setupAutoRefresh() silently exited when delay <= 0 — when a browser tab was backgrounded and the system timer was throttled/skipped, the proactive refresh window was missed with no recovery.

  3. init() guard blocked recovery calls — once _initialized=true, calling init() again (e.g. from a 401 handler) returned isAuthenticated() directly without attempting a refresh on expired sessions.

Fixes

  • getAccessToken(): when access token is absent, check for refresh token and attempt refreshToken() before returning null
  • setupAutoRefresh(): when delay <= 0, call refreshToken() immediately and re-schedule
  • init(): when already initialized but session is expired, attempt silent refresh instead of returning false
  • Added [IAMClient] debug logs to all key lifecycle events

Impact

These bugs meant that once an access token expired (1hr TTL), NebulaOS would redirect to /login even though the IAM server session and refresh token were still valid.

## Problem Three bugs caused hourly logouts in NebulaOS: 1. **`getAccessToken()` returned null when access token was absent** — even if a valid refresh token existed, it bailed immediately instead of attempting a silent refresh. 2. **`setupAutoRefresh()` silently exited when `delay <= 0`** — when a browser tab was backgrounded and the system timer was throttled/skipped, the proactive refresh window was missed with no recovery. 3. **`init()` guard blocked recovery calls** — once `_initialized=true`, calling `init()` again (e.g. from a 401 handler) returned `isAuthenticated()` directly without attempting a refresh on expired sessions. ## Fixes - `getAccessToken()`: when access token is absent, check for refresh token and attempt `refreshToken()` before returning null - `setupAutoRefresh()`: when `delay <= 0`, call `refreshToken()` immediately and re-schedule - `init()`: when already initialized but session is expired, attempt silent refresh instead of returning false - Added `[IAMClient]` debug logs to all key lifecycle events ## Impact These bugs meant that once an access token expired (1hr TTL), NebulaOS would redirect to /login even though the IAM server session and refresh token were still valid.
mohiit1502 added 1 commit 2026-05-03 19:03:22 +05:30
fix(client): handle missing access token + delayed autoRefresh timer
Some checks failed
Stuffle/iam-client-sdk/pipeline/head There was a failure building this commit
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
cf787e3b4c
- getAccessToken(): attempt refreshToken() when access token is absent
  but refresh token exists (previously returned null immediately)
- setupAutoRefresh(): when delay <= 0 (background tab woke up after
  timer window), refresh immediately instead of silently exiting
- init(): when _initialized=true but session is expired, attempt
  silent refresh instead of returning false immediately
- Add [IAMClient] debug logging to all key lifecycle points
mohiit1502 added 1 commit 2026-05-03 19:18:41 +05:30
test: add headless integration test suite for refreshToken() lifecycle
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
3c9bc6e57c
mohiit1502 added 1 commit 2026-05-03 20:11:41 +05:30
fix(client): respect server grant_types_supported for refresh; fix test token rotation
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
7e9faa551c
- refreshToken(): check discovery.grant_types_supported includes 'refresh_token'
  before attempting — respects IAM control-plane toggle (DB config)
- setupAutoRefresh(): guard on autoRefresh config flag (was missing)
- OIDCDiscovery.grant_types_supported: made optional (some OIDC servers omit it)
- Tests: redesign real-IAM suite to share one client+storage across sequential
  tests (handles refresh token rotation — each token is single-use)
- Tests: remove beforeEach storage clear (tests manage their own state)
mohiit1502 added 1 commit 2026-05-04 00:20:20 +05:30
chore: bump to 0.1.3, fix @vitest/coverage-v8 peer dep conflict
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
47926656d7
mohiit1502 added 1 commit 2026-05-04 00:45:31 +05:30
fix(ci): write NPM_TOKEN to ~/.npmrc in publish.sh for CI authentication
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
6c0561f693
mohiit1502 added 1 commit 2026-05-04 02:54:18 +05:30
chore: bump to 0.1.5 (published)
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
e1625e6a04
Some checks failed
Stuffle/iam-client-sdk/pipeline/pr-main There was a failure building this commit
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/token-refresh-lifecycle:fix/token-refresh-lifecycle
git checkout fix/token-refresh-lifecycle
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Restruct-Corporate-Advantage/iam-client-sdk#1