[BUG] OAuth callback server hangs after authorization - setup-token and /login both fail

Resolved 💬 16 comments Opened Oct 11, 2025 by jadenschwartz22-ops Closed Apr 24, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

I'm experiencing a critical authentication issue with Claude Code where all OAuth-based authentication methods fail to complete.

Environment:

  • macOS version: 15.6.1 (Build 24G90)
  • Node.js version: v22.20.0
  • npm version: 10.9.3
  • Claude Code version: 2.0.14
  • Shell: zsh

Steps to Reproduce:

Method 1: claude setup-token

  1. Run claude setup-token
  2. Browser opens to claude.ai OAuth authorization page
  3. Click "Authorize"
  4. Browser redirects to http://localhost:[PORT]/callback but hangs/loads indefinitely
  5. Terminal shows no errors, just sits at "Opening browser to sign in..."
  6. Verified with lsof -i :[PORT] that the callback server IS listening on the port
  7. Manually accessing http://localhost:[PORT]/callback in browser also hangs

Example URL after clicking authorize:

What Should Happen?

OAuth callback should complete successfully and authentication token should be stored and work properly.

Error Messages/Logs

No error messages displayed - the callback server hangs indefinitely.

API Error when OAuth token is eventually created:
401 - Invalid bearer token - Please run /login

Steps to Reproduce

Method 1: claude setup-token

  1. Run claude setup-token in terminal
  2. Browser opens to https://claude.ai/oauth/authorize
  3. Click "Authorize" button
  4. Browser redirects to http://localhost:[PORT]/callback
  5. Page hangs/loads indefinitely - never completes
  6. Terminal shows "Opening browser to sign in..." but never progresses
  7. Verified callback server IS listening with: lsof -i :[PORT]
  8. Server is running but not responding to callback requests

Method 2: /login command

  1. Start Claude Code: claude
  2. Run /login command
  3. Same authorization flow - browser opens
  4. Click "Authorize"
  5. Terminal shows "Creating API key for Claude Code..."
  6. Hangs indefinitely, never completes

Method 3: OAuth token created but doesn't work

  1. After waiting ~5+ minutes, oauth flow eventually succeeded once
  2. Token was displayed in terminal
  3. Set token as environment variable: export CLAUDE_CODE_OAUTH_TOKEN="[token]"
  4. Run claude "test"
  5. Get error: API Error: 401 - Invalid bearer token - Please run /login

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.0.14 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

  • Verified with lsof -i :[PORT] that the callback server is listening on the port but not responding to requests
  • Not using VPN or corporate firewall
  • --debug flag shows no additional information
  • Directory trust prompts also sometimes freeze (possibly related issue)
  • Manual API key from console.anthropic.com works perfectly as a workaround

View original on GitHub ↗

16 Comments

github-actions[bot] · 9 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/1529
  2. https://github.com/anthropics/claude-code/issues/9371
  3. https://github.com/anthropics/claude-code/issues/5244

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

github-actions[bot] · 7 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

tobz1000 · 6 months ago

I have also encountered this issue when attempting to log in via a VS Code devcontainer. The localhost port is being forwarded to the host machine, but when I click Authorize, the browser cannot complete the redirect to the localhost address and hangs indefinitely.

keisuke-yanagisawa · 6 months ago

@tobz1000
In my case, OAuth callback failed in a VS Code Dev Container because Claude Code was listening only on IPv6 (::1), while the browser / VS Code port forwarding accessed the callback via IPv4 (127.0.0.1).

I confirmed this with:

  netstat -ltnp

which showed:

  tcp6 ::1:<PORT> LISTEN claude

As a workaround, I bridged IPv4 → IPv6 using socat:

  apt install -y socat
  socat TCP4-LISTEN:<PORT>,bind=127.0.0.1,reuseaddr,fork TCP6:[::1]:<PORT>

After this, the redirect to http://localhost:<PORT>/callback successfully reached Claude Code and OAuth completed.

litio2001 · 5 months ago

@tobz1000

I have also encountered this issue when attempting to log in via a VS Code devcontainer. The localhost port is being forwarded to the host machine, but when I click Authorize, the browser cannot complete the redirect to the localhost address and hangs indefinitely.

In my case, I solved it by pasting the URL that the authorization returns into a second terminal (I have replaced the genuine key with XXX):

curl -s "http://localhost:41581/callback?code=XXXXXXXXXXXXXX&state=_sR-nt5-XXXXXXXXXXXXXX"

And when I returned to the terminal where it asked me to paste the "code", I was already authorized.

By the way, my Claude Code runtime environment is Docker with Code-Server under a Synology NAS.

extronics · 5 months ago

Encountered the same issue, the reason being that the callback server binds to [::1]:PORT (IPv6 only):

$ ss -tlnp | grep claude
LISTEN 0 511 [::1]:43149 [::]:* users:(("claude",pid=2230,fd=36))

VSCode's port forwarding sends traffic to 127.0.0.1 (IPv4), which never reaches the IPv6-bound server.

Workaround which avoids adding tunnels or fiddling the the callback URL:

Add to devcontainer.json:

{
  "containerEnv": {
    "NODE_OPTIONS": "--dns-result-order=ipv4first"
  }
}

This forces Node.js to resolve localhost to IPv4 first, making the callback server bind to 127.0.0.1.

drobbins-ancile · 5 months ago

None of the listed workarounds are working for me. Any chance we can get this fixed?

becerra-alberto · 5 months ago

Im having the same issue, unable to log in

tommymsz006 · 5 months ago
@tobz1000 In my case, OAuth callback failed in a VS Code Dev Container because Claude Code was listening only on IPv6 (::1), while the browser / VS Code port forwarding accessed the callback via IPv4 (127.0.0.1). I confirmed this with: `` netstat -ltnp ` which showed: ` tcp6 ::1:<PORT> LISTEN claude ` As a workaround, I bridged IPv4 → IPv6 using socat: ` apt install -y socat socat TCP4-LISTEN:<PORT>,bind=127.0.0.1,reuseaddr,fork TCP6:[::1]:<PORT> ` After this, the redirect to http://localhost:<PORT>/callback` successfully reached Claude Code and OAuth completed.

This solution worked for me well after using quotes in the two parameters for socat.

PORT=xxxxx
socat "TCP4-LISTEN:$PORT,bind=127.0.0.1,reuseaddr,fork" "TCP6:[::1]:$PORT"
bradleybeddoes · 5 months ago

Environment: Claude Code v2.1.42, VS Code devcontainer (Docker), Node.js v22.14.0, tmux as default terminal profile. The issue reproduces in both tmux and plain zsh terminals within the devcontainer, ruling out tmux as a contributing factor.

Root cause: Claude Code's OAuth callback server binds exclusively to IPv6 loopback (::1:<port>). VS Code's port forwarding tunnels host localhost:<port> traffic to 127.0.0.1:<port> (IPv4) inside the container, which never reaches the IPv6-only listener. The browser redirect to http://localhost:<port>/callback hangs indefinitely.

Confirmed this with netstat -ltnp inside the container, where 34245 is the random port Claude Code has chosen in the redirect url:

``` sh
tcp6 0 0 ::1:34245 :::* LISTEN 15037/claude


No corresponding IPv4 listener exists on the same port. Meanwhile, VS Code's Ports panel shows the port as forwarded (HTTP, auto-detected via `remote.autoForwardPortsSource: "process"`), but the forwarded traffic targets `127.0.0.1`, not `::1`.

 **Possible cause:** Node.js v17 changed the default `dns.setDefaultResultOrder()` from `ipv4first` to `verbatim`, causing `localhost` to resolve to `::1` (IPv6) before `127.0.0.1` on systems
  with IPv6 enabled ([nodejs/node#40537](https://github.com/nodejs/node/issues/40537)).

 **Fixes tried:** Set `NODE_OPTIONS=--dns-result-order=ipv4first` via `containerEnv` in `devcontainer.json`. The variable was confirmed present in the container shell (`echo $NODE_OPTIONS`), but Claude Code still bound to IPv6. This suggests the callback server either explicitly binds to `::1`, or uses a code path that bypasses the DNS result order flag, Node.js documentation states that `dns.setDefaultResultOrder()` takes higher priority than `--dns-result-order` ([Node.js DNS docs](https://nodejs.org/api/dns.html)), so if Claude Code calls `dns.setDefaultResultOrder('verbatim')` internally, the CLI flag would be overridden.

 **Workaround:** Remove the `::1` entry from `/etc/hosts` inside the container, forcing `localhost` to resolve to IPv4 only. Note that `sed -i` fails on Docker's bind-mounted `/etc/hosts`, so a copy-and-overwrite is required:

``` sh
sudo cp /etc/hosts /tmp/hosts.tmp && sudo sed '/^::1\s/d' /tmp/hosts.tmp | sudo tee /etc/hosts > /dev/null

After this, Claude Code's callback server binds to 127.0.0.1, VS Code's port forwarding works, and OAuth login within the browser completes successfully. This can be added to a postCreateCommand or dotfiles install script for persistence across rebuilds.

Confirmed this with netstat -ltnp inside the container, where 34903 is the random port Claude Code has chosen in the redirect url:

``` sh
tcp 0 0 127.0.0.1:34903 0.0.0.0:* LISTEN 21484/claude

santyclaz · 4 months ago

I found another workaround based off of @bradleybeddoes solution above. The workaround uses this net.ipv6.conf.all.disable_ipv6 kernel parameter and doesn't require fanagling with the /etc/hosts file that should ideally be read only.

tl;dr: Set net.ipv6.conf.all.disable_ipv6=1 when you run the container

Example Docker command

docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 [image_name]

Example compose.yml

services:
  your-service:
    # ...
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=1
  # ...

Example devcontainer.json

{
  // ...
  "dockerFile": "path/to/Dockerfile",
  "runArgs": [
    "--sysctl net.ipv6.conf.all.disable_ipv6=1"
  ],
  // ...
}
jessezhang91 · 4 months ago

Thank you @santyclaz!

Adding this to my devcontainer.json worked:

{
  // ...
  "dockerFile": "path/to/Dockerfile",
  "runArgs": [
    "--sysctl", "net.ipv6.conf.all.disable_ipv6=1"
  ],
  // ...
}

(note the separate strings for sysctl)

paulc-ibisworld · 4 months ago

I have also encountered this issue in both terminal based claude-code, as well as via vs-code. The the auth-flow redirect back to the client never completes because it is listening on IPV6 only and the request goes to IPV4

  • Windows 11, Chrome 145
  • Port was confirmed listening on [::1] via netstat -ano
  • The auth flow completes successfully server-side — the callback URL with the auth code is correctly redirected to localhost:<port>, but nothing is listening on IPv4
  • Claude Code version 2.1.70 (from your logs: cc_version=2.1.70)
joaomacedx · 3 months ago

I’m experiencing the same issue. When I try to log in to Claude both in the CLI and in the browser I receive the following error message:

4006-147f7d0033d2abaa.js:14 [REACT_QUERY_CLIENT] QueryClient error: a: Internal server error
    at i (20152-804e66473bf4cf52.js:1:18338)
    at 20152-804e66473bf4cf52.js:1:20308
    at async 20152-804e66473bf4cf52.js:1:21616
github-actions[bot] · 2 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.