Skip to content

feat(profile-sync-controller): add getCachedBearerToken - #10283

Open
basgys wants to merge 4 commits into
MetaMask:mainfrom
basgys:feat/auth-cached-bearer-token
Open

basgys wants to merge 4 commits into
MetaMask:mainfrom
basgys:feat/auth-cached-bearer-token

Conversation

@basgys

@basgys basgys commented Sep 17, 2026

Copy link
Copy Markdown

Explanation

AuthenticationController:getBearerToken logs in when no valid session exists. Callers on hot paths therefore pay for a login, and wait on it: a nonce fetch, a snap signature, authenticate and authorizeOIDC, with no timeout. On a failing auth API every call retries, and a 429 makes each call sleep for Retry-After first.

This adds getCachedBearerToken(), a synchronous read of the token already in state. It never logs in. It returns undefined when the wallet is locked, when the SRP has no session, and when the token is past 90% of its lifetime, which is the point where getBearerToken replaces it. Refreshing stays with whichever caller next uses getBearerToken.

The caller this is for is #9927, which presents the token on requests to built-in Infura endpoints. There, a login per RPC request is not acceptable, and the async getter also forces a fetch wrapper just to inject the header. A synchronous getter removes both.

Open as a separate PR so it can be reviewed, and closed, on its own.

References

Follows from the Bugbot finding on #9927: #9927 (comment)

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

Note

Medium Risk
Changes how access tokens are read on authentication hot paths; mis-calling the sync getter vs async refresh could omit headers near expiry, though behavior is intentionally tied to existing 90% refresh rules.

Overview
Adds getCachedBearerToken() and the messenger action AuthenticationController:getCachedBearerToken so hot-path callers (e.g. per-RPC Infura requests) can read the OIDC access token synchronously from controller state without triggering login. It returns undefined when the wallet is locked, there is no SRP session, the session fails freshness checks, or canonicalProfileId is missing—the same conditions under which getBearerToken would refresh rather than reuse the cache.

Introduces shared helper isFreshLoginResponse (valid LoginResponse plus session age under 90% of expiresIn) and refactors SIWE/SRP #getAuthSession to use it instead of duplicated inline TTL logic, keeping the cached getter aligned with the JWT bearer flows.

Reviewed by Cursor Bugbot for commit 9a6220e. Bugbot is set up for automated code reviews on this repo. Configure here.

@basgys
basgys requested review from a team as code owners September 17, 2026 14:59

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit b40fa35. Configure here.

getBearerToken logs in when no valid session exists, so callers on hot
paths pay for a login and wait on it. getCachedBearerToken reads the
cached token synchronously and returns undefined instead of logging in.
Both auth flows inlined the 90% expiry rule. isFreshLoginResponse holds
it once, and getCachedBearerToken uses it so its checks match the SRP
flow, including the JWT exp check it previously skipped.
@basgys
basgys force-pushed the feat/auth-cached-bearer-token branch from 6720763 to 9a6220e Compare September 17, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant