AACWorkflow Docs

MCP OAuth 2.1 인증

PKCE, refresh 토큰 로테이션 및 범위 기반 접근 제어로 MCP 클라이언트용 OAuth 2.1 인증 서버 구축.

AACWorkflow는 **MCP (Model Context Protocol)**을 통해 OAuth 2.1 인증으로 API를 노출합니다. Claude, ChatGPT 커넥터 및 사용자 정의 도구를 포함한 외부 MCP 클라이언트는 OAuth 서버를 통해 인증하여 (사용자, 워크스페이스) 쌍에 바인딩된 범위 제한, 갱신 가능한 액세스 토큰을 획득합니다.

개요

OAuth 서버는 Authorization Code grantPKCE (Proof Key for Code Exchange), refresh 토큰 로테이션 및 동적 클라이언트 등록으로 구현합니다. 이는 다음을 보장합니다:

  • 사용자 제어 — 사용자가 동의 화면을 통해 워크스페이스 접근을 명시적으로 부여
  • 범위 기반 액세스 — 클라이언트가 필요한 리소스 선언 (issue, 댓글, 에이전트 등)
  • 토큰 생명주기 — 단기 유효 액세스 토큰 (~15분) 및 갱신 가능한 장기 토큰
  • 재사용 감지 — refresh 토큰 재생은 전체 토큰 족을 철회, 토큰 누출 감지

OAuth 흐름

1. 클라이언트 등록

클라이언트는 한 번 등록:

POST /oauth/register
Content-Type: application/json

{
  "client_name": "My MCP Tool",
  "redirect_uris": ["http://localhost:5000/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "none"
}

client_idclient_secret 반환 (공개 클라이언트는 비밀 없음).

2. 인증 코드 흐름

클라이언트가 로그인 시작:

GET /oauth/authorize?
  client_id=<id>&
  redirect_uri=http://localhost:5000/callback&
  response_type=code&
  scope=issues:read+issues:write+comments:read&
  code_challenge=<sha256_hash>&
  code_challenge_method=S256

사용자가 요청 범위와 워크스페이스를 나열하는 동의 화면을 봅니다. 승인 시 인증 코드 획득 (10분 유효):

HTTP 302
Location: http://localhost:5000/callback?code=<auth_code>&state=<state>

3. 코드를 토큰으로 교환

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=<auth_code>&
client_id=<id>&
code_verifier=<original_plain_challenge>&
redirect_uri=http://localhost:5000/callback

반환:

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "<refresh_token>",
  "scope": "issues:read issues:write comments:read"
}

액세스 토큰은 다음을 포함하는 서명된 JWT:

  • sub — 사용자 ID
  • wsid — 워크스페이스 ID
  • scope — 공백 구분 범위
  • exp — 만료 (900초)

4. Refresh 토큰 로테이션

액세스 토큰 만료 시 refresh 토큰 사용:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=<refresh_token>&
client_id=<id>

새 액세스 토큰 새 refresh 토큰 반환. 이전 refresh 토큰 자동 무효화. 이전 refresh 토큰 재생 시 서버가 전체 토큰 족을 철회, 토큰 누출 가능성 신호.

범위

범위 토큰은 클라이언트가 액세스할 수 있는 리소스 정의:

범위접근
issues:readIssue, 상태, 타임라인 읽기
issues:writeIssue 생성, 업데이트; 상태 변경
comments:readIssue 댓글 및 스레드 읽기
comments:write댓글 생성 및 편집
agents:read에이전트 나열, 세부정보 보기
agents:write에이전트 생성, issue에 할당
runtimes:read런타임 상태 및 로그 조회
autopilot:run자동조종장치 트리거
dashboard:read사용량 및 품질 대시보드 조회

클라이언트는 인증 중 범위 부분집합 요청. 토큰은 요청한 범위로만 발급. 갱신이 범위를 좁히면 새 토큰은 원본보다 적은 범위 보유.

엔드포인트

메서드경로목적
GET/.well-known/oauth-authorization-serverRFC 8414 메타데이터 검색
GET/oauth/authorize동의 UI; 인증 코드 발급
POST/oauth/token코드-토큰 및 갱신 흐름
POST/oauth/register동적 클라이언트 등록 (RFC 7591)
POST/oauth/revokeRFC 7009 토큰 취소

검색

클라이언트가 인증 서버 메타데이터 검색:

GET /.well-known/oauth-authorization-server

반환:

{
  "issuer": "https://aacworkflow.example.com",
  "authorization_endpoint": "https://aacworkflow.example.com/oauth/authorize",
  "token_endpoint": "https://aacworkflow.example.com/oauth/token",
  "registration_endpoint": "https://aacworkflow.example.com/oauth/register",
  "revocation_endpoint": "https://aacworkflow.example.com/oauth/revoke",
  "scopes_supported": [
    "issues:read", "issues:write", "comments:read", "comments:write",
    "agents:read", "agents:write", "runtimes:read", "autopilot:run", "dashboard:read"
  ],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["none"],
  "code_challenge_methods_supported": ["S256"]
}

보안 고려사항

PKCE 필수code_challenge_method=S256 필요; plain 미수용.

  • 정확한 리다이렉트 URI 매칭 — 리다이렉트 URI는 등록 값에 대해 정확히 검증 (접두사 매치 없음)
  • 인증 코드 일회용 — 인증 코드는 한 번만 교환 가능; 두 번째 시도 실패
  • Refresh 토큰 로테이션 — 각 갱신은 이전 refresh 토큰 무효화, 토큰 누출 감지 및 대응
  • 단기 유효 액세스 토큰 — 액세스 토큰은 15분 후 만료; 클라이언트는 갱신으로 연장
  • 안전한 토큰 저장 — 토큰은 미보호 상태에서 해시 (개인 액세스 토큰과 동일 KDF); 평문 토큰 미보관

접근 취소

언제든 토큰 (액세스 또는 refresh) 취소:

POST /oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=<access_or_refresh_token>&
client_id=<id>

refresh 토큰 취소는 계단식: 그 refresh에서 발급한 모든 액세스 토큰도 무효화.

MCP와의 통합

외부 MCP 서버는 OAuth 토큰을 사용하여 AACWorkflow 도구 호출. 토큰이 Authorization 헤더에 전달:

GET /api/issues
Authorization: Bearer <access_token>

서버는 토큰 서명 검증, 만료 확인 및 범위 강제. 도구가 issues:write 필요하지만 토큰이 issues:read만 가지면 호출이 403 Forbidden으로 거부.

감사 로그

모든 OAuth 이벤트 (로그인, 토큰 발급, 갱신, 취소, 재사용 감지)는 규정 준수 및 조사를 위해 감사 로그에 기록됨.