diff --git a/app/scripts/services/oauth/oauth-service.ts b/app/scripts/services/oauth/oauth-service.ts index 52a2925a0049..c343d103e57c 100644 --- a/app/scripts/services/oauth/oauth-service.ts +++ b/app/scripts/services/oauth/oauth-service.ts @@ -1,6 +1,9 @@ import { AuthConnection } from '@metamask/seedless-onboarding-controller'; import log from 'loglevel'; -import { OAuthErrorMessages } from '../../../../shared/modules/error'; +import { + isUserCancelledLoginError, + OAuthErrorMessages, +} from '../../../../shared/modules/error'; import { checkForLastError } from '../../../../shared/modules/browser-runtime.utils'; import { TraceName, TraceOperation } from '../../../../shared/lib/trace'; import { BaseLoginHandler } from './base-login-handler'; @@ -204,12 +207,13 @@ export default class OAuthService { reject(error); } } else { - if (this.#isUserCancelledLoginError()) { - reject( - new Error(OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR), - ); + const userCancelledLoginError = + this.#getUserCancelledLoginError(); + if (userCancelledLoginError) { + reject(userCancelledLoginError); return; } + // Throw default error for no redirect URL found reject( new Error(OAuthErrorMessages.NO_REDIRECT_URL_FOUND_ERROR), ); @@ -357,9 +361,12 @@ export default class OAuthService { return url.searchParams.get('code'); } - #isUserCancelledLoginError(): boolean { + #getUserCancelledLoginError(): Error | undefined { const error = checkForLastError(); - return error?.message === OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR; + if (isUserCancelledLoginError(error)) { + return error; + } + return undefined; } async setMarketingConsent( diff --git a/shared/modules/error.ts b/shared/modules/error.ts index 10d28b2f148c..f86c18e90366 100644 --- a/shared/modules/error.ts +++ b/shared/modules/error.ts @@ -39,6 +39,9 @@ export enum OAuthErrorMessages { USER_CANCELLED_LOGIN_ERROR = 'The user did not approve access.', // TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860 // eslint-disable-next-line @typescript-eslint/naming-convention + USER_CANCELLED_LOGIN_ERROR_FIREFOX = 'User cancelled or denied access.', + // TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860 + // eslint-disable-next-line @typescript-eslint/naming-convention NO_REDIRECT_URL_FOUND_ERROR = 'No redirect URL found', // TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860 // eslint-disable-next-line @typescript-eslint/naming-convention @@ -47,3 +50,17 @@ export enum OAuthErrorMessages { // eslint-disable-next-line @typescript-eslint/naming-convention INVALID_OAUTH_STATE_ERROR = 'Invalid OAuth state', } + +/** + * Checks if the Web Authentication error is a user cancelled error. + * + * @param error - The error to check. + * @returns True if the error is a user cancelled login error, false otherwise. + */ +export function isUserCancelledLoginError(error: Error | undefined): boolean { + // NOTE: Firefox and chrome have different error messages for user cancelled the social login window. + return ( + error?.message === OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR || + error?.message === OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR_FIREFOX + ); +} diff --git a/ui/pages/onboarding-flow/welcome/welcome.js b/ui/pages/onboarding-flow/welcome/welcome.js index c4514d92c69b..f3b60fe11fd2 100644 --- a/ui/pages/onboarding-flow/welcome/welcome.js +++ b/ui/pages/onboarding-flow/welcome/welcome.js @@ -8,7 +8,6 @@ import React, { } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom-v5-compat'; -import log from 'loglevel'; import { Box } from '../../../components/component-library'; import { ONBOARDING_COMPLETION_ROUTE, @@ -41,7 +40,10 @@ import { import { getIsSeedlessOnboardingFeatureEnabled } from '../../../../shared/modules/environment'; import { getBrowserName } from '../../../../shared/modules/browser-runtime.utils'; import { PLATFORM_FIREFOX } from '../../../../shared/constants/app'; -import { OAuthErrorMessages } from '../../../../shared/modules/error'; +import { + isUserCancelledLoginError, + OAuthErrorMessages, +} from '../../../../shared/modules/error'; import { TraceName, TraceOperation } from '../../../../shared/lib/trace'; import { AlignItems, @@ -214,7 +216,7 @@ export default function OnboardingWelcome() { error instanceof Error ? error.message : 'Unknown error'; // Map raw OAuth error messages to UI modal-friendly constants - if (errorMessage === OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR) { + if (isUserCancelledLoginError(error)) { setLoginError(null); return; } @@ -354,9 +356,7 @@ export default function OnboardingWelcome() { ); const handleLoginError = useCallback((error) => { - log.error('handleLoginError::error', error); - const errorMessage = error.message; - if (errorMessage === OAuthErrorMessages.USER_CANCELLED_LOGIN_ERROR) { + if (isUserCancelledLoginError(error)) { setLoginError(null); } else { setLoginError(LOGIN_ERROR.GENERIC);