날짜: 2026-03-10
환경: Windows 11 Home + WSL2 Ubuntu 24.04
CLI 버전: Claude Code v2.1.71 (WSL), v2.1.63 (Windows)
상태: ❌ 미해결 → ✅ 우회 솔루션 확인
WSL2 환경에서 claude auth login 실행 시 OAuth 토큰 교환이 일관되게 HTTP 400 에러로 실패.
총 15회 이상 시도, 모두 동일 증상.
Login failed: Request failed with status code 400
| 항목 | 값 | |
| OS | Windows 11 Home 10.0.26200 | |
|---|---|---|
| WSL | Ubuntu 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 인증 | ❌ 실패 |
# 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" 메시지와 코드 표시
방법 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 에러
[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 이미 소비됨)
1. CLI가 생성하는 redirect_uri: https://platform.claude.com/oauth/code/callback
2. 브라우저가 승인 후 이 URL로 네비게이션 → platform 서버가 code를 수신
3. 콜백 페이지는 단순히 코드를 표시 (localhost로 요청 안 함)
4. 이후 CLI가 같은 code로 토큰 교환 시도 → 이미 소비된 code라 400 반환
| 요인 | 설명 | |
| WSL2 네트워크 격리 | WSL2는 NAT 네트워크 → Windows 브라우저에서 WSL localhost 직접 접근 불가 | |
|---|---|---|
| Ink TUI 입력 제한 | `tmux send-keys`로 Ink 컴포넌트에 텍스트 전달 불가 | |
| CLI 버전 차이 | WSL 2.1.71 vs Win 2.1.63 — 동작 차이 가능성 |
| # | 접근법 | 결과 | ||
| 1 | `BROWSER=echo` + 수동 브라우저 + curl callback | ❌ 400 | ||
|---|---|---|---|---|
| 2 | Chrome MCP 자동 승인 + curl callback | ❌ 400 | ||
| 3 | Chrome MCP 자동 승인 + tmux send-keys | ❌ 입력 전달 안 됨 | ||
| 4 | JavaScript redirect 인터셉트 | ❌ location.assign read-only | ||
| 5 | NODE_DEBUG 디버깅 | ❌ 출력 과다, tee 파이프 호환 문제 | ||
| 6 | strace 디버깅 | ❌ WSL 환경에서 출력 없음 | ||
| 7 | Windows 자격증명 복사 | ✅ **성공** — `~/.claude/.credentials.json` 파일 기반 확인 (2026-03-16) | ||
| 8 | API Key 방식 | ❌ 별도 개발자 과금 필요 (구독과 별개) | ||
| 9 | 즉시 curl (승인 후 수 초 내) | ❌ 400 | ||
| 10 | 다중 세션 반복 시도 (10회+) | ❌ 모두 400 |
CLI 소스에서 CLAUDE_CODE_OAUTH_TOKEN 환경변수 지원 확인.
claude setup-token 명령으로 1년짜리 장기 토큰 생성 가능.
절차:
# 1. Windows PowerShell 새 창 열기 (Claude Code 바깥에서 실행)
# 2. nested session 차단 해제 후 토큰 생성
$env:CLAUDECODE=""
claude setup-token
# 3. 브라우저 승인 → 토큰 화면에 표시됨
# 4. WSL에서 토큰 설정
echo 'export CLAUDE_CODE_OAUTH_TOKEN="표시된_토큰"' >> ~/.bashrc
source ~/.bashrc
# 5. 확인
claude auth status
# → loggedIn: true
setup-token은 TTY가 필요해 Claude Code 세션 내에서 실행 불가.
실제로 동작한 방법: Windows ~/.claude/.credentials.json을 WSL에 직접 복사.
# Windows credentials 경로 (Claude Code 실행 중 확인)
# ~/.claude/.credentials.json → {"claudeAiOauth": {"accessToken": "sk-ant-oat01-...", "refreshToken": "sk-ant-ort01-...", "expiresAt": ...}}
# WSL에서 복사
cp /mnt/c/Users/dtsli/.claude/.credentials.json ~/.claude/.credentials.json
# 확인
claude -p 'echo hello' --dangerously-skip-permissions --output-format text
# → hello ✅
핵심 발견:
| 변수 | 용도 | |
| `CLAUDE_CODE_OAUTH_TOKEN` | 장기 OAuth 토큰 (setup-token으로 생성) | |
|---|---|---|
| `ANTHROPIC_AUTH_TOKEN` | 인증 토큰 (SDK 내부 사용) | |
| `ANTHROPIC_API_KEY` | API 키 (별도 과금, 구독과 무관) |
| 항목 | 값 | |
| Authorization | `https://console.anthropic.com/oauth/authorize` | |
|---|---|---|
| Token Exchange | `https://platform.claude.com/v1/oauth/token` | |
| Callback (code display) | `https://platform.claude.com/oauth/code/callback` | |
| Client ID | `9d1c250a-e61b-44d9-88ed-5944d1962f5e` |
WSL2 환경에서 claude auth login의 OAuth PKCE 흐름은 구조적으로 실패한다.
redirect_uri가 localhost가 아닌 platform.claude.com으로 설정되어 있어,
authorization code가 platform 서버에서 소비된 후 CLI의 토큰 교환이 불가능.
실제 해결책: Windows ~/.claude/.credentials.json을 WSL에 복사.
refreshToken이 포함되어 자동 갱신 가능. watchdog.sh에서 1시간 주기 자동 동기화 운영 중.
setup-token은 TTY 필요로 Claude Code 세션 내 실행 불가 — 차선책으로만 유효.
보고자: Claude Code (Opus 4.6) — 자동화 시도 15회+ 후 원인 분석 완료
해결: Claude Code (Sonnet 4.6) — 2026-03-16 credentials.json 복사 방식 검증