Skip to content

fix(oauth): add RefreshTokenHttpError and guard refreshAuthTokens in MaxKeyChainLength recovery#26258

Merged
himanshuchawla009 merged 10 commits into
mainfrom
fix/refresh-token-http-error
Feb 25, 2026
Merged

fix(oauth): add RefreshTokenHttpError and guard refreshAuthTokens in MaxKeyChainLength recovery#26258
himanshuchawla009 merged 10 commits into
mainfrom
fix/refresh-token-http-error

Conversation

@himanshuchawla009

@himanshuchawla009 himanshuchawla009 commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Explanation

Companion to MetaMask/core#7989.

1. RefreshTokenHttpError in AuthTokenHandler

The core SeedlessOnboardingController now distinguishes permanent token failures (401) from transient ones to apply the right recovery strategy. It does this by checking whether the error thrown by refreshJWTToken is a RefreshTokenHttpError with statusCode === 401.

Previously AuthTokenHandler threw a plain Error('Failed to refresh JWT token') for all non-2xx responses, making this distinction impossible. This PR adds a RefreshTokenHttpError class that carries the HTTP statusCode, giving the controller the information it needs

2. try/catch around refreshAuthTokens in the MaxKeyChainLengthExceeded recovery path

refreshAuthTokens is called fire-and-forget in the MaxKeyChainLengthExceeded recovery path before rehydrateSeedPhrase. If the refresh token is already stale or revoked (which is precisely the scenario that triggers this path), the call would throw and abort rehydration entirely — leaving the user stuck.

Wrapping in try/catch logs the error and lets rehydration proceed regardless.

3. encryptorAdapter for SeedlessOnboardingController

KeyringController has a generic EncryptionResult type that accepts our mobile Encryptor's cipher property. However, SeedlessOnboardingController uses a fixed VaultEncryptor type (from ExportableKeyEncryptor) that strictly requires data instead of cipher.

Changelog

CHANGELOG entry: null

References

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 manually tested the PR (required)

Note

Medium Risk
Touches OAuth token refresh and seedless recovery flows; incorrect error typing/handling could change recovery behavior for revoked or transient refresh-token failures.

Overview
Improves seedless OAuth token-refresh error handling so callers can distinguish auth-server HTTP failures by status code.

AuthTokenHandler.refreshJWTToken now throws RefreshTokenHttpError (includes statusCode) on non-2xx responses, and the MaxKeyChainLengthExceeded recovery path in Authentication.syncPasswordAndUnlockWallet wraps SeedlessOnboardingController.refreshAuthTokens() in a try/catch to log and continue with rehydrateSeedPhrase instead of aborting recovery.

Written by Cursor Bugbot for commit 413b327. This will update automatically on new commits. Configure here.

…MaxKeyChainLength recovery

Companion to MetaMask/core#7989.

- Add `RefreshTokenHttpError` class to `AuthTokenHandler` that carries the
  HTTP `statusCode`, enabling callers to distinguish permanent (401) from
  transient failures. The core controller duck-types this error shape to map
  401 responses to `InvalidRefreshToken` instead of the generic
  `FailedToRefreshJWTTokens`.

- Wrap `SeedlessOnboardingController.refreshAuthTokens()` in a try/catch in
  the `MaxKeyChainLengthExceeded` recovery path. A stale or revoked refresh
  token should not abort rehydration — the error is logged and execution
  continues to `rehydrateSeedPhrase`.
@himanshuchawla009 himanshuchawla009 requested a review from a team as a code owner February 19, 2026 07:57
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-onboarding Onboarding team label Feb 19, 2026
@himanshuchawla009 himanshuchawla009 marked this pull request as draft February 19, 2026 07:58

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

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.

super(message);
this.name = 'RefreshTokenHttpError';
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing Object.setPrototypeOf in custom Error subclass

Low Severity

RefreshTokenHttpError extends Error but omits the Object.setPrototypeOf(this, RefreshTokenHttpError.prototype) call that the project's own AuthenticationError class uses (with an explicit link to the TypeScript breaking-changes wiki). Without it, instanceof RefreshTokenHttpError checks can silently return false in transpiled environments, defeating the purpose of this typed error class. The whole point of introducing RefreshTokenHttpError is to let callers distinguish it from plain Error.

Fix in Cursor Fix in Web

Co-authored-by: Cursor <cursoragent@cursor.com>
@socket-security

socket-security Bot commented Feb 24, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​metamask/​seedless-onboarding-controller@​6.1.0 ⏵ 8.1.09910078 +196100

View full report

@socket-security

socket-security Bot commented Feb 24, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

Ignoring alerts on:

  • npm/@metamask/seedless-onboarding-controller@8.1.0

View full report

@github-actions github-actions Bot added size-M and removed size-S labels Feb 24, 2026
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeIdentity, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeTrade, SmokeWalletPlatform, SmokeCard, SmokePerps, SmokeRamps, SmokeMultiChainAPI, SmokePredictions, FlaskBuildTests
  • Selected Performance tags: @PerformanceAccountList, @PerformanceOnboarding, @PerformanceLogin, @PerformanceSwaps, @PerformanceLaunch, @PerformanceAssetLoading, @PerformancePredict, @PerformancePreps
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (controller-version-update): @MetaMask controller package version updated in package.json: @metamask/seedless-onboarding-controller. Running all tests.

Performance Test Selection:
Hard rule (controller-version-update): @MetaMask controller package version updated in package.json: @metamask/seedless-onboarding-controller. Running all tests.

View GitHub Actions results

@metamaskbot metamaskbot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Feb 25, 2026
@grvgoel81 grvgoel81 marked this pull request as ready for review February 25, 2026 03:08
@grvgoel81

Copy link
Copy Markdown
Contributor

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION

Action Severity Alert  (click "▶" to expand/collapse)
Block Medium
Network access: npm @metamask/seedless-onboarding-controller in module globalThis["fetch"]
Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/seedless-onboarding-controller@8.1.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review
the linked package source code to understand the potential risk. Ensure the
package is not malicious before proceeding. If you're unsure how to proceed,
reach out to your security team or ask the Socket team for help at
support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

_Mark the package as acceptable risk_. To ignore this alert only
in this pull request, reply with the comment
`@SocketSecurity ignore npm/@metamask/seedless-onboarding-controller@8.1.0`. You can
also ignore all packages with `@SocketSecurity ignore-all`.
To ignore an alert for all future pull requests, use Socket's Dashboard to
change the [triage state of this alert](https://socket.dev/dashboard/org/MetaMask/diff-scan/50d61b88-0749-4b4c-b8a3-6bea1311f8c3/alert/QjAme1AXxJn1Y-yruToXkjt8lnJ9ui4fvil0KiDKsLvA).

View full report

https://github.com/SocketSecurity ignore npm/@metamask/seedless-onboarding-controller@8.1.0

@metamask/seedless-onboarding-controller is used for social login onboarding and requires network access for interacting with Web3Auth servers and Toprf Operations.

@himanshuchawla009

Copy link
Copy Markdown
Contributor Author

@SocketSecurity ignore npm/@metamask/seedless-onboarding-controller@8.1.0

@metamask/seedless-onboarding-controller is used for social login onboarding and requires network access for interacting with Web3Auth servers and Toprf Operations.

@himanshuchawla009 himanshuchawla009 added this pull request to the merge queue Feb 25, 2026
Merged via the queue into main with commit dd3455c Feb 25, 2026
118 of 119 checks passed
@himanshuchawla009 himanshuchawla009 deleted the fix/refresh-token-http-error branch February 25, 2026 08:47
@github-actions github-actions Bot locked and limited conversation to collaborators Feb 25, 2026
@metamaskbot metamaskbot added the release-7.68.0 Issue or pull request that will be included in release 7.68.0 label Feb 25, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template release-7.68.0 Issue or pull request that will be included in release 7.68.0 size-M team-onboarding Onboarding team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants