WSL2 Claude Code CLI 인증 실패 보고서

날짜: 2026-03-10

환경: Windows 11 Home + WSL2 Ubuntu 24.04

CLI 버전: Claude Code v2.1.71 (WSL), v2.1.63 (Windows)

상태: ❌ 미해결 → ✅ 우회 솔루션 확인


1. 문제 요약

WSL2 환경에서 claude auth login 실행 시 OAuth 토큰 교환이 일관되게 HTTP 400 에러로 실패.

총 15회 이상 시도, 모두 동일 증상.

Login failed: Request failed with status code 400

2. 환경 구성

항목
OSWindows 11 Home 10.0.26200
WSLUbuntu 24.04 (WSL2)
Node.js (WSL)v24.14.0 (NVM)
Node.js (Win)v22.18.0
Claude Code (WSL)v2.1.71
Claude Code (Win)v2.1.63
Windows Claude 인증✅ 정상 (oauth_token, firstParty)
WSL Claude 인증❌ 실패

3. 재현 절차

3.1 기본 시도 (BROWSER=echo 모드)

# WSL에서 실행
PATH=/home/dtsli/.nvm/versions/node/v24.14.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
BROWSER=echo claude auth login

1. CLI가 로컬 HTTP 서버 시작 (랜덤 포트, e.g. 45405)

2. OAuth URL 출력 (console.anthropic.com/oauth/authorize)

3. 브라우저에서 URL 접속 → 승인 클릭

4. 브라우저가 platform.claude.com/oauth/code/callback?code=XXX&state=YYY로 리다이렉트

5. 콜백 페이지에 "Paste this into Claude Code" 메시지와 코드 표시

3.2 코드 전달 시도 (모두 실패)

방법 A: curl로 localhost callback 호출

curl "http://127.0.0.1:PORT/callback?code=XXX&state=YYY"
# → 302 Found (로컬 서버는 수신) → 토큰 교환 시 400

방법 B: tmux send-keys로 코드 붙여넣기

tmux send-keys -t claude-auth "CODE#STATE" Enter
# → CLI의 Ink TUI에 텍스트 전달 안 됨

방법 C: 즉시 전달 (승인 후 수 초 내)

# Chrome MCP로 승인 버튼 자동 클릭 후 즉시 curl
# → 동일한 400 에러

4. 원인 분석

4.1 OAuth PKCE 흐름 분석

[CLI] ──── code_challenge, state ────→ [Authorization Server]
                                              │
[Browser] ←── redirect to callback ───────────┘
                                              │
[Browser] ──→ platform.claude.com/oauth/code/callback?code=X&state=Y
                                              │
              ┌── 여기서 code가 서버에 도달 ──┘
              │
[CLI] ──── code + code_verifier ────→ [Token Endpoint]
              │
              └── 400 Bad Request (code 이미 소비됨)

4.2 핵심 원인: redirect_uri 이중 소비

1. CLI가 생성하는 redirect_uri: https://platform.claude.com/oauth/code/callback

2. 브라우저가 승인 후 이 URL로 네비게이션 → platform 서버가 code를 수신

3. 콜백 페이지는 단순히 코드를 표시 (localhost로 요청 안 함)

4. 이후 CLI가 같은 code로 토큰 교환 시도 → 이미 소비된 code라 400 반환

4.3 검증 근거