# MCP Hub OAuth 2.0 표준 준수 명세

> **대상**: 고객사 보안·감사·조달팀 / MCP 클라이언트 개발자
> **버전**: 2026-07-25 기준
> **참고**: MCP 전반 준수는 별도 문서 [MCP 표준 준수 명세](/guides/mcp-spec-compliance)

WRKS MCP Hub 가 어떤 표준 (RFC) 을 준수하고, 어떤 부분에서 의도적으로 확장·비준수 하는지 정리한 문서. 대기업 조달 시 "OAuth 구현이 표준 준수하냐" 문의에 대한 근거 자료이자, MCP 클라이언트 (WRKS AI 등) 개발자가 통합 시 참조.

---

## 1. 한 눈에 요약

WRKS MCP Hub 는 **OAuth 2.0 Authorization Server 역할** 을 하면서 동시에 **고객사 사내 OAuth 앱 (Google Workspace / Microsoft Entra ID 등) 의 broker** 로 동작합니다. MCP 표준 (2025-11-25 revision) 인증 요구사항을 준수하며, 브라우저를 통한 사용자별 로그인 (per-user) 과 서비스 계정 (M2M) 방식을 모두 지원.

| 계층                                       | 담당                         | 준수 표준                                                                                  |
| ------------------------------------------ | ---------------------------- | ------------------------------------------------------------------------------------------ |
| MCP 클라이언트 ↔ Hub                       | Hub 이 AS + Resource Server  | RFC 6749 / 7591 / 7636 / 8414 / 9728 / 6750 / 8707 (lenient) + MCP OAuth 2025-11-25 (부분) |
| Hub ↔ 사내 OAuth 앱 (Google / Entra ID 등) | Hub 이 confidential client   | RFC 6749 §4.1 · §4.4 · §6                                                                  |
| 커넥터 ↔ 사내 백엔드 API                   | 커넥터가 Bearer 헤더 forward | 표준 무관 (고객 API 요구사항 따름)                                                         |

---

## 2. 준수 표준 (Compliance Matrix)

| RFC / 표준               | 제목                                       |    준수    | 비고                                                                                                                                    |
| ------------------------ | ------------------------------------------ | :--------: | --------------------------------------------------------------------------------------------------------------------------------------- |
| **RFC 6749 §4.1**        | Authorization Code Grant                   |     ✅     | client_secret 은 커넥터 host 에 보관 → confidential client                                                                              |
| **RFC 6749 §4.4**        | Client Credentials Grant (M2M)             |     ✅     | 커넥터에서 캐시·자동 갱신                                                                                                               |
| **RFC 6749 §6**          | Refresh Token                              |     ✅     | Rotation 지원 (reuse 감지 시 family 전체 revoke). Upstream 토큰 만료 시 자동 재발급                                                     |
| **RFC 7009**             | Token Revocation                           |  부분 ✅   | Access · refresh 둘 다 지원. Introspection (RFC 7662) 은 미구현                                                                         |
| **RFC 7591**             | Dynamic Client Registration                |     ✅     | 15개 optional field (token_endpoint_auth_method 등) 수용                                                                                |
| **RFC 7636**             | PKCE (Proof Key for Code Exchange)         |     ✅     | **S256 only** — plain method 는 거부. Code challenge 길이·문자셋 엄격 검증                                                              |
| **RFC 8414**             | OAuth 2.0 Authorization Server Metadata    |     ✅     | `.well-known/oauth-authorization-server/mcp/<slug>` 엔드포인트                                                                          |
| **RFC 9728**             | OAuth 2.0 Protected Resource Metadata      |     ✅     | `.well-known/oauth-protected-resource/mcp/<slug>` — MCP spec 필수 요구                                                                  |
| **RFC 6750**             | Bearer Token Usage                         |     ✅     | `Authorization: Bearer <token>` 헤더 검증 + 401 시 `WWW-Authenticate: Bearer error="..."` 응답                                          |
| **RFC 8707**             | Resource Indicators                        | lenient ✅ | `resource` 파라미터 accept + canonical URI 매치 검증 (MCP 2025-11-25 신규 필수). Client 대응 유예 위해 lenient (없으면 backward-compat) |
| **MCP OAuth 2025-11-25** | Model Context Protocol OAuth spec (latest) |  부분 ✅   | Metadata endpoint · DCR · Bearer · WWW-Authenticate · Resource Indicators (lenient) 모두 준수. Client ID Metadata Documents 는 로드맵   |

### 2-1. PKCE 세부 (RFC 7636 §4.6 준수 이유)

Hub 은 MCP 클라이언트 (WRKS AI) 에게 **PKCE S256 을 필수 강제**합니다. 반면 Hub 이 upstream (Google / Entra ID) 에게 요청 시에는 **PKCE 파라미터를 forward 하지 않습니다**. 이유:

- MCP 클라이언트 ↔ Hub 레이어: 클라이언트가 verifier 를 만들고 관리 → PKCE 유효
- Hub ↔ upstream 레이어: Hub 은 confidential client (client_secret 보유) 라 PKCE 불필요. 만약 MCP 클라이언트의 challenge 를 upstream 에 forward 하면 Hub 이 verifier 를 몰라 token 교환 시 `invalid_grant: Missing code verifier` 로 실패 — RFC 7636 §4.6 (server behavior) 대로

### 2-2. RFC 8707 Resource Indicators (lenient 모드)

MCP 2025-11-25 spec 은 client 에게 `resource` 파라미터를 authorize/token 요청 시 필수로 붙이라 요구. Hub 은:

- `resource` 있으면: 이 endpoint 의 canonical URI 와 매치 검증. 불일치 시 400 `invalid_target` (confused deputy 방어)
- `resource` 없으면: backward-compat 로 통과. 아직 대응 안 한 client 를 즉시 breaking 시키지 않음
- Audience binding 자체는 우리 endpoint scoping 으로 이미 강제 (한 endpoint 의 token 은 다른 endpoint 에서 못 씀)
- Metadata 응답에 `resource_indicators_supported: true` 광고

향후 클라이언트 대응 진행되면 strict 모드로 전환 예정.

---

## 3. 확장 · 우리만의 설계

RFC 에 없지만 MCP 사용 패턴을 지원하기 위해 추가한 확장:

### 3-1. Endpoint-scoped Authorization Server

각 MCP endpoint (slug) 를 **독립 OAuth AS 로 취급**. `issuer = https://mcp-hub.wrks.ai/mcp/<slug>` 형식. 이유:

- Multi-tenant 격리 — 한 endpoint 의 client_id 로 다른 endpoint 진입 불가
- MCP 클라이언트 관점에서 endpoint 마다 다른 IdP 처럼 동작 (실제로도 각 endpoint 가 다른 upstream 을 가리킬 수 있음)

### 3-2. Upstream OAuth Broker

Hub 이 **broker** 로 동작해 MCP 클라이언트가 upstream (Google 등) 을 직접 몰라도 됨:

- MCP 클라이언트: Hub 만 OAuth AS 로 인식
- Hub: upstream authorize URL 로 redirect + callback 수신 + code 교환
- 사용자 브라우저: Hub → upstream → Hub 왕복 (표준 OAuth flow)

Google 대응 시 `access_type=offline` + `prompt=consent` 자동 세팅 (refresh_token 확보), Entra ID 는 `offline_access` scope 필수 (사용자 설정).

### 3-3. 4-tier Architecture

일반 3-tier OAuth (Client → AS → Resource) 와 다른 4-tier 구조:

```
MCP Client  ↔  Hub (public SaaS)  ↔  Connector (고객 사내망)  ↔  Upstream IdP + API
```

- Hub 자체는 고객 IdP · client_secret 을 **저장하지 않음** — 커넥터 host 에만 존재
- Upstream token 교환 · refresh 는 커넥터가 수행 (Hub 이 터널로 위임)
- 데이터 residency: 고객 credential 이 SaaS 경계를 넘지 않음

### 3-4. Token 저장 · 암호화

- Upstream (Google / Entra ID) access_token · refresh_token 은 **AEAD (Authenticated Encryption with Associated Data) 방식으로 암호화** 저장. Key rotation 지원
- 개별 토큰별로 서로 다른 암호화 컨텍스트 사용 — 한 토큰 유출로 다른 토큰 복호화 불가
- Hub 발급 access_token 은 **SHA-256 해시만 저장**, 평문 X

---

## 4. 의도적 비준수 / 제한

투명성을 위해 준수 안 하는 부분도 명시:

| 표준                                                                        | 상태   | 이유                                                                                     |
| --------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------- |
| RFC 7662 (Token Introspection)                                              | 미구현 | MCP 사용 패턴에서 client 가 직접 검증하기보다 Hub 이 호출 시점에 검증. 요청 시 추가 가능 |
| RFC 8628 (Device Authorization Grant)                                       | 미구현 | 브라우저 있는 사용자만 대상. IoT · CLI 대응 시 추가 검토                                 |
| RFC 9068 (JWT access token)                                                 | 미준수 | Access token 은 opaque random. Introspection 대신 hash lookup. Confidentiality 우선      |
| Client ID Metadata Documents (draft-ietf-oauth-client-id-metadata-document) | 로드맵 | MCP 2025-11-25 신규 권장. 파트너 요청 시 우선순위 상향                                   |
| SAML 2.0 / OIDC federation                                                  | 미구현 | OAuth 2.0 access delegation 만. Identity federation 이 필요하면 SAML gateway 별도 필요   |

---

## 5. 보안 부가 정보

### 5-1. 전송 보안

- MCP 클라이언트 ↔ Hub: TLS 1.2+
- Hub ↔ 커넥터: **mTLS** (상호 TLS 인증서 검증) + WebSocket over TLS
- 커넥터 ↔ 고객 백엔드: 고객 정책 (내부망이면 HTTP 도 허용, public 이면 HTTPS 강제)

### 5-2. 인증서 관리

- 커넥터 페어링: 짧은 수명 pairing token (한 번만 사용) 으로 client 인증서 발급
- 인증서 rotation: 커넥터 재시작 시 자동 갱신 요청 (신원 검증 후)
- Fatal close codes 로 revoke 즉시 반영

### 5-3. Rate Limiting

OAuth flow 남용 방지:

- Authorize endpoint: IP + endpoint 조합으로 rate limit
- DCR endpoint: endpoint 별 신규 등록 rate limit
- Token endpoint: client_id 별 rate limit

### 5-4. 감사 로그

모든 OAuth 이벤트 (issue / rotate / revoke) 는 append-only 로 기록. 90일 보관 (기본).

---

## 6. 준수 검증 방법

고객사 감사팀이 직접 확인 가능한 방법:

### 6-1. Metadata 응답 검증

```bash
curl https://mcp-hub.wrks.ai/.well-known/oauth-authorization-server/mcp/<slug>
```

RFC 8414 §3 이 요구하는 모든 필드 (`issuer`, `authorization_endpoint`, `token_endpoint`, `grant_types_supported`, `code_challenge_methods_supported`) + `resource_indicators_supported: true` 응답 확인.

### 6-2. Protected Resource Metadata 검증

```bash
curl https://mcp-hub.wrks.ai/.well-known/oauth-protected-resource/mcp/<slug>
```

RFC 9728 §2 응답 형식 준수 확인.

### 6-3. WWW-Authenticate 헤더 검증

```bash
curl -i https://mcp-hub.wrks.ai/mcp/<slug>
```

401 응답에 `WWW-Authenticate: Bearer error="...", resource_metadata="..."` 헤더 포함 확인.

### 6-4. PKCE S256 강제 검증

Authorization URL 에 `code_challenge_method=plain` 으로 요청 시 400 `pkce_S256_required` 반환 확인.

### 6-5. DCR 검증

```bash
curl -X POST https://mcp-hub.wrks.ai/oauth/<slug>/register \
  -H 'Content-Type: application/json' \
  -d '{"redirect_uris":["https://example.com/cb"],"token_endpoint_auth_method":"client_secret_basic"}'
```

201 응답 + `client_id` / `client_secret` 반환 확인.

### 6-6. Resource Indicators (RFC 8707) 검증

```bash
# 다른 endpoint 대상 resource 로 authorize 시도 → 400 invalid_target
curl -i "https://mcp-hub.wrks.ai/oauth/<slug>/authorize?client_id=x&redirect_uri=https://example.com&state=s&code_challenge=$(head -c 32 /dev/urandom | base64 | tr '+/' '-_' | tr -d '=')&code_challenge_method=S256&resource=https://mcp-hub.wrks.ai/mcp/<다른-slug>"
```

---

## 7. 인증·인가 흐름 요약도

```
[사용자 브라우저]
      │
      │  ① 도구 호출 → WRKS AI 가 로그인 필요 판단
      ▼
[WRKS AI (MCP client)]
      │
      │  ② DCR 로 client_id 자동 발급
      │  ③ authorize URL 로 브라우저 redirect (resource 파라미터 포함 권장)
      ▼
[Hub 의 authorize endpoint]
      │
      │  ④ 요청 상태 저장 (state + PKCE challenge + resource 검증)
      │  ⑤ upstream authorize URL 로 302
      ▼
[사내 IdP (Google / Entra ID)]
      │
      │  ⑥ 사용자 로그인 + 권한 승인
      │  ⑦ callback URL 로 code 반환
      ▼
[Hub 의 callback endpoint]
      │
      │  ⑧ 커넥터 터널로 code 교환 요청
      ▼
[커넥터 (사내망)]
      │
      │  ⑨ upstream `/token` 호출 (client_secret 사용)
      │  ⑩ access + refresh token 획득
      ▼
[Hub]
      │
      │  ⑪ 암호화 저장 (개별 컨텍스트로 격리)
      │  ⑫ Hub 자체 code 발급 → WRKS AI callback 으로 리다이렉트
      ▼
[WRKS AI]
      │
      │  ⑬ Hub `/token` 으로 access token 획득 (resource 파라미터 포함 권장)
      │  ⑭ 도구 호출 시 Authorization: Bearer 로 사용
      ▼
[정상 도구 사용 시작]
```

---

## 8. 추가 자료

- MCP 전반 표준 준수: [MCP 표준 준수 명세](/guides/mcp-spec-compliance)
- 심화 위협 모델 · 사고 대응 절차 · pen test 체크리스트: **별도 문서로 감사 요청 시 전달** (내부 아키텍처 세부 포함으로 공개 배포 X)
- 문의: WRKS 담당자
