---
title: WIF 참조
url: https://platform.claude.com/docs/ko/manage-claude/wif-reference
description: Workload Identity Federation을 위한 환경 변수, 검증 규칙, 프로필 구성 및 오류 참조.
---

이 페이지는 [Workload Identity Federation](https://platform.claude.com/docs/ko/manage-claude/workload-identity-federation)의 구성 표면, 검증 제약 조건 및 오류 매핑을 모아 놓은 것입니다. 설정 안내는 [공급자 가이드](https://platform.claude.com/docs/ko/manage-claude/workload-identity-federation#identity-providers)를 참조하세요.

## 토큰 교환 요청

`POST /v1/oauth/token`은 [RFC 7523](https://www.rfc-editor.org/rfc/rfc7523) `jwt-bearer` 그랜트를 사용하는 JSON 본문을 받습니다. SDK는 [환경 변수](https://platform.claude.com/docs/ko/manage-claude/wif-reference#environment-variables)로부터 이 요청을 자동으로 구성하며, 각 공급자 가이드의 cURL 예제는 원시 본문을 보여줍니다.

| 필드                   | 필수 여부 | 설명                                                                                                                                                                                                                    |
| -------------------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `grant_type`         | 예     | 항상 `urn:ietf:params:oauth:grant-type:jwt-bearer`입니다.                                                                                                                                                                  |
| `assertion`          | 예     | 신원 공급자가 발급한 OIDC JWT입니다.                                                                                                                                                                                              |
| `federation_rule_id` | 예     | 평가할 페더레이션 규칙의 태그 ID(`fdrl_...`)입니다.                                                                                                                                                                                   |
| `organization_id`    | 예     | Anthropic 조직의 UUID입니다.                                                                                                                                                                                                |
| `service_account_id` | 예     | 대상 서비스 계정의 태그 ID(`svac_...`)입니다.                                                                                                                                                                                      |
| `workspace_id`       | 조건부   | 발급된 토큰의 범위를 지정할 워크스페이스의 태그 ID(`wrkspc_...`)입니다. 규칙이 둘 이상의 워크스페이스에서 활성화된 경우 필수입니다. 생략하면 서버가 규칙에서 활성화된 유일한 워크스페이스를 선택합니다. 리터럴 `default`도 조직의 Default Workspace에 대해 작동하지만 지원 중단되었으므로, 해당 워크스페이스의 `wrkspc_...` ID를 사용하세요. |

## 토큰 교환 응답

`POST /v1/oauth/token`은 표준 OAuth 2.0 토큰 응답([RFC 6749 §5.1](https://www.rfc-editor.org/rfc/rfc6749#section-5.1))을 반환합니다:

| 필드             | 타입      | 설명                                                                                          |
| -------------- | ------- | ------------------------------------------------------------------------------------------- |
| `access_token` | string  | `sk-ant-oat01-...` 접두사가 붙은 수명이 짧은 Anthropic 토큰입니다. `Authorization: Bearer <token>`으로 전달하세요. |
| `token_type`   | string  | 항상 `Bearer`입니다.                                                                             |
| `expires_in`   | integer | 토큰이 만료될 때까지의 초 단위 시간입니다.                                                                    |
| `scope`        | string  | 일치한 규칙이 부여한 OAuth 범위입니다.                                                                    |

## 환경 변수

SDK는 생성자 인수 없이 페더레이션 토큰 교환을 수행하기 위해 이 변수들을 읽습니다.

| 변수                              | 필수 여부                          | 설명                                                                                                                                                                                                                                                                 | 예시                                     |
| ------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- |
| `ANTHROPIC_FEDERATION_RULE_ID`  | 예                              | 평가할 페더레이션 규칙의 태그 ID입니다.                                                                                                                                                                                                                                            | `fdrl_...`                             |
| `ANTHROPIC_ORGANIZATION_ID`     | 예                              | Anthropic 조직의 UUID입니다. Claude Console의 [Organization](https://platform.claude.com/settings/organization) 페이지(`platform.claude.com/settings/organization`)에서 확인할 수 있습니다.                                                                                            | `00000000-0000-0000-0000-000000000000` |
| `ANTHROPIC_IDENTITY_TOKEN_FILE` | `_TOKEN_FILE` 또는 `_TOKEN` 중 하나 | "identity provider"(신원 공급자), 즉 IdP가 발급한 JWT의 파일 시스템 경로입니다. SDK는 교환할 때마다 이 파일을 다시 읽으므로 디스크에서 교체되는 프로젝션 토큰이 항상 최신 상태로 유지됩니다.                                                                                                                                         | `/var/run/secrets/anthropic.com/token` |
| `ANTHROPIC_IDENTITY_TOKEN`      | `_TOKEN_FILE` 또는 `_TOKEN` 중 하나 | 문자열 형태의 리터럴 JWT입니다. 플랫폼이 토큰을 파일이 아닌 환경 변수로 주입하는 경우에 사용하세요.                                                                                                                                                                                                         | `eyJhbGciOiJSUzI1NiIs...`              |
| `ANTHROPIC_SERVICE_ACCOUNT_ID`  | 예                              | 발급된 액세스 토큰이 대리하는 대상 Anthropic 서비스 계정의 태그 ID입니다.                                                                                                                                                                                                                    | `svac_...`                             |
| `ANTHROPIC_WORKSPACE_ID`        | 조건부                            | 발급된 토큰의 범위를 지정할 워크스페이스의 태그 ID입니다. 페더레이션 규칙이 둘 이상의 워크스페이스에서 활성화된 경우 필수이며, 규칙이 단일 워크스페이스에 바인딩된 경우 선택 사항입니다. 발급된 토큰은 교환 시점에 이 워크스페이스로 범위가 지정되므로, 워크스페이스를 전환하려면 새로 교환해야 합니다. 리터럴 `default`도 Default Workspace에 대해 작동하지만 지원 중단되었으므로, 해당 워크스페이스의 `wrkspc_...` ID를 사용하세요. | `wrkspc_...`                           |
| `ANTHROPIC_PROFILE`             | 아니요                            | 로드할 [구성 프로필](https://platform.claude.com/docs/ko/manage-claude/wif-reference#profile-configuration-file)의 이름입니다. 이 표의 페더레이션 환경 변수보다 우선합니다.                                                                                                                         | `staging-profile`                      |

직접 환경 변수 페더레이션 경로는 `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, 그리고 `ANTHROPIC_IDENTITY_TOKEN_FILE` 또는 `ANTHROPIC_IDENTITY_TOKEN` 중 하나가 모두 설정된 경우에만 활성화됩니다. `ANTHROPIC_WORKSPACE_ID`는 함께 읽히지만 활성화를 제어하지는 않습니다.

<Warning>
  빈 문자열로 설정된 변수도 여전히 자격 증명 우선순위 체인에서 자리를 차지합니다. `ANTHROPIC_API_KEY=""`가 내보내지면 SDK는 페더레이션으로 넘어가지 않고 빈 키로 API 키 경로를 선택합니다. 사용하지 않는 자격 증명 변수는 비워두지 말고 설정 해제하세요.
</Warning>

### 자격 증명 우선순위

SDK는 이 순서로 자격 증명을 해결합니다. 자격 증명을 산출하는 첫 번째 소스가 우선합니다.

| 순서 | 소스                                                | 참고                                                                                                                                 |
| -- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| 1  | 생성자 인수(`api_key=`, `auth_token=`, `credentials=`) | 항상 다른 모든 것을 재정의합니다.                                                                                                                |
| 2  | `ANTHROPIC_API_KEY` 또는 `ANTHROPIC_AUTH_TOKEN`     | 페더레이션을 완전히 가립니다. API 키에서 마이그레이션할 때 이를 설정 해제하세요.                                                                                    |
| 3  | `ANTHROPIC_PROFILE`                               | `<config_dir>/configs/<name>.json`을 로드합니다. 명명된 프로필이 없으면 넘어가는 것이 아니라 오류입니다.                                                         |
| 4  | 페더레이션 환경 변수                                       | `ANTHROPIC_FEDERATION_RULE_ID` + `ANTHROPIC_ORGANIZATION_ID` + `ANTHROPIC_SERVICE_ACCOUNT_ID` + `ANTHROPIC_IDENTITY_TOKEN[_FILE]`. |
| 5  | 활성 프로필                                            | `<config_dir>/active_config`에서 해결되며, `default`라는 이름의 프로필로 폴백합니다.                                                                   |

프로필이 로드되면 환경 변수는 프로필이 생략한 필드를 채우지만 프로필이 명시적으로 설정한 필드는 절대 재정의하지 않습니다. 예를 들어, `ANTHROPIC_WORKSPACE_ID`는 활성 프로필이 `workspace_id`를 설정하지 않은 경우에만 이를 채웁니다.

## 프로필 구성 파일

프로필은 SDK와 `ant` CLI가 모두 읽는 명명된 구성 파일입니다. 프로필을 사용하면 컨테이너 이미지와 함께 페더레이션 매개변수를 배포하거나 코드를 변경하지 않고 환경 간에 전환할 수 있습니다.

### 구성 디렉터리

SDK는 이 순서로 구성 디렉터리를 찾습니다:

1. `$ANTHROPIC_CONFIG_DIR`
2. Linux 및 macOS의 `~/.config/anthropic`
3. Windows의 `%APPDATA%\Anthropic`

### 활성 프로필

활성 프로필 이름은 이 순서로 해결됩니다:

1. `$ANTHROPIC_PROFILE`
2. `<config_dir>/active_config`의 내용(`ant profile activate <name>`이 작성한 한 줄짜리 파일)
3. 리터럴 이름 `default`

Claude Code와 Claude Agent SDK는 이와 동일한 해결 순서를 따르므로, 여기에 구성된 페더레이션 프로필은 추가 설정 없이 해당 도구들도 인증합니다.

### 파일 레이아웃

| 경로                                        | 내용                                                                              | 민감도                              |
| ----------------------------------------- | ------------------------------------------------------------------------------- | -------------------------------- |
| `<config_dir>/configs/<profile>.json`     | `version`, `authentication` 블록, `organization_id`, `workspace_id`, `base_url`.  | 비밀이 아님. 커밋하거나 이미지에 구워 넣어도 안전합니다. |
| `<config_dir>/credentials/<profile>.json` | `version`, 캐시된 `access_token`, `expires_at`, 그리고 (대화형 로그인의 경우) `refresh_token`. | 비밀. SDK가 `0600` 모드로 작성합니다.       |

구성 파일과 자격 증명 파일 모두 `major.minor` 형식(현재 `"1.0"`)의 최상위 문자열 `version` 필드를 가집니다. SDK는 향후 릴리스가 이전 형식을 감지하고 마이그레이션할 수 있도록 이 필드를 자동으로 작성합니다. 구성을 수동으로 작성할 때 이를 생략하면 SDK는 파일을 현재 버전으로 취급합니다.

### 페더레이션 프로필 예시

```json configs/production.json
{
  "version": "1.0",
  "authentication": {
    "type": "oidc_federation",
    "federation_rule_id": "fdrl_...",
    "service_account_id": "svac_...",
    "identity_token": {
      "source": "file",
      "path": "/var/run/secrets/anthropic.com/token"
    }
  },
  "organization_id": "00000000-0000-0000-0000-000000000000",
  "workspace_id": "wrkspc_...",
  "base_url": "https://api.anthropic.com"
}
```

`authentication.identity_token`이 생략되면 SDK는 환경의 `ANTHROPIC_IDENTITY_TOKEN_FILE` 또는 `ANTHROPIC_IDENTITY_TOKEN`으로 폴백합니다.

## OAuth 범위

페더레이션 규칙에 설정한 `oauth_scope`는 발급된 액세스 토큰이 호출할 수 있는 Claude API 엔드포인트를 결정합니다.

| 범위                         | 접근 권한 부여 대상                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace:developer`      | 규칙의 워크스페이스에 있는 모든 비관리 Claude API 엔드포인트: [Messages](https://platform.claude.com/docs/ko/api/messages)(스트리밍 및 토큰 계산 포함), [Models](https://platform.claude.com/docs/ko/api/models/list), [Managed Agents](https://platform.claude.com/docs/ko/managed-agents/overview) 및 해당 세션, [Files](https://platform.claude.com/docs/ko/build-with-claude/files), [Skills](https://platform.claude.com/docs/ko/build-with-claude/skills-guide). 이는 동일한 워크스페이스의 워크스페이스 API 키가 가진 액세스와 일치합니다. |
| `workspace:inference`      | 규칙의 워크스페이스에 있는 추론 엔드포인트: [Messages](https://platform.claude.com/docs/ko/api/messages)(스트리밍 및 토큰 계산 포함), [Models](https://platform.claude.com/docs/ko/api/models/list), [OpenAI 호환 채팅 엔드포인트](https://platform.claude.com/docs/ko/cli-sdks-libraries/libraries/openai-sdk). Claude를 호출하기만 하면 되고 Files, Skills 또는 기타 리소스를 관리할 필요가 없는 워크로드에 사용하세요.                                                                                                                               |
| `workspace:manage_tunnels` | [MCP 터널 API](https://platform.claude.com/docs/ko/agents-and-tools/mcp-tunnels/reference#tunnels-api): 터널 생성, 나열 및 가져오기, CA 인증서 등록 및 보관, 터널 토큰 공개 및 회전, 터널 보관. Console의 터널 생성 모달 창은 이를 통해 규칙을 생성할 때 이 범위를 잠급니다.                                                                                                                                                                                                                                                               |
| `org:admin`                | [Admin API](https://platform.claude.com/docs/ko/manage-claude/admin-api)에 대한 전체 액세스(조직 구성원, 초대, 워크스페이스, API 키 등). OAuth `org:admin` 토큰은 `workspace:developer` 또는 `workspace:inference`로 범위가 지정된 규칙만 생성하거나 수정할 수 있으며, 다른 범위를 가진 규칙을 뒷받침하는 발급자를 업데이트할 수 없습니다. [제약 조건](https://platform.claude.com/docs/ko/manage-claude/wif-admin-api#permissions-and-constraints)을 참조하세요.                                                                                                     |

토큰의 범위를 벗어난 엔드포인트에 대한 요청은 HTTP 403을 반환합니다. 더 세분화된 범위(리소스별 또는 읽기 대 쓰기)는 현재 사용할 수 없습니다.

### 권한 경계

페더레이션 규칙의 `oauth_scope`는 상한선입니다. 발급된 토큰은 이를 절대 초과할 수 없습니다. 대상 서비스 계정의 `organization_role`(`developer` 또는 `admin`)은 어떤 범위를 부여할 수 있는지 결정하므로, `org:admin`을 부여하는 규칙은 `organization_role=admin`인 서비스 계정을 대상으로 해야 합니다. 유효 권한은 규칙의 범위와 서비스 계정의 역할의 교집합입니다.

| 규칙 `oauth_scope`      | 서비스 계정 `organization_role` | 유효 권한                                                                                                                                                                           |
| --------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace:developer` | `admin`                    | 규칙의 워크스페이스에서만 Claude API 액세스. 범위가 역할보다 아래로 토큰을 제한합니다.                                                                                                                           |
| `org:admin`           | `admin`                    | 전체 Admin API 액세스(조직 구성원, 초대, 워크스페이스, API 키 등)에서 OAuth 호출자 예외를 뺀 것. [제약 조건](https://platform.claude.com/docs/ko/manage-claude/wif-admin-api#permissions-and-constraints)을 참조하세요. |

## 검증 규칙

Anthropic은 발급자와 규칙을 생성하거나 업데이트할 때, 그리고 교환 시점에 들어오는 JWT를 검증할 때 이러한 제약 조건을 적용합니다.

전체 매개변수 세부 정보와 응답 스키마는 [서비스 계정 API 참조](https://platform.claude.com/docs/ko/api/organization/service_accounts), [페더레이션 발급자 API 참조](https://platform.claude.com/docs/ko/api/organization/federation/issuers), [페더레이션 규칙 API 참조](https://platform.claude.com/docs/ko/api/organization/federation/rules)를 참조하세요.

### 리소스 필드

| 필드                          | 제약 조건                                                                                                                                                                                                  |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 발급자, 규칙 및 서비스 계정 `name`     | `^[a-z0-9-]+$`와 일치해야 하며, 길이는 1\~255자입니다.                                                                                                                                                               |
| `workspace_id`              | `applies_to_all_workspaces`가 true가 아닌 한 생성 시 필수입니다. 이 규칙에 따라 발급된 토큰에 할당량, 청구 및 속도 제한이 적용되는 워크스페이스(`wrkspc_...`)입니다. 동일한 조직의 워크스페이스여야 하며, 대상 서비스 계정이 해당 워크스페이스의 구성원이어야 합니다.                             |
| `applies_to_all_workspaces` | 불리언. 하나를 지정하는 대신 조직의 모든 워크스페이스에서 규칙을 활성화하려면 `true`로 설정하세요. 생성 시 이것 또는 `workspace_id` 중 하나가 필수입니다.                                                                                                      |
| `token_lifetime_seconds`    | `60`과 `86400`(1분\~24시간) 사이의 정수. 기본값 `3600`. 이 범위를 벗어난 값은 요청 시점에 거부됩니다. [토큰 수명 및 갱신](https://platform.claude.com/docs/ko/manage-claude/workload-identity-federation#token-lifetime-and-refresh)을 참조하세요. |

### URL 필드

`issuer_url`, `jwks.discovery_base`, `jwks.url` 필드가 검증됩니다:

| 제약 조건 | 세부 사항                                                                |
| ----- | -------------------------------------------------------------------- |
| 스킴    | `https`여야 합니다.                                                       |
| 포트    | `443`(명시적 또는 기본값)이어야 합니다.                                            |
| 호스트   | OIDC 공급자의 공개 DNS 호스트명이어야 합니다. 공개 IP 주소로 해석되어야 하며, IP 리터럴은 허용되지 않습니다. |

URL 검증 실패는 오류 메시지에 필드 이름을 접두사로 붙여 `400 invalid_request_error`를 반환합니다(예: `issuer_url: url must use https scheme`).

<Note>
  URL 제약 조건은 Anthropic이 다이얼하는 URL에만 적용됩니다. `explicit_url` 및 `inline` JWKS 모드에서, 그리고 `jwks.discovery_base`가 설정된 `discovery` 모드에서 `issuer_url`은 JWT `iss` 클레임과 문자열로 비교되며 절대 가져오지 않으므로, 내부 호스트명이나 비표준 포트를 참조할 수 있습니다.
</Note>

### JWT 검증

| 제약 조건   | 세부 사항                                                                                                                                                                                                                                                                  |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 최대 크기   | `assertion` JWT는 최대 16 KiB여야 합니다.                                                                                                                                                                                                                                      |
| 서명 알고리즘 | 비대칭 알고리즘(RSA 및 ECDSA 계열: ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512)만 허용됩니다. HMAC(`HS256`, `HS384`, `HS512`)와 `none`은 거부됩니다.                                                                                                                        |
| 키 ID    | JWT 헤더에는 발급자의 JWKS에 있는 키와 일치하는 `kid`가 있어야 합니다. `kid`가 없는 토큰은 거부됩니다.                                                                                                                                                                                                    |
| 필수 클레임  | `sub`가 있어야 합니다. `iat`가 있어야 하며 미래 시점이 아니어야 합니다. `exp`가 있어야 하며 미래 시점이어야 합니다.                                                                                                                                                                                             |
| 일회성 사용  | `jti` 클레임을 포함한 어설션은 발급자당 한 번만 교환할 수 있습니다. 동일한 `jti`로 교환을 반복하면 재전송(replay)으로 거부됩니다. 발급자의 `check_jti` 필드(기본적으로 활성화됨)가 이 검사를 제어하며, `jti` 클레임이 없는 어설션은 이 검사의 대상이 아닙니다. [페더레이션 발급자 API 참조](https://platform.claude.com/docs/ko/api/organization/federation/issuers)를 참조하세요. |
| 최대 수명   | 토큰의 수명(`exp`에서 `iat`를 뺀 값)은 발급자에 구성된 최대값(기본 1시간, Claude Console에서 발급자별로 구성 가능)을 초과할 수 없습니다.                                                                                                                                                                            |
| 클록 스큐   | `exp`, `nbf`, `iat`에 30초의 허용 오차가 적용됩니다.                                                                                                                                                                                                                                |

## 규칙 매칭 의미론

페더레이션 규칙의 `match` 블록은 들어오는 JWT가 수락되는지 여부를 결정합니다. 채워진 모든 필드는 AND 의미론으로 평가됩니다. JWT는 채워진 모든 매처를 충족해야 합니다. `subject_prefix`, `claims`, `condition` 중 적어도 하나는 설정되어야 합니다. `audience`만 포함하는(또는 매처가 전혀 없는) `match` 블록은 거부됩니다. 이는 발급자의 모든 토큰을 수락하는 규칙을 방지합니다.

| 매처               | 타입                   | 의미론                                                                                                                |
| ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `subject_prefix` | string               | JWT `sub` 클레임과의 정확한 일치. 후행 `*`는 이를 접두사 일치로 만듭니다(`sub` 값은 `*` 앞의 문자로 시작해야 합니다). 대소문자 구분.                            |
| `audience`       | string               | JWT `aud` 클레임은 이 정확한 문자열을 포함해야 합니다. `aud`가 배열인 경우 정확히 일치하는 요소가 하나라도 있으면 검사를 충족합니다.                                 |
| `claims`         | map\<string, string> | 각 키는 최상위 클레임 이름이고 각 값은 필요한 정확한 문자열 값입니다. 중첩, 숫자, 불리언 또는 리스트 및 맵과 같은 복잡한 클레임의 경우 대신 CEL 표현식과 함께 `condition`을 사용하세요. |
| `condition`      | string (CEL)         | `true`로 평가되어야 하는 [CEL](https://cel.dev/) 표현식입니다.                                                                   |

### CEL 평가 환경

`condition` 표현식은 단일 변수에 접근할 수 있습니다:

| 변수       | 타입  | 내용                                               |
| -------- | --- | ------------------------------------------------ |
| `claims` | map | 완전히 디코딩된 JWT 클레임 세트. 중첩된 객체는 중첩된 맵으로 접근할 수 있습니다. |

예시:

```text wrap
claims.sub.startsWith("repo:acme-corp/") && claims.ref in ["refs/heads/main", "refs/heads/release"]
```

<Warning>
  CEL 조건은 보안 경계입니다. 의도한 것보다 더 많은 입력에 대해 `true`로 평가되는 표현식은 의도한 것보다 더 광범위한 액세스를 부여합니다. 제약 조건을 표현할 수 있을 때는 정적 매처를 선호하세요.
</Warning>

## 오류

### 토큰 교환 오류

`POST /v1/oauth/token`은 표준 [API 오류 형식](https://platform.claude.com/docs/ko/api/errors)으로 오류를 반환합니다. SDK는 교환 실패를 `WorkloadIdentityError` (ruby: `Anthropic::Credentials::WorkloadIdentityError`; go: `error`; java: `UnexpectedStatusCodeException`; csharp: `WorkloadIdentityException`; php: `OAuthException`)로 보고하며, 여기에는 HTTP 상태와 응답 본문의 오류 세부 정보가 포함됩니다. 요청 ID는 Python, TypeScript, Ruby에서는 오류 객체에, Java에서는 예외의 응답 헤더에 있습니다. Go에서는 오류 타입이 내부 패키지에 있기 때문에 오류 메시지에만 포함되며, C# 및 PHP 오류에는 포함되지 않습니다.

| 상태  | 오류                      | 원인                                                                                                           | 해결 방법                                                                                                                                                                                                                                         |
| --- | ----------------------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 | `invalid_request_error` | `federation_rule_id`가 잘못되었거나 필수 요청 필드가 누락되었습니다.                                                              | `fdrl_` ID와 요청 본문에 모든 필수 필드가 포함되어 있는지 확인하세요.                                                                                                                                                                                                  |
| 400 | `invalid_request_error` | `workspace_id`가 있지만 올바른 형식의 `wrkspc_...` ID 또는 리터럴 `default`가 아닙니다.                                          | `workspace_id` 값을 수정하세요. 응답 메시지가 예상 형식을 명시합니다.                                                                                                                                                                                                |
| 401 | `authentication_error`  | JWT `iss` 클레임이 등록된 `issuer_url`과 정확히 일치하지 않습니다.                                                              | 후행 슬래시와 스킴을 포함하여 바이트 단위로 비교하세요: `jq -rR 'split(".")[1] \| gsub("-";"+") \| gsub("_";"/") \| @base64d \| fromjson \| .iss' <<< "$JWT"`.                                                                                                        |
| 401 | `authentication_error`  | JWKS 가져오기가 실패했거나, JWKS가 오래되었거나, JWT가 JWKS에 없는 키로 서명되었습니다.                                                    | `inline` 모드의 경우 회전된 키로 발급자를 업데이트하세요. `discovery` 및 `explicit_url`의 경우 JWKS 엔드포인트가 포트 443에서 접근 가능한지 확인하세요. 발급자가 최근에 서명 키를 회전한 경우 [키 회전 및 캐싱](https://platform.claude.com/docs/ko/manage-claude/wif-reference#key-rotation-and-caching)을 참조하세요. |
| 401 | `authentication_error`  | JWT `exp` 클레임이 과거입니다(30초 스큐 윈도우를 넘어서).                                                                       | 신원 공급자가 새로운 토큰을 프로젝션하고 있고 SDK가 토큰 파일을 다시 읽고 있는지 확인하세요.                                                                                                                                                                                        |
| 401 | `authentication_error`  | JWT가 검증되었지만 해당 클레임이 규칙의 `match` 블록을 충족하지 않습니다.                                                               | JWT를 디코딩하고 각 클레임을 규칙과 비교하세요. `subject_prefix`는 대소문자를 구분합니다. `audience`는 정확한 요소 일치가 필요합니다.                                                                                                                                                     |
| 401 | `authentication_error`  | `federation_rule_id`가 존재하지 않거나, 보관되었거나, JWT가 이에 대해 권한이 없습니다(열거를 방지하기 위해 통합됨).                                | Claude Console에서 규칙 ID를 확인하고 규칙이 보관되지 않았는지 확인하세요.                                                                                                                                                                                             |
| 401 | `authentication_error`  | 페더레이션 규칙이 둘 이상의 워크스페이스에 대해 활성화되어 있고 요청이 `workspace_id`를 생략했습니다. 인증 기록 항목에 `workspace_id_required` 사유가 표시됩니다. | 토큰의 범위를 지정하려는 `wrkspc_...` ID로 `ANTHROPIC_WORKSPACE_ID`(또는 원시 요청의 `workspace_id` 본문 필드)를 설정하세요. [토큰 교환 요청](https://platform.claude.com/docs/ko/manage-claude/wif-reference#token-exchange-request)을 참조하세요.                                    |

모든 어설션 거부는 어떤 검사가 실패했는지와 관계없이 고정 메시지 `Authentication failed`와 함께 동일한 불투명한 `401` `authentication_error`를 반환합니다. 구별 가능한 오류는 호출자가 규칙 구성을 탐색할 수 있게 하기 때문입니다. 거부 사유는 Claude Console의 [인증 기록](https://platform.claude.com/settings/workload-identity-federation?tab=history)에 있는 해당 시도 항목에 기록됩니다. 예를 들어 `sub` 클레임이 규칙의 `subject_prefix`를 충족하지 못하면 `match_subject_prefix`, 규칙이 여러 워크스페이스에 걸쳐 있는데 요청이 워크스페이스를 지정하지 않으면 `workspace_id_required`가 기록됩니다. 규칙의 조직이 확인되기 전에 거부된 요청(위의 `400 invalid_request_error` 계열)은 기록 항목을 남기지 않으며, 응답 메시지에 문제가 직접 명시됩니다. 일치하는 기록 항목이 없는 `401`은 대개 `federation_rule_id` 자체가 인식되지 않았음을 의미합니다.

### 일반적인 SDK 측 실패

| 증상                                   | 원인                                                                                                                                                          | 해결 방법                                                                                                                    |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| SDK가 교환 대신 "no credentials"를 보고함     | `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, `ANTHROPIC_IDENTITY_TOKEN[_FILE]` 중 하나가 설정되지 않았고 활성 프로필이 없습니다. | 네 변수를 모두 설정하거나 프로필을 구성하세요.                                                                                               |
| SDK가 페더레이션 대신 API 키로 인증함             | `ANTHROPIC_API_KEY` 또는 `ANTHROPIC_AUTH_TOKEN`이 설정되어 있고 우선순위에서 이깁니다.                                                                                         | 키 또는 토큰 변수를 설정 해제하세요.                                                                                                    |
| 첫 요청에서 `FileNotFoundError`           | `ANTHROPIC_IDENTITY_TOKEN_FILE`의 경로가 존재하지 않습니다. SDK는 교환 시점에 파일을 지연 열기합니다.                                                                                   | 프로젝션된 토큰 볼륨이 마운트되어 있고 경로가 일치하는지 확인하세요.                                                                                   |
| 토큰 교환은 성공하지만 Claude API 요청이 403을 반환함 | 발급된 토큰의 범위가 해당 엔드포인트에 대한 액세스를 부여하지 않습니다.                                                                                                                    | 규칙의 `oauth_scope`를 [OAuth 범위](https://platform.claude.com/docs/ko/manage-claude/wif-reference#oauth-scopes)와 대조하여 확인하세요. |
| 빈 자격 증명으로 인증 실패                      | 자격 증명 환경 변수가 내보내졌지만 빈 문자열로 설정되었습니다. 빈 값도 여전히 우선순위 자리를 이깁니다.                                                                                                 | `VAR=""` 대신 `unset VAR`로 변수를 설정 해제하세요.                                                                                   |

## 실패한 교환 문제 해결

`401` `authentication_error` 응답은 의도적으로 불투명하며 그 메시지는 항상 `Authentication failed`입니다. 거부 사유는 응답이 아니라 인증 기록에 기록됩니다.

<Tip>
  Claude Console의 [인증 기록 페이지](https://platform.claude.com/settings/workload-identity-federation?tab=history)부터 시작하세요. 최근 교환 시도는 평가된 발급자와 규칙, 검사된 JWT 클레임, 그리고 어떤 검증 단계가 실패했는지를 표시하며, 이는 일반적으로 다음 검사들을 단축시킵니다.
</Tip>

흔한 불투명 실패 중 하나는 재생된 어설션입니다. `jti` 클레임을 가진 어설션은 [한 번만 교환](https://platform.claude.com/docs/ko/manage-claude/wif-reference#jwt-verification)할 수 있으므로, 동일한 JWT를 다시 보내는 워크로드(재시도 루프 또는 회전되지 않은 토큰을 다시 읽는 갱신)는 두 번째 교환에서 거부됩니다. 인증 기록 페이지는 이러한 시도를 `jti_reused` 사유로 표시합니다. 해결책은 각 교환마다 새로운 어설션을 발급하는 것입니다.

JWT 자체에서 디버깅해야 하는 경우 다음 검사를 순서대로 진행하세요:

<Steps>
  <Step title="JWT 디코딩">
    보낸 어설션을 디코딩하여 각 클레임을 발급자 및 규칙 구성과 비교할 수 있도록 하세요:

    ```bash cURL
    jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson' <<< "$JWT"
    ```
  </Step>

  <Step title="iss가 발급자와 일치하는지 확인">
    디코딩된 `iss` 클레임은 스킴, 포트 및 후행 슬래시를 포함하여 등록된 `issuer_url`과 바이트 단위로 일치해야 합니다. 단일 문자의 불일치도 검증에 실패합니다.
  </Step>

  <Step title="aud가 규칙과 일치하는지 확인">
    디코딩된 `aud` 클레임은 규칙의 `audience` 값을 정확한 일치로 포함해야 합니다. `aud`가 배열인 경우 한 요소가 정확히 일치해야 합니다.
  </Step>

  <Step title="sub 및 각 claims 항목 확인">
    `sub`를 규칙의 `subject_prefix`와 비교하세요(대소문자 구분. 후행 `*`는 접두사 일치이고, 그 외에는 정확한 일치입니다). 규칙의 `claims` 맵에 있는 모든 키를 동일한 이름의 최상위 클레임과 비교하세요.
  </Step>

  <Step title="exp, nbf, iat 확인">
    `exp`는 미래여야 하고 `nbf`/`iat`는 30초 스큐 윈도우 내에서 과거여야 합니다. 워크로드 호스트의 클록이 드리프트된 경우 그 외에는 유효한 토큰이 거부됩니다.
  </Step>

  <Step title="JWKS 접근 가능성 확인">
    `discovery` 모드의 경우 포트 443의 공개 HTTPS를 통해 `<jwks.discovery_base or issuer_url>/.well-known/openid-configuration`을 가져오고 `jwks_uri`가 해석되는지 확인하세요. `explicit_url`의 경우 JWKS URL을 직접 가져오세요. `inline`의 경우 키를 등록한 이후 발급자의 서명 키가 회전되지 않았는지 확인하세요.

    발급자가 서명 키를 회전하고 즉시 그것으로 서명을 시작한 경우, Anthropic의 JWKS 캐시가 새로 고쳐지는 동안 최대 1분간 교환이 실패할 수 있습니다. [키 회전 및 캐싱](https://platform.claude.com/docs/ko/manage-claude/wif-reference#key-rotation-and-caching)을 참조하세요.
  </Step>
</Steps>

## JWKS 소스 모드

페더레이션 발급자를 등록할 때 `jwks` 필드는 Anthropic이 해당 발급자의 JWT 서명을 검증하는 데 사용되는 공개 키를 얻는 방법을 제어합니다. 이는 `type`을 키로 하는 구별된 유니온입니다:

| `jwks.type`       | `jwks` 형태                                                                                                                 | 동작                                                                                                                              | 사용 시점                                                                                                         |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `discovery` (기본값) | `{ "type": "discovery", "discovery_base": "https://..." }` (`discovery_base`는 선택 사항. 디스커버리 URL이 `issuer_url`과 다를 때 설정하세요) | Anthropic이 `<discovery_base or issuer_url>/.well-known/openid-configuration`을 가져오고, 디스커버리 문서에서 `jwks_uri`를 읽고, 거기서 JWKS를 가져옵니다. | IdP가 공개 인터넷에서 표준 OIDC 디스커버리 문서를 제공합니다. 대부분의 관리형 공급자(EKS, GKE, Cloud Run, GitHub Actions, Entra ID)가 이를 지원합니다. |
| `explicit_url`    | `{ "type": "explicit_url", "url": "https://..." }`                                                                        | Anthropic이 `url`에서 JWKS를 직접 가져옵니다. `issuer_url`은 JWT `iss` 클레임과의 문자열 비교에만 사용되며 절대 다이얼되지 않습니다.                                   | IdP가 디스커버리 문서를 제공하지 않거나, 디스커버리는 내부 전용이지만 JWKS는 공개적으로 접근 가능합니다.                                                |
| `inline`          | `{ "type": "inline", "keys": [...] }`                                                                                     | JWK 객체 배열을 인라인으로 제공합니다(래퍼 객체가 아닌 JWKS 문서의 `keys` 배열). Anthropic은 아웃바운드 요청을 하지 않습니다. `issuer_url`은 `iss` 비교에만 사용됩니다.             | 에어갭 환경, 클러스터 내부 발급자 URL을 가진 자체 관리형 Kubernetes 클러스터, 또는 키 회전에 대한 명시적 제어를 원할 때.                                 |

구별된 유니온은 구성상 동반 필드를 상호 배타적으로 만듭니다. `discovery`와 `explicit_url` 모두 프라이빗 CA에서 TLS를 제공하는 발급자를 위한 선택적 `ca_cert_pem` 문자열도 받습니다.

### 키 교체 및 캐싱

`discovery` 및 `explicit_url` 모드에서 Anthropic은 가져온 JWKS를 캐시합니다. 신원 공급자가 새로운 서명 키를 게시하고 즉시 그것으로 토큰 서명을 시작하면, 해당 토큰을 제시하는 교환은 캐시가 새로 고쳐지는 동안 최대 1분간 서명 오류로 실패할 수 있습니다.

이 윈도우를 피하려면 신원 공급자가 새로운 서명 키로 토큰 서명을 시작하기 최소 15분 전에 JWKS에 새로운 서명 키를 게시하고, 대체된 키로 서명된 토큰이 만료될 때까지 해당 키를 JWKS에 유지하세요. 관리형 신원 공급자는 일반적으로 이 규율을 스스로 따릅니다. 자체 발급자(자체 관리형 Kubernetes 클러스터, SPIRE OIDC 디스커버리 공급자, 또는 구성된 회전 주기를 가진 Okta 사용자 지정 권한 부여 서버)를 운영하는 경우, 회전 정책이 첫 사용 전에 새로운 키를 게시하는지 확인하세요.

<Warning>
  `inline` 모드에서는 자동 키 새로 고침이 없습니다. 신원 공급자가 서명 키를 회전하면 새로운 JWKS로 발급자 구성을 업데이트해야 하며, 그렇지 않으면 모든 토큰 교환이 서명 검증에 실패합니다.
</Warning>
