handleRedirectCallback is not idempotent: SSO callback runs twice and the second signUp.create({ transfer: true }) fails with "There is no account to transfer"
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- next.js, react, typescript
- Ambito
- authentication, backend-api-design
Direzione di ricerca
Start with the three named entry points: packages/ui/src/common/SSOCallback.tsx, packages/clerk-js/src/core/clerk.ts, and packages/react/src/isomorphicClerk.ts. Trace the callback effect and redirect handling, then locate tests for these paths and reproduce the duplicate call behavior. Done means repeated handling of one OAuth return does not create duplicate transfers and callback rejections reach the caller.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Preliminary Checks
- I have reviewed the documentation: https://clerk.com/docs
- I have searched for existing issues: https://github.com/clerk/javascript/issues
- I have not already reached out to Clerk support via email or Discord (if you have, no need to open an issue here)
- This issue is not a question, general help request, or anything other than a bug report directly related to Clerk. Please ask questions in our Discord community: https://clerk.com/discord.
Reproduction
Source-level, see Description. No minimal repro: the double mount happens in real Chrome and Firefox but never in headless Chromium.
Publishable key
N/A
Description
After going from @clerk/nextjs 7.7.9 to 7.9.17, new users signing up with Google via the prebuilt <SignIn> started failing with "There is no account to transfer". Same clerk-js (6.39.0) before and after. Before: every new-user OAuth return sent one transfer. After: most sent two, and the second one failed.
Steps to reproduce:
- Prebuilt
<SignIn>on a path-routed page, Google OAuth on, legal consent required - Continue with Google using a Google account that has no Clerk user
- Finish Google consent, land on /sign-in/sso-callback
Expected behavior:
One POST /v1/client/sign_ups?transfer=true, then the legal consent step.
Actual behavior:
Two POST /v1/client/sign_ups?transfer=true, 4 to 200 ms apart. The first creates the sign-up (missing_requirements). The second fails with account_transfer_invalid and the user is sent back to sign-in. Once both succeeded and left two half done sign-ups.
The SignIn tree mounts twice. On a plain /sign-in load in real Chrome, useAutoFillPasskey sends two identical POST /v1/client/sign_ins in the same ms with different ids:
https://github.com/clerk/javascript/blob/6857df6841fb044f88e69f978917d8b8e8040d67/packages/ui/src/components/SignIn/SignInStart.tsx#L60
So SSOCallback calls handleRedirectCallback twice. Nothing stops the second call:
- SSOCallback runs it from a useEffect with no once guard, the cleanup only hides the error: https://github.com/clerk/javascript/blob/6857df6841fb044f88e69f978917d8b8e8040d67/packages/ui/src/common/SSOCallback.tsx#L28-L52
- _handleRedirectCallback has no in-flight dedupe, both calls see "transferable" and both call signUp.create({ transfer: true }): https://github.com/clerk/javascript/blob/6857df6841fb044f88e69f978917d8b8e8040d67/packages/clerk-js/src/core/clerk.ts#L2853-L2860
- IsomorphicClerk.handleRedirectCallback swallows the rejection, so a custom callback page using useClerk() can't see the failure. The comment there already names the fix ("making handleRedirectCallback idempotent"): https://github.com/clerk/javascript/blob/6857df6841fb044f88e69f978917d8b8e8040d67/packages/react/src/isomorphicClerk.ts#L1636-L1650
Workaround: own sso-callback page that calls window.Clerk.handleRedirectCallback once per callback URL per page load.
Ask:
- Make handleRedirectCallback idempotent per OAuth return (or dedupe in-flight calls)
- Let IsomorphicClerk pass the rejection through
Environment
@clerk/nextjs 7.9.17, @clerk/react 6.17.8, @clerk/shared 4.40.0, clerk-js 6.39.0 to 6.41.0, @clerk/ui 1.42.0, next 16.4.1, react 19.2.8, Chrome and Firefox (current stable)
- Lingua principale
- TypeScript
- Stelle
- 1.8k
- Fork
- 483
- Merge medio
- 1g 20h
- PR unite (30g)
- 363
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di clerk/javascript
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
clerk/javascript#10548 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
clerk/javascript#10547 ·
I maintainer di solito rispondono entro 1 giorno
-
<SignIn />: first "Use email" click switches back to phone when `initialValues.phoneNumber` is setForse già presa @twicestruck l’ha presa 3 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
clerk/javascript#10487 ·
I maintainer di solito rispondono entro 1 giorno
-
useLoadedIsomorphicClerk misses "ready" when a ClerkProvider remounts after clerk-js has loaded — <ClerkLoading> never resolvesForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
clerk/javascript#10462 ·
I maintainer di solito rispondono entro 1 giorno
-
ClerkAPIError drops meta.lockout_expires_in_seconds from user_locked errorsForse già presa @umeraamir69 l’ha presa 9 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
clerk/javascript#10026 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di clerk/javascript
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
Northeastern-Electric-Racing/FinishLine#4660 ·
I maintainer di solito rispondono entro 2 giorni
-
BeOS .json missingAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
mihaip/infinite-mac#475 ·
-
Let TypeScript accept an initial object in ReactiveDictForse già presa @yograj-vijay-yadav l’ha presa oggi. Apertabug good first issue help wanted workshop
Difficoltà 2/5 1-3 ore Idoneità per principianti 92/100
meteor/meteor#14919 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
marmelab/atomic-crm#401 ·
I maintainer di solito rispondono entro 1 giorno
-
account: profile
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 5 giorni