diff --git a/.changeset/curly-carrots-invite.md b/.changeset/curly-carrots-invite.md new file mode 100644 index 00000000000..f842b4c6b38 --- /dev/null +++ b/.changeset/curly-carrots-invite.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Only refresh signIn and signUp resources during an SSO callback if the authentication was performed via a popup. diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 23b07d02abb..4b62ea82d3d 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -112,7 +112,13 @@ import { memoizeListenerCallback } from '../utils/memoizeStateListenerCallback'; import { RedirectUrls } from '../utils/redirectUrls'; import { AuthCookieService } from './auth/AuthCookieService'; import { CaptchaHeartbeat } from './auth/CaptchaHeartbeat'; -import { CLERK_SATELLITE_URL, CLERK_SUFFIXED_COOKIES, CLERK_SYNCED, ERROR_CODES } from './constants'; +import { + CLERK_SATELLITE_URL, + CLERK_SUFFIXED_COOKIES, + CLERK_SYNCED, + ERROR_CODES, + SESSION_STORAGE_AUTH_WITH_POPUP_KEY, +} from './constants'; import { clerkErrorInitFailed, clerkInvalidSignInUrlFormat, @@ -1507,11 +1513,23 @@ export class Clerk implements ClerkInterface { return; } + let shouldRefreshResources = false; + try { + const hasCalledAuthWithPopup = sessionStorage.getItem(SESSION_STORAGE_AUTH_WITH_POPUP_KEY); + if (hasCalledAuthWithPopup) { + shouldRefreshResources = true; + } + } catch { + // In the event that sessionStorage is disabled, assume the resource needs to be refreshed. Refreshing when not + // needed doesn't break anything, but it does cause 405 network errors. + shouldRefreshResources = true; + } + // If `handleRedirectCallback` is called on a window without an opener property (such as when the OAuth flow popup // directs the opening page to navigate to the /sso-callback route), we need to reload the signIn and signUp resources // to ensure that we have the latest state. This operation can fail when we try reloading a resource that doesn't // exist (such as when reloading a signIn resource during a signUp attempt), but this can be safely ignored. - if (!window.opener) { + if (!window.opener && shouldRefreshResources) { try { await signIn.reload(); } catch { diff --git a/packages/clerk-js/src/core/constants.ts b/packages/clerk-js/src/core/constants.ts index 347b6263b9f..53398f1e782 100644 --- a/packages/clerk-js/src/core/constants.ts +++ b/packages/clerk-js/src/core/constants.ts @@ -51,3 +51,5 @@ export const SIGN_UP_MODES: Record = { // This is the currently supported version of the Frontend API export const SUPPORTED_FAPI_VERSION = '2024-10-01'; + +export const SESSION_STORAGE_AUTH_WITH_POPUP_KEY = 'hasUsedAuthenticateWithPopup'; diff --git a/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx b/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx index 5a3754a9db1..e0d8ab76e50 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx @@ -1,6 +1,7 @@ import { useClerk } from '@clerk/shared/react'; import React from 'react'; +import { SESSION_STORAGE_AUTH_WITH_POPUP_KEY } from '../../../core/constants'; import { buildSSOCallbackURL } from '../../common/redirects'; import { useCoreSignIn, useSignInContext } from '../../contexts'; import { useEnvironment } from '../../contexts/EnvironmentContext'; @@ -38,6 +39,12 @@ export const SignInSocialButtons = React.memo((props: SocialButtonsProps) => { } }, 500); + try { + window.sessionStorage.setItem(SESSION_STORAGE_AUTH_WITH_POPUP_KEY, 'true'); + } catch { + // It's okay if sessionStorage is disabled since we will treat the failure to read the value as it being true. + } + return signIn .authenticateWithPopup({ strategy, redirectUrl, redirectUrlComplete, popup }) .catch(err => handleError(err, [], card.setError)); diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx index 2eaa170f5eb..4333ec0e457 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx @@ -2,6 +2,7 @@ import { useClerk } from '@clerk/shared/react'; import type { OAuthStrategy } from '@clerk/types'; import React from 'react'; +import { SESSION_STORAGE_AUTH_WITH_POPUP_KEY } from '../../../core/constants'; import { useCoreSignUp, useSignUpContext } from '../../contexts'; import { useCardState } from '../../elements'; import type { SocialButtonsProps } from '../../elements/SocialButtons'; @@ -39,6 +40,12 @@ export const SignUpSocialButtons = React.memo((props: SignUpSocialButtonsProps) } }, 500); + try { + window.sessionStorage.setItem(SESSION_STORAGE_AUTH_WITH_POPUP_KEY, 'true'); + } catch { + // It's okay if sessionStorage is disabled since we will treat the failure to read the value as it being true. + } + return signUp .authenticateWithPopup({ strategy,