티스토리 뷰
1. MCP 서버의 인증 과정에 대한 이해(MCP Authorization flow)
[ MCP 인증의 필수 유무 ]
MCP 공식 문서에 따르면, MCP 인증은 선택 사항이다.

하지만 다음의 상황에는 MCP 인증이 강하게 요구된다고 한다.
- user-specific한 데이터에 접근하는 경우
- 누가 어떤 행동을 했는지에 대한 감사가 필요한 경우
- 사용자 동의가 필요한 API에 대한 접근 권한 관리가 필요한 경우
- 엄격한 권한 통제가 필요한 enterprise 환경을 위해 개발하는 경우
- 사용자 단위로 rate limit 구현 혹은 사용량 트래핑이 필요한 경우
따라서 필요에 맞게 MCP 인증은 반드시 필요한 상황이 올테니, 알아둘 필요가 있다.
[ MCP 인증 플로우 ]
만약 MCP 인증을 도입했다면, MCP 인증 플로우는 다음과 같다.
sequenceDiagram
autonumber
participant Client as MCP 클라이언트
participant Server as MCP 서버<br/>(Resource Server)
participant AS as 인증 서버<br/>(Authorization Server)
participant User as 사용자
Note over Client,Server: 1단계: 초기 핸드셰이크
Client->>Server: MCP 서버 연결 요청
Server-->>Client: 401 Unauthorized<br/>WWW-Authenticate 헤더, resource_metadata
Note over Client,Server: 2단계 · 보호 리소스 메타데이터(PRM) 탐색
Client->>Server: /.well-known/oauth-protected-resource 요청
Server-->>Client: PRM 문서 반환<br/>(authorization_servers, scopes_supported)
Note over Client,AS: 3단계 · 인증 서버 탐색
Client->>AS: OIDC / OAuth 2.0 메타데이터 요청
AS-->>Client: 메타데이터 반환<br/>(authorization, token, registration 엔드포인트)
Note over Client,AS: 4단계 · 클라이언트 등록
alt 사전 등록(Pre-registered)
Client->>Client: 내장된 등록 정보 사용
else 동적 등록(DCR)
Client->>AS: registration_endpoint로 등록 요청
AS-->>Client: client_id 등 등록 정보 반환
end
Note over Client,User: 5단계 · 사용자 인가
Client->>User: 브라우저로 /authorize 열기
User->>AS: 로그인 및 권한 동의(consent)
AS-->>Client: authorization code로 리다이렉트
Client->>AS: code 교환 (PKCE)
AS-->>Client: access_token + refresh_token
Note over Client,Server: 6단계 · 인증된 요청
Client->>Server: 요청 + Authorization: Bearer 토큰
Server->>Server: 토큰 검증<br/>(introspection / 서명·aud·scope 확인)
Server-->>Client: 정상 응답 (권한 확인 시)
1. 초기 핸드셰이크
MCP 클라이언트가 MCP 서버로의 접근을 시도했을 때, 인증되지 않은 상태라면 MCP 서버는 요청을 401 Unauthorized 상태로 응답하며, 이때 헤더에 WWW-Authenticate 헤더와 resource_metadata를 포함시킨다. resource_metadata는 WWW-Authenticate 헤더 안의 파라미터로, 클라이언트에게 "인증 정보가 어디 있는지" 알려주는 URI 포인터이다.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp", resource_metadata="<https://mangkyu-auth.com/.well-known/oauth-protected-resource>"
이 URI는 Protected Resource Metadata (PRM) 문서를 가리킨다. PRM은 RFC 9728에 정의된 표준으로, “보호된 리소스(MCP 서버)에 접근하려면 어떻게 인증해야 하는지"를 기계가 읽을 수 있게 담아놓은 JSON 문서이다.
- 인증 서버(Authorization Server) 메타데이터: "나는 토큰을 어떻게 발급하는가"
- 보호 리소스(Protected Resource) 메타데이터: "나에게 접근하려면 어떤 인증이 필요한가"
MCP 서버는 자기 자신이 "보호된 리소스"이므로, 클라이언트에게 자신의 인증 요구사항을 알려주기 위해 PRM 문서를 제공한다. 아직 인증되지 않은 MCP 클라이언트라면, resource_metadata를 통해 인증을 위한 정보를 전달해주는 것이다. MCP 서버는 예측 가능한 표준 경로로(/.well-known/oauth-protected-resource), resource_metadata를 통해 PRM을 제공한다.
https://mangkyu-mcp.com/.well-known/oauth-protected-resource
2. PRM 탐색
헤더를 통해 전달된 URI로 PRM 문서를 얻어올 수 있다. PRM은 보통 3가지 필드로 다음과 같이 구성되며, 실제로는 이보다 더 많은 필드를 담을 수 있다. 전체 목록은 RFC 9728 §3.2에서 참고할 수 있다.
- resource : 이 메타데이터가 설명하는 보호된 리소스의 식별자(서버 URI)
- authorization_servers: 이 리소스에 쓸 토큰을 발급해줄 수 있는 인증 서버 목록, 여러 개일 수 있음
- scopes_supported: 이 리소스가 이해하는 스코프(권한 범위) 목록
{
"resource": "<https://mangkyu-mcp.com/mcp>",
"authorization_servers": ["<https://mangkyu-auth.com>"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
3. 인증 서버 탐색
클라이언트는 PRM의 authorization_servers를 보고 각각의 인증 서버가"무엇을 할 수 있는지, 각 엔드포인트가 어디인지"를 알아낸다. 그리고 그 중 하나의 인증 서버를 선택하고, 표준 메타데이터 URI를 만들어, 인증 서버가 무엇을 지원하느냐에 따라 다음 둘 중 하나의 엔드포인트로 요청을 보낸다.
- OAuth 2.0 Authorization Server Metadata: https://mangkyu-auth.com/.well-known/oauth-authorization-server
- OpenID Connect (OIDC) Discovery: https://mangkyu-auth.com/.well-known/openid-configuration
위 둘은 모두 인증 서버가 자신의 정보(엔드포인트 주소, 지원 기능 등)를 표준 형식으로 공개하는 "메타데이터 발견(discovery)" 방법이다. 두 방식은 기본적으로 클라이언트가 인증 서버 설정을 미리 하드코딩하지 않아도, 약속된 경로(.well-known/...)로 요청 한 번 보내면 JSON으로 모든 엔드포인트 정보를 받아올 수 있게 하는 것을 목표로 한다.
만약 "이 클라이언트가 이 리소스에 접근해도 되는가"를 다룬다면, OAuth 2.0 인가 프로토콜 만으로도 충분하다. 하지만 만약 "이 사용자가 누구인가(신원)"까지 다루어야 한다면, OAuth 2.0 위에 얹은 "인증(authentication)" 계층인 OIDC가 필요하다. OIDC는 id_token이라는 신원 정보를 추가로 제공하여 이 문제를 해결한다.
즉, OIDC는 OAuth2.0 방식을 확장하여 신원 정보를 제공해주는 것이다. 따라서 응답 역시 기본적으로 OAuth 2.0과 OIDC가 동일하고, OIDC에 신원 관련 필드(userinfo_endpoint, id_token_signing_alg_values_supported 등)가 추가로 들어갈 뿐이다.
MCP 클라이언트는 인증 서버가 무엇을 지원하는지에 따라 적절한 경로로 요청해서, 어느 쪽이든 결국 같은 목적(엔드포인트 주소 파악)을 달성한다. 그리고 인증 서버로부터 플로우를 완성하는 데 필요한 엔드포인트들을 반환받는데, 통상적으로 다음의 정보들이 포함된다.
- issuer:이 인증 서버의 식별자로, 나중에 토큰의 iss 클레임 검증에 쓰임
- authorization_endpoint: 사용자가 로그인 하는 곳으로, 브라우저로 열림
- token_endpoint: authorization code를 access token으로 교환하는 곳
- registration_endpoint: 클라이언트를 동적으로 등록하는 곳
{
"issuer":"<https://mangkyu-auth.com>",
"authorization_endpoint":"<https://mangkyu-auth.com/authorize>",
"token_endpoint":"",
"registration_endpoint":""
}
4. 클라이언트 등록
OAuth에서 인증 서버는 아무 클라이언트에게나 토큰을 발급하지 않는다. "너는 누구인가(어떤 클라이언트인가)"가 먼저 인증 서버에 등록되어 있어야 클라이언트가 client_id를 활용해 인가 플로우를 진행할 수 있다. 이때 클라이언트가 등록되는 방식은 두 가지가 있다.
- 사전 등록 (Pre-registered): 클라이언트가 특정 인증 서버에 미리 등록돼 있는 경우로, 클라이언트가 등록 정보(client_id 등)를 이미 내장하고 있으므로, 그걸 그대로 사용해 인가 플로우를 진행함
- 동적 클라이언트 등록 (DCR, Dynamic Client Registration): 클라이언트가 인증 서버에 스스로 등록하는 방식으로, 인증 서버가 DCR을 지원해야만 가능함
따라서 클라이언트가 사전에 인증 서버에 등록되어 있지 않다면, 자기 신원을 동적으로 등록하는 과정이 필요한데, 4단계는 이를 위한 단계라고 볼 수 있다. 만약 인증 서버에서 DCR을 지원한다면, 클라이언트는 3단계에서 알아낸 registration_endpoint로 자기 정보를 보내서 등록하게 된다.
- client_name: 클라이언트 이름
- redirect_uris: 인가 코드를 돌려받을 콜백 주소
- grant_types**:** 사용할 OAuth 그랜트 타입 (여기선 authorization code + refresh token)
- response_types: 기대하는 응답 타입 (code = authorization code 방식)
{
"client_name": "My MCP Client",
"redirect_uris": ["<http://localhost:3000/callback>"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
등록이 성공하면 인증 서버는 client_id 등이 담긴 등록 정보를 JSON으로 반환한다.
만약 인증 서버가 DCR을 지원하지 않고, 클라이언트도 사전 등록돼 있지 않다면, 클라이언트 개발자가 최종 사용자에게 클라이언트 정보를 수동으로 입력받는 방법(affordance)을 제공해야 한다. MCP는 이 책임을 클라이언트 개발자에게 넘깁니다.
참고로 MCP는 다양한 클라이언트(VS Code, Claude 등)가 미리 알지 못하는 임의의 서버들에 연결되는 것을 전제로 한다. 클라이언트가 모든 서버에 사전 등록돼 있을 수는 없으므로, DCR이 있으면 처음 보는 인증 서버에도 자동으로 자기를 등록하고 연결할 수 있어 매우 유용하다. 이것이 앞서 얘기한 "하드코딩 없는 자동 발견·연결"이라는 MCP 설계 철학과 맞닿아 있다. 물론 인증 없는 DCR(unauthenticated DCR)은 아무나 인증 서버에 클라이언트를 등록할 수 있으므로, DCR과 함께 신뢰 호스트(trusted hosts) 제한, 등록 감사(audit) 등 조직 상황에 맞는 통제 장치를 함께 둬야 한다.
5. 사용자 인가
이제 실제로 사용자가 개입해 로그인하고 권한에 동의(consent)하고, 토큰을 받아온다. 이 전체 과정은 표준 OAuth 2.1 authorization code + PKCE 규약을 따른다.
- 브라우저로 인가 엔드포인트 열기: 클라이언트가 3단계에서 알아낸 authorization_endpoint를 브라우저로 열음
- 사용자 로그인 & 동의: 사용자가 인증 서버에 로그인하고, 클라이언트가 요청한 권한을 승인함
- authorization code 반환: 인증 서버가 클라이언트로 리다이렉트하면서 authorization code를 함께 넘김 (4단계에서 등록한 redirect_uris로 돌아옴)
- code를 토큰으로 교환: 클라이언트가 이 code를 token_endpoint로 보내 실제 토큰으로 바꿈
6. 인증된 요청
이제 손에 넣은 access_token으로 실제 MCP 서버에 요청하는 마지막 단계이다. 클라이언트 측은 토큰을 Authorization 헤더에 담아 요청한다.
GET /mcp HTTP/1.1
Host: <https://mangkyu-mcp.com>
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
참고 자료
'AI' 카테고리의 다른 글
| [AI] 앤트로픽(Anthropic)이 알려주는 좋은 클로드 코드 스킬(Claude Code Skill) (0) | 2026.03.10 |
|---|---|
| [AI] Claude Code(클로드 코드)의 활용을 극대화해주는 설정과 도구들의 모음(Claude Code Skills, Plugins, ETC) (2) | 2026.03.03 |
| [AI] AI 시대를 맞이하는 개발자의 역할과 작업 방식의 변화 (2) | 2026.02.24 |
| [AI] Claude Code(클로드 코드) 활용을 극대화하기 위한 최신 기술들(Skills, Slack, GitHub Actions, Chrome ETC) (4) | 2025.12.23 |
| [AI] 지금까지의 AI에 대한 사실과 오해 그리고 현실적인 올바른 활용법 (1) | 2025.11.04 |