OAuth 2.1 초안에서 PKCE와 보안 요구사항 읽기
OAuth 2.1은 아직 IETF 초안입니다. 현재 보안 기준인 RFC 9700과 초안의 PKCE, 리다이렉트 URI, 리프레시 토큰 범위를 구분해 실제 배포 점검에 연결합니다.
발행·오류 제보: infostoa · 편집 기준
이 글의 개별 작성자와 전문 검토자 정보는 제공되지 않습니다.
먼저 상태를 구분하세요
2026년 10월 12일 확인한 IETF Datatracker의 draft-ietf-oauth-v2-1-16은 Active Internet-Draft입니다. RFC 상태는 지정되지 않았고, IETF 문서는 작업 중인 초안이므로 확정 규격처럼 인용하면 안 됩니다. 운영 기준으로 당장 적용할 내용은 이미 발행된 OAuth 보안 모범 사례 RFC 9700에서 확인하고, OAuth 2.1의 통합 방향은 바뀔 수 있는 초안으로 읽으세요.
PKCE가 묶는 것과 묶지 않는 것
PKCE는 인가 코드 요청과 토큰 교환을 일회성 code_verifier로 연결합니다. 클라이언트는 요청마다 예측하기 어려운 검증자를 만들고 code_challenge를 인가 요청에 보냅니다. 토큰 엔드포인트에서 검증자를 제시해야 코드를 교환할 수 있어, 코드만 가로챈 공격자가 자기 검증자로 토큰을 받는 위험을 줄입니다. PKCE는 로그인 이후 탈취된 액세스 토큰을 보호하거나 브라우저 XSS를 막지는 않습니다.
현재 RFC 9700은 공개 클라이언트에 PKCE 사용을 MUST로, 기밀 클라이언트에도 사용을 RECOMMENDED로 둡니다. OAuth 2.1 초안의 기본 인가 코드 흐름도 PKCE 매개변수를 포함하며, §7.5.1의 특정 요건을 만족하는 경우에만 code_challenge 예외가 있습니다. 초안은 검증자를 노출하지 않는 방법을 요구하고 현재 그 방법은 S256뿐이라고 적습니다. 이는 모든 OAuth grant에 PKCE를 요구한다거나 클라이언트 인증용 시크릿을 대체한다는 뜻이 아닙니다. PKCE의 역할은 클라이언트 인증과 별개입니다.
배포 설정을 읽는 네 가지 기준
| 항목 | 현재 발행된 기준 | OAuth 2.1 초안의 방향 | 배포 시 확인 |
|---|---|---|---|
| PKCE | RFC 9700은 공개 클라이언트에 MUST, 기밀 클라이언트에 RECOMMENDED | 기본 인가 코드 흐름에 포함, §7.5.1 예외 및 S256 범위 확인 | SPA·네이티브 앱에서 원문 검증자는 클라이언트에만 보관하고, 인가 요청에는 S256 challenge만 보내며 토큰 교환 때 토큰 엔드포인트에 검증자를 제출하는지, 서버 앱의 클라이언트 인증은 따로 유지되는지 |
| 리다이렉트 URI | RFC 9700 §2.1은 사전 등록 URI와 정확한 문자열 비교를 MUST로 규정. 네이티브 앱의 localhost 포트는 예외 | 같은 RFC 9700 규칙을 참조 | 등록 URI와 실제 요청의 비교 규칙, 네이티브 loopback 예외를 제공자 문서에서 확인 |
| 공개 클라이언트 리프레시 토큰 | RFC 9700 §2.2.2는 sender constraint 또는 rotation을 MUST로 요구 | 초안은 공개 클라이언트 토큰을 sender-constrained 또는 일회용으로 요약 | 제공자가 실제로 재사용 탐지·폐기를 어떻게 구현하는지와 재인증 복구 흐름 확인 |
| 레거시 grant | RFC 9700은 암시적 grant 사용을 SHOULD NOT으로 권고하며 명시된 완화 조건에 예외 가능성을 둡니다. 비밀번호 자격 증명 grant 사용은 MUST NOT으로 금지합니다. | 둘 다 초안에서 제외 | 현재 앱·서버 로그에서 해당 grant 사용 여부와 대체 Authorization Code 흐름을 점검 |
localhost 예외는 임의 와일드카드 허용이 아닙니다. RFC 9700은 네이티브 앱의 localhost 리다이렉트에서 포트 번호만 예외로 둡니다. 그 밖의 등록·비교 규칙은 정확한 범위를 제공자 설정과 RFC 원문으로 확인하세요.
가상의 배포 점검 예
가령 팀이 SPA와 서버 렌더링 앱을 함께 운영한다고 합시다. 설정 화면에서 두 앱의 grant와 클라이언트 유형을 먼저 기록합니다. SPA의 인가 요청에는 원문 code_verifier가 아니라 S256으로 만든 code_challenge와 code_challenge_method=S256만 보내는지 살핍니다. 원문 검증자는 클라이언트에 보관하고, 인가 코드를 교환할 때 토큰 엔드포인트에만 제출하는지 확인합니다. 서버 앱의 client authentication은 PKCE와 별도로 유지되는지도 확인합니다. 이어 등록된 redirect URI와 실제 요청을 대조하되, 네이티브 loopback의 포트 예외를 일반 웹 URI에 넓히지 않습니다. 공개 클라이언트의 refresh token 재사용 시 기존 토큰 폐기 또는 sender proof 확인이 발생하는지도 제공자 로그와 문서로 확인합니다. 이는 설명을 위한 가상 점검 순서이며 특정 제품에서 실행하거나 검증한 결과가 아닙니다.
채택 판단
OAuth 2.1을 제품 설정의 단일 체크박스로 간주하지 마세요. RFC 9700에 이미 있는 보안 요구를 기준으로 앱 유형별 현재 설정을 확인하고, 초안 조항은 버전과 예외를 기록해 추적하는 편이 안전합니다. 특히 PKCE는 코드 탈취 완화책이지 토큰 저장 설계나 XSS 대응을 대신하지 않습니다. 브라우저 토큰 보관 방식은 별도 위협 모델로 결정해야 합니다.