Skip to content

WSL2: clerk auth login needs device flow or printed auth URL fallback #411

Description

@stephlocke

When running clerk auth login inside a WSL2 environment, the CLI cannot reliably open a browser, so interactive login may fail or become unusable.

Problem

clerk auth login appears to depend on opening a local browser automatically. In WSL2 (and similar headless/remote terminal environments), that assumption often breaks, which makes login infeasible.

Expected behavior

Please support one (or both) of these fallback paths when browser launch is unavailable:

  1. Device authorization flow (recommended)

    • Show a verification URL + short code in terminal
    • Let user complete auth in any browser/device
    • CLI polls and completes login once authorized
  2. Manual browser flow fallback

    • Print the exact auth URL to stdout (and optionally “press Enter after auth”)
    • Keep process waiting and detect completion/token handoff after browser auth

Why this matters

This improves usability for:

  • WSL2 users
  • SSH/remote development environments
  • CI-like or constrained shells where GUI/browser launch is unavailable

Repro context

  • Environment: WSL2
  • Command: clerk auth login
  • Issue: Browser does not reliably launch from CLI context, blocking login completion

Suggested UX details

  • Detect browser-launch failures and automatically fall back
  • Always print auth URL as a backup, even when auto-open succeeds
  • Include copy-friendly output and clear next-step prompts
  • Exit with actionable error/help text if auth times out

Notes from AI on resolving it locally

Root cause: clerk auth login binds its OAuth callback server to 127.0.0.1 only (via Bun.serve({hostname:"127.0.0.1",
port:0, ...})) and opens the browser via a plain xdg-open call. In WSL2, depending on .wslconfig networking mode
/ whether wslu's wslview is properly wired as the xdg-open/BROWSER handler, xdg-open either fails silently or opens
nothing, and the CLI just sits on "Waiting for authentication (timeout in 2m)..." with no fallback message — even
though the local server itself is listening fine and is reachable from Windows via WSL2's default localhostForwarding.

What actually unblocked it: other commands in the same CLI (e.g. clerk users open, clerk apps open) already have a
"browser failed to open" fallback that prints the URL (Could not open your browser automatically. Open this URL to
continue: ...), but clerk auth login doesn't call that same fallback path — it just hangs silently. I shadowed
xdg-open on PATH with a one-line script that writes $1 to a file instead of trying to open anything, ran clerk auth
login in the background, grabbed the captured authorize URL, and opened it manually in a Windows browser. The
already-running local callback server picked up the redirect fine — confirming the only broken part is "opening the
browser automatically," not the network path back.

Suggestions for the devs:

  1. Give clerk auth login the same "couldn't open browser" fallback that users open/apps open/impersonate already have
    — check the same "did xdg-open/open() actually succeed" signal and print the authorize URL on failure instead of just
    silently waiting.
  2. Add a --no-browser / --print-url flag (or auto-detect no-DISPLAY/WSL environments) that skips the open attempt
    entirely and just prints the URL, similar to users open --print.
  3. Detect WSL specifically (e.g. /proc/version containing "microsoft") and default to the print-URL path there, since
    xdg-open in WSL is notoriously inconsistent depending on distro/wslu setup — this is probably the single most common
    environment this bites.
  4. Document the workaround now: for anyone else stuck, clerk config commands accept CLERK_PLATFORM_API_KEY, but that
    key type currently has no self-serve Dashboard page to generate (the "API keys" page under an app/instance only shows
    pk_/sk_) — worth flagging as a second, separate gap: either surface where to mint an ak_... key, or document that it
    isn't self-serve yet

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions