Okta SSO(JWT 인증)로 Claude Code 사용하기
Okta SSO(JWT 인증)로 Claude Code 사용하기
Claude Code를 각 개발자의 Okta 신원을 사용해 LiteLLM을 통해 라우팅하는 방법을 알려드릴게요. Claude Code가 매 요청마다 개발자 본인의 Okta 접근 토큰을 보내면, LiteLLM이 이를 사용자 Okta 인증 서버에서 검증하고 첫 요청 시 사용자를 자동으로 생성해요. 사용량, 지출, 로그는 모두 그 사용자에게 귀속돼요. 사용자별 API 키를 발급하거나 수동 프로비저닝할 필요가 없어서, 10명이든 10,000명이든 똑같이 동작해요.
출처: 문서
본문
엔터프라이즈 기능
JWT 인증은 LiteLLM Enterprise 라이선스가 필요해요. 무료 30일 체험판을 시작하거나 데모를 예약해 보세요. Enterprise에 포함된 내용을 확인해 보세요.
이 가이드는 Okta를 사용하지만, JWT 접근 토큰을 발급하는 모든 OIDC 제공자(Azure AD, Keycloak, Auth0 등)도 같은 방식으로 동작해요. 발급자 URL과 앱 설정만 다를 뿐이에요.
동작 원리
개발자가 처음으로 Claude Code를 사용할 때, 작은 apiKeyHelper 스크립트가 Okta 로그인 페이지를 열어요. 그 이후부터는 전부 조용히 진행돼요. 스크립트가 캐시된 토큰을 서빙하고 백그라운드에서 갱신하고, Claude Code가 그 토큰을 API 키로 보내면, LiteLLM이 Okta에 공개된 JWKS 키로 토큰 서명을 검증해요. user_id_upsert가 활성화되어 있기 때문에, LiteLLM은 첫 요청 시 토큰의 sub와 email 클레임에서 내부 사용자 레코드를 만들어요. 그래서 관리자가 아무것도 발급하지 않아도 사용자별 지출 추적이 즉시 시작돼요.
1. Okta 앱 만들기
Okta Admin Console에서 Claude Code용 OIDC Native Application을 만들어요:
-
Applications > Create App Integration에서 OIDC와 Native Application을 선택해요.
-
Grant type에서 Device Authorization(CLI 도구에 가장 적합해요. 클라이언트 시크릿이나 localhost 리다이렉트가 필요 없어요)과 Refresh Token을 활성화해요.
-
접근 권한이 있어야 하는 Okta 그룹에 앱을 할당해요.
-
Client ID를 기록해 두세요.
토큰은 org 인증 서버가 아니라 커스텀 인증 서버(예: 내장된 default라는 이름의 서버)에서 와야 해요. 커스텀 인증 서버의 접근 토큰만 JWKS 엔드포인트로 검증할 수 있는 JWT이기 때문이에요. Security > API > Authorization Servers에서 default 서버가 존재하는지 확인하고 두 값을 기록해 두세요.
-
JWKS URL:
https:///oauth2/default/v1/keys -
Audience:
api://default(또는 서버의 audience 설정값)
커스텀 인증 서버의 접근 토큰은 기본적으로 sub를 포함해요. 접근 토큰에서 사용자 이메일도 얻으려면 Security > API > Authorization Servers > default > Claims에서 클레임을 추가해요. 이름은 email, Access Token에 포함, 값은 user.email로 설정해요.
2. LiteLLM 구성하기
프록시 config에서 JWT 인증을 활성화해요.
model_list: - model_name: claude-opus-5 litellm_params: model: anthropic/claude-opus-5 api_key: os.environ/ANTHROPIC_API_KEY - model_name: claude-sonnet-5 litellm_params: model: anthropic/claude-sonnet-5 api_key: os.environ/ANTHROPIC_API_KEYgeneral_settings: master_key: os.environ/LITELLM_MASTER_KEY enable_jwt_auth: true litellm_jwtauth: user_id_jwt_field: "sub" user_email_jwt_field: "email" user_id_upsert: true
환경 변수를 설정해요. 사용자 upsert는 데이터베이스에 기록하므로 DATABASE_URL이 필요해요.
export JWT_PUBLIC_KEY_URL="https:///oauth2/default/v1/keys"export JWT_AUDIENCE="api://default"export DATABASE_URL="postgresql://..."export LITELLM_LICENSE=""export ANTHROPIC_API_KEY="sk-ant-..."export LITELLM_MASTER_KEY="sk-
"
프록시를 시작해요.
litellm --config /path/to/config.yaml
tip
회사 도메인으로 접근을 제한하려면 litellm_jwtauth 아래에 user_allowed_email_domain: "yourcompany.com"을 추가해요. 사용 가능한 클레임 매핑과 접근 제어의 전체 목록은 JWT 기반 인증 문서를 참고하세요.
3. 토큰으로 검증하기
자신의 Okta 사용자에 대한 접근 토큰을 얻은 다음(예: 4단계의 헬퍼 스크립트를 한 번 실행), 그 토큰으로 프록시를 호출해 봐요.
export OKTA_TOKEN=""curl -X POST http://0.0.0.0:4000/v1/messages \ -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-5", "max_tokens": 100, "messages": [{"role": "user", "content": "Hello"}] }'
성공 응답이 나오면 토큰이 Okta의 JWKS에 대해 검증됐다는 뜻이에요. Admin UI에서 Internal Users를 열면, 토큰의 sub 클레임에서 생성된 사용자와 그 사용자에게 이미 귀속된 이번 요청의 지출을 확인할 수 있어요.
4. Claude Code 구성하기
Claude Code는 apiKeyHelper를 통해 동적 자격 증명을 지원해요. 이는 정적 키 대신 새 API 키를 얻기 위해 실행하는 스크립트예요. 이것을 ~/.claude/okta-token.sh로 저장해요(자신의 Okta 도메인과 1단계의 Client ID를 입력해 주세요).
#!/usr/bin/env bashset -euo pipefailOKTA_DOMAIN="https://"AUTH_SERVER="default"CLIENT_ID=""SCOPES="openid profile email offline_access"CACHE="$HOME/.claude/okta_token.json"token_url="$OKTA_DOMAIN/oauth2/$AUTH_SERVER/v1/token"now=$(date +%s)if [ -f "$CACHE" ]; then if [ "$now" -lt "$(( $(jq -r '.expires_at // 0' "$CACHE") - 60 ))" ]; then jq -r '.access_token' "$CACHE" exit 0 fi refresh=$(jq -r '.refresh_token // empty' "$CACHE") if [ -n "$refresh" ]; then if resp=$(curl -sf "$token_url" \ -d grant_type=refresh_token \ -d client_id="$CLIENT_ID" \ -d refresh_token="$refresh" \ -d scope="$SCOPES"); then echo "$resp" | jq --argjson now "$now" '. + {expires_at: ($now + .expires_in)}' > "$CACHE" chmod 600 "$CACHE" jq -r '.access_token' "$CACHE" exit 0 fi fifidevice=$(curl -sf "$OKTA_DOMAIN/oauth2/$AUTH_SERVER/v1/device/authorize" \ -d client_id="$CLIENT_ID" \ -d scope="$SCOPES")echo "Sign in with Okta: $(echo "$device" | jq -r '.verification_uri_complete')" >&2device_code=$(echo "$device" | jq -r '.device_code')interval=$(echo "$device" | jq -r '.interval // 5')while true; do sleep "$interval" resp=$(curl -s "$token_url" \ -d grant_type=urn:ietf:params:oauth:grant-type:device_code \ -d client_id="$CLIENT_ID" \ -d device_code="$device_code") if echo "$resp" | jq -e '.access_token' > /dev/null; then echo "$resp" | jq --argjson now "$(date +%s)" '. + {expires_at: ($now + .expires_in)}' > "$CACHE" chmod 600 "$CACHE" jq -r '.access_token' "$CACHE" exit 0 fi err=$(echo "$resp" | jq -r '.error // empty') if [ "$err" != "authorization_pending" ] && [ "$err" != "slow_down" ]; then echo "Okta sign-in failed: $resp" >&2 exit 1 fidone
스크립트는 apiKeyHelper가 요구하는 대로 stdout에 접근 토큰만 출력하고, 로그인 프롬프트는 stderr로 보내요. chmod +x ~/.claude/okta-token.sh로 실행 권한을 부여해요.
그런 다음 ~/.claude/settings.json에서 Claude Code가 LiteLLM을 가리키게 해요.
{ "env": { "ANTHROPIC_BASE_URL": "https://litellm.yourcompany.com", "CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "3300000" }, "apiKeyHelper": "~/.claude/okta-token.sh"}
CLAUDE_CODE_API_KEY_HELPER_TTL_MS는 Claude Code가 헬퍼의 출력을 캐시하는 시간을 제어해요. Okta 접근 토큰 수명보다 약간 짧게 설정해요(Okta 기본값은 1시간이므로 여기서는 55분). 첫 실행에서 개발자가 브라우저에서 Okta 로그인을 한 번 완료하면, 그 이후의 모든 요청에는 자동으로 개발자 본인의 신원이 실려요.
5. 조직에 배포하기
위의 어떤 단계도 사용자별 관리자 작업이 필요하지 않아요. 그러므로 배포는 단지 디바이스 관리 도구를 통해 헬퍼 스크립트와 Claude Code 설정 두 파일을 배포하는 것으로 충분해요. 각 개발자의 ~/.claude/settings.json에 의존하는 대신 설정을 중앙에서 강제하려면, 관리형 설정으로 배포해요(macOS에서는 /Library/Application Support/ClaudeCode/managed-settings.json, Linux에서는 /etc/claude-code/managed-settings.json). 이 설정은 우선순위가 높고 로컬에서 덮어쓸 수 없어요.
선택 사항: 팀, 예산, 사용자별 키
기본 흐름이 동작한 뒤에 흔히 확장하는 두 가지가 있어요. 지출을 팀에 귀속하려면 Okta 접근 토큰에 groups 클레임을 추가하고 team_ids_jwt_field: "groups"로 매핑해요. 그룹 값은 LiteLLM 팀 ID와 일치해야 하는데, SCIM으로 Okta에서 동기화하거나 수동으로 만들 수 있어요. 각 개발자에게 공유 팀 설정 대신 자체 예산, 속도 제한, 모델 접근을 부여하려면 unregistered_jwt_client_behavior: "auto_register"와 함께 JWT to Virtual Key Mapping을 사용해요. 그러면 각 사용자의 첫 요청 시 가상 키가 프로비저닝돼요.
더 알아보기 (Learn more)
- JWT 기반 인증 - 모든
litellm_jwtauth옵션 - JWT to Virtual Key Mapping - 사용자별 키, 예산, 모델 접근
- Claude Code Gateway (SSO 로그인) - 개발자가 헬퍼 스크립트 없이 프록시의 SSO로
/login에 로그인하는 방식 - Claude Code Quickstart - Claude Code + LiteLLM 기본 설정