Skip to content

JoyID: authWithPopup fails on Brave/Firefox — authWithRedirect not accessible via @joyid/ckb #361

@toastmanAu

Description

@toastmanAu

Problem

The JoyID connect flow in @joyid/ckb uses authWithPopup() from @joyid/common, which relies on a WebSocket relay to pass the passkey result from phone to desktop.

This relay only works reliably in Chrome/Chromium. On Brave and Firefox:

  • The WebSocket relay is blocked or throttled by the browser
  • The desktop never receives the signed passkey result
  • Users must scan the QR 2–4 times before it sometimes succeeds
  • Often times out entirely, leaving users stuck

This affects any dapp using CCC's JoyID connector on desktop Brave/Firefox — which is a significant portion of the CKB developer/user community.

Root Cause

Chrome has Google's own FIDO2 cross-device transport (CTAP2) infrastructure built in. Brave and Firefox route through JoyID's relay server, which these browsers throttle or block.

authWithRedirect() and authCallback() already exist in @joyid/common and work in every browser (full-page redirect to app.joy.id, no WebSocket relay). However, they are not accessible through the CCC JoyID connector — CCC uses authWithPopup() directly.

Workaround

We implemented a custom connector that wraps @joyid/common directly with browser detection:

// Brave/Firefox: authWithRedirect() — full page nav to app.joy.id, no relay needed
// Chrome/mobile: authWithPopup() — existing behaviour unchanged
if (typeof navigator.brave !== 'undefined' || /Firefox/.test(navigator.userAgent)) {
  common.authWithRedirect(request); // redirects to app.joy.id
} else {
  return common.authWithPopup(request);
}

Result: Brave users go from 2–4 QR scan attempts + frequent timeouts → 1 Face ID tap, done.

Note: navigator.brave.isBrave is a Promise (async) — must use typeof navigator.brave !== 'undefined' for synchronous detection.

Suggested Fix

The CCC JoyID connector could detect the browser and fall back to authWithRedirect() on Brave/Firefox. Alternatively, expose a preferRedirect option.

We also filed nervina-labs/joyid-sdk-js#58 requesting that authWithRedirect, authCallback, and isRedirectFromJoyID be re-exported from @joyid/ckb directly — a one-line fix on their end.

Browser Scorecard (tested on wyltekindustries.com)

  • Chrome ✅ popup, 1 shot
  • Brave ✅ redirect flow (custom connector), 1 shot
  • Chromium ✅ redirect flow, 1 shot
  • Safari iOS ✅ 1 tap Face ID
  • Firefox ⚠ not supported (CTAP2 hybrid not available in Firefox — we show a clear message)

Impact

Any dapp using CCC + JoyID on desktop Brave/Firefox is affected. Brave has significant adoption in the Web3/crypto community.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions