Skip to content

fix(clerk-js): Bypass captcha on OAuth backport for Core 2#8734

Merged
jacekradko merged 1 commit into
release/core-2from
daniel/user-5459-backport-oauth-captcha-callback-fix-to-clerk-js-5x
Jun 3, 2026
Merged

fix(clerk-js): Bypass captcha on OAuth backport for Core 2#8734
jacekradko merged 1 commit into
release/core-2from
daniel/user-5459-backport-oauth-captcha-callback-fix-to-clerk-js-5x

Conversation

@dmoerner

@dmoerner dmoerner commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Description

Backport of the OAuth captcha bypass fix from #8030 to Core 2. shouldBypassCaptchaForAttempt bailed out early (therefore showing captcha) when params.strategy was unset, which is the case on an OAuth transfer to sign up (the strategy lives on the sign in verification). As a result a captcha was unconditionally requested for brand-new OAuth users. Normally this was a no-op, just wasting cycles to Cloudflare and then our backend would ignore captcha results for bypassed providers anyway. However, we got a report that it was producing a bug on Safari where the frontend would hang indefinitely on /sign-in/sso-callback.

The transfer bypass is now checked before any strategy-based early return, and the redundant strategy-injection block in create is removed. Enterprise SSO transfers still correctly show a captcha.

Only the captcha bypass fix is backported; the sign_up_if_missing feature from #8030 is intentionally excluded.

For discussion of the regression introduced in 2024, see https://clerkinc.slack.com/archives/C01KTTYKWBU/p1772566383559539.

Written by Claude under Daniel's supervision.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where new OAuth users could hang on the SSO callback during signup transitions. The system now properly bypasses captcha verification for pre-configured OAuth providers instead of showing an inaccessible captcha, providing a smoother user experience.

Backport of the OAuth captcha bypass fix from #8030 to clerk-js 5.x
(Core 2). `shouldBypassCaptchaForAttempt` bailed out early when
`params.strategy` was unset, which is the case on an OAuth transfer to
sign up (the strategy lives on the sign in verification). As a result a
captcha was unconditionally requested for brand-new OAuth users, who
could hang indefinitely on /sign-in/sso-callback.

The transfer bypass is now checked before any strategy-based early
return, and the redundant strategy-injection block in `create` is
removed. Enterprise SSO transfers still correctly show a captcha.

Only the captcha bypass fix is backported; the sign_up_if_missing
feature from #8030 is intentionally excluded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jun 3, 2026 3:37pm

Request Review

@changeset-bot

changeset-bot Bot commented Jun 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c47dac6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@clerk/clerk-js Patch
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR fixes OAuth users hanging on SSO callbacks during signup transfers by refactoring the captcha bypass logic. It removes a strategy-override condition from create(), updates shouldBypassCaptchaForAttempt() to properly gate OAuth bypass checks, adds test coverage validating correct bypass behavior, and documents the fix in a changeset.

Changes

OAuth Captcha Bypass Fix

Layer / File(s) Summary
Core bypass logic refactor
packages/clerk-js/src/core/resources/SignUp.ts
Removes strategy override from create() when transfer: true and captcha bypass apply. Updates shouldBypassCaptchaForAttempt() to load captcha-OAuth bypass config earlier, gate OAuth bypass behind explicit params.strategy presence, and remove the prior early-return so transfer-based bypass logic runs independently when strategy is missing.
Test coverage for create() transfer behavior
packages/clerk-js/src/core/resources/__tests__/SignUp.test.ts
Adds describe('create') test suite for { transfer: true } scenarios with captchaOauthBypass configuration. Validates that CaptchaChallenge is not called for OAuth strategies in the bypass list, but is called for enterprise_sso.
Changeset entry
.changeset/oauth-captcha-callback-backport.md
Documents the @clerk/clerk-js patch that fixes SSO callback hang by ensuring captcha is correctly bypassed for configured OAuth providers during signup transfers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • dstaley

Poem

🐰 A hop through OAuth's winding path,
No captcha hang to block the auth!
Transfer flows now smooth and fast,
With bypass rules at last held fast.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: a backport of an OAuth captcha bypass fix to Core 2, addressing the issue where new OAuth users experienced hangs on SSO callback.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch daniel/user-5459-backport-oauth-captcha-callback-fix-to-clerk-js-5x

Comment @coderabbitai help to get the list of available commands and usage tips.

@dmoerner dmoerner changed the title fix(js): Bypass captcha on OAuth backport for Core 2 fix(clerk-js): Bypass captcha on OAuth backport for Core 2 Jun 3, 2026
@dmoerner

dmoerner commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

finalParams = { ...finalParams, ...captchaParams };
}

if (finalParams.transfer && this.shouldBypassCaptchaForAttempt(finalParams)) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

On the previous code path, this branch would never hit: On a transfer we would have no strategy which would then early return false from shouldBypassCaptchaForAttempt. Clean it up, and it was useless even if it did hit, because the backend deliberately ignores the strategy sent with a transfer in favor of fetching the original strategy.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/clerk-js/src/core/resources/SignUp.ts (1)

565-569: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard nested sign-in strategy access to avoid runtime crashes on transfer flows.

SignUp.clerk.client!.signIn.firstFactorVerification.strategy can throw if any intermediate object is missing. In that case, create() fails instead of falling back to captcha handling.

Suggested fix
-    if (
-      params.transfer &&
-      // eslint-disable-next-line `@typescript-eslint/no-non-null-assertion`
-      captchaOauthBypass.some(strategy => strategy === SignUp.clerk.client!.signIn.firstFactorVerification.strategy)
-    ) {
+    const transferStrategy = SignUp.clerk.client?.signIn?.firstFactorVerification?.strategy;
+    if (params.transfer && transferStrategy && captchaOauthBypass.some(strategy => strategy === transferStrategy)) {
       return true;
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/clerk-js/src/core/resources/SignUp.ts` around lines 565 - 569, The
condition unsafely dereferences
SignUp.clerk.client!.signIn.firstFactorVerification.strategy which can throw if
clerk/client/signIn/firstFactorVerification is missing; update the check in
SignUp.create (the params.transfer branch) to safely guard using optional
chaining or explicit null checks (e.g. const currentStrategy =
SignUp.clerk.client?.signIn?.firstFactorVerification?.strategy and then use
captchaOauthBypass.some(s => s === currentStrategy)) so the code falls back to
captcha handling instead of crashing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/clerk-js/src/core/resources/SignUp.ts`:
- Around line 565-569: The condition unsafely dereferences
SignUp.clerk.client!.signIn.firstFactorVerification.strategy which can throw if
clerk/client/signIn/firstFactorVerification is missing; update the check in
SignUp.create (the params.transfer branch) to safely guard using optional
chaining or explicit null checks (e.g. const currentStrategy =
SignUp.clerk.client?.signIn?.firstFactorVerification?.strategy and then use
captchaOauthBypass.some(s => s === currentStrategy)) so the code falls back to
captcha handling instead of crashing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8b0ea16c-48a0-4a8c-a980-095c31069109

📥 Commits

Reviewing files that changed from the base of the PR and between 29388cd and c47dac6.

📒 Files selected for processing (3)
  • .changeset/oauth-captcha-callback-backport.md
  • packages/clerk-js/src/core/resources/SignUp.ts
  • packages/clerk-js/src/core/resources/__tests__/SignUp.test.ts

@pkg-pr-new

pkg-pr-new Bot commented Jun 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@8734

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8734

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8734

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8734

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8734

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@8734

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@8734

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@8734

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8734

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8734

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8734

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8734

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8734

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8734

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@8734

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8734

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@8734

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8734

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8734

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8734

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@8734

@clerk/types

npm i https://pkg.pr.new/@clerk/types@8734

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8734

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8734

commit: c47dac6

@wobsoriano wobsoriano left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks good 👍🏼

Im not sure about the release process of Core 2, let's ask @clerk/team-sdk

@jacekradko jacekradko merged commit cb1a62f into release/core-2 Jun 3, 2026
202 of 219 checks passed
@jacekradko jacekradko deleted the daniel/user-5459-backport-oauth-captcha-callback-fix-to-clerk-js-5x branch June 3, 2026 17:19
@dmoerner

dmoerner commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Tested with a dummy Core 2 app on Safari.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants