9.8 KiB
title, source_type, url, archive_url, status, confidence, tags, related_projects, related_branches, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | tags | related_projects | related_branches | created | last_reviewed | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RFC 7636 — Proof Key for Code Exchange by OAuth Public Clients (PKCE) | official-doc | https://datatracker.ietf.org/doc/html/rfc7636 | raw | high |
|
|
|
2026-05-25 | 2026-05-27 |
RFC 7636 — Proof Key for Code Exchange (PKCE)
Layer:
raw/official-docs/— IETF RFC 7636 (Standards Track) 발췌. PKCE 메커니즘의 표준 정의.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-keycloak-patterns | keycloak-patterns root에서 SPA/native 등 public client 패턴이 PKCE를 의무로 채택하는 표준 근거 |
| raw/branch-notes/feature-keycloak-internal-spa-direct-no-google | P2A SPA Direct에서 client secret 없는 public client가 PKCE로 code interception을 방어하는 근거 |
| raw/branch-notes/feature-keycloak-single-ec2-no-google | P3A 단일 EC2 vanilla JS 구현에서 PKCE flow가 baseline인 표준 근거 |
| raw/branch-notes/feature-keycloak-vanilla-js-spa-pkce | vanilla JS SPA의 code_verifier 생성 / S256 challenge 변환 구현 근거 |
| raw/branch-notes/feature-keycloak-pkce-flow-stages | PKCE flow의 (A)~(E) 단계별 분해와 verifier-challenge chain 설계 근거 |
컨텍스트
P2A (Internal SPA + Resource Server) 패턴의 SPA는 public client — client secret을 안전하게 보관할 방법이 없음. 따라서 authorization code 탈취 시 즉시 token 교환이 가능해지는 공격 surface를 막기 위해 PKCE가 의무. "왜 SPA에 PKCE를 강제로 켜야 하나"의 1차 근거.
출처 / Source
- 원본 URL: https://datatracker.ietf.org/doc/html/rfc7636
- 아카이브 URL: (미수집)
- 저자 / 조직: IETF — N. Sakimura (Nomura Research Institute), J. Bradley (Ping Identity), N. Agarwal (Google)
- 발행일: 2015-09 (RFC 7636 Standards Track)
- 관련: RFC 6749 (OAuth 2.0 Core), RFC 8252 (OAuth 2.0 for Native Apps), OAuth 2.1 draft
- 마지막 확인일: 2026-05-27 (WebFetch 재검증 완료 — 5개 quote 중 4개 verbatim MATCH, 1개는 quote 스타일 차이만 있음)
핵심 인용 / Key quotes (verbatim)
[§1 Abstract/Introduction, 2026-05-27 verified MATCH] "OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack."
[§1.1 Protocol Flow, 2026-05-25 capture — quoting style 차이만] "The client creates and records a secret named the code_verifier and derives a transformed version t(code_verifier) (referred to as the code_challenge)."
[§1.1 Protocol Flow, 2026-05-27 verified verbatim with single-quote markers] "The client creates and records a secret named the 'code_verifier' and derives a transformed version 't(code_verifier)' (referred to as the 'code_challenge')."
[§4.2 Client Creates the Code Challenge, 2026-05-27 verified MATCH] "code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))"
[§1.1 Protocol Flow, 2026-05-27 verified MATCH] "The authorization server transforms code_verifier and compares it to t(code_verifier) from (B). Access is denied if they are not equal."
[§1.1 Protocol Flow, 2026-05-27 verified MATCH] "An attacker who intercepts the authorization code at (B) is unable to redeem it for an access token, as they are not in possession of the code_verifier secret."
(2026-05-27 note: 원본 RFC 7636 §1.1 의 "(B)" 단계 인용 출처는 §4.6 이 아닌 §1.1 Protocol Flow 내부. 2026-05-25 capture 가 §4.6 으로 잘못 식별한 것을 본 재검증에서 정정.)
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| PKCE-RFC7636-C1 | OAuth 2.0 public client가 Authorization Code Grant 사용 시 authorization code interception attack에 취약 | [§1 Introduction] "OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack." | official-standard |
OAuth 2.0 public client (SPA, native app 등 client secret을 안전하게 보관 불가한 client) | confidential client (server-side, client secret 보호 가능) 가 동일 공격에 취약하다는 뜻은 아님 — RFC 7636의 직접 scope는 public client |
| PKCE-RFC7636-C2 | PKCE의 핵심 메커니즘: client가 비밀 code_verifier를 생성·기록하고, 변환 함수 t()를 적용한 code_challenge를 도출 |
[§1.1 Protocol Flow] "The client creates and records a secret named the 'code_verifier' and derives a transformed version 't(code_verifier)' (referred to as the 'code_challenge')." | official-standard |
PKCE를 적용하는 모든 OAuth client | t()의 구체적 선택지(plain vs S256)의 보안 동등성을 말하지 않음 — §4.2에서 별도 정의 |
| PKCE-RFC7636-C3 | S256 method: code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) (단방향 SHA-256 해시 + URL-safe Base64) |
[§4.2 Client Creates the Code Challenge] "code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))" | official-standard |
S256 method를 선택한 client (RFC 권장) | plain method도 사용 가능하나 RFC가 S256을 권장하는 정확한 위험 모델 비교는 별도 인용 필요 |
| PKCE-RFC7636-C4 | Authorization server는 token 교환 시 client가 제출한 code_verifier를 동일한 변환 t()로 처리하여 (B)단계의 code_challenge와 비교, 불일치 시 access 거부 |
[§1.1 Protocol Flow] "The authorization server transforms code_verifier and compares it to t(code_verifier) from (B). Access is denied if they are not equal." | official-standard |
PKCE를 강제하는 Authorization Server의 token endpoint | "거부" 응답의 정확한 error code / HTTP status는 본 인용 범위 밖 (RFC 6749 error mapping에 의존) |
| PKCE-RFC7636-C5 | 공격자가 (B) 단계에서 authorization code를 가로채도 code_verifier가 없으면 access token으로 교환 불가 |
[§1.1 Protocol Flow] "An attacker who intercepts the authorization code at (B) is unable to redeem it for an access token, as they are not in possession of the code_verifier secret." | official-standard |
code interception 공격 모델 (악성 앱이 redirect URI 가로채는 시나리오) | code_verifier 자체가 client device 외부로 유출된 경우의 방어는 별도 — PKCE는 transport 단계 가로채기 방어만 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
PKCE-RFC7636-C1~C5: PKCE 표준 메커니즘 (code_verifier/challenge 생성·검증, S256 공식, 위협 모델)
- 이 자료가 증명하지 않는 것:
- PKCE가 confidential client에도 의무라는 점 (RFC 7636 범위는 public client. OAuth 2.1 draft / RFC 9700에서 확장 — 본 문서 범위 밖)
code_verifier길이 (43~128 char) / 허용 문자 정확한 spec — 본 발췌 인용에 포함 안 됨, §4.1 참조 권고- Keycloak이 client별 PKCE 강제 옵션을 어떻게 노출하는지 (Keycloak vendor 문서 참조)
- Implicit flow의 PKCE 적용 불가 사실 (RFC 8252에서 다룸, 본 RFC 범위 밖)
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- Keycloak realm/client 설정에서 "Proof Key for Code Exchange Code Challenge Method = S256" 강제 설정 위치
- vanilla JS SPA에서
crypto.subtle.digest('SHA-256', ...)+base64urlencoding 호환성 (IE/구형 브라우저 미지원, modern only) - code_verifier를 sessionStorage에 둘 때 XSS 노출 위험과 single-page lifetime 일치성
P2A/P3A 함의 (내 프로젝트 해석)
본 섹션은 자료 직접 인용이 아닌 패턴 결정 컨텍스트 해석. wiki 추출 시
wiki/concepts/또는wiki/projects/source-summary로 옮겨야 함.
code_verifier: 43~128 byte 길이의[A-Z][a-z][0-9]-._~random string (§4.1).- Method:
plain:code_challenge = code_verifier— 권장 안 함.S256:BASE64URL(SHA256(verifier))— 표준 선택지. Keycloak도 client 설정에서 강제 가능.
- 공격 시나리오 (mobile / SPA 공통): redirect URI를 가로채는 악성 앱/스크립트가 code를 캡처 → 정상 client보다 먼저
/token호출. PKCE 없으면 토큰 발급, 있으면 verifier 불일치로 거부. - OAuth 2.1 draft는 PKCE를 **모든 client (confidential 포함)**에 의무화 — RFC 7636의 범위를 public client에서 전체로 확장.
- ID 흐름 (Implicit)은 PKCE 적용 불가 — 그래서 RFC 8252 / OAuth 2.1에서 deprecated.
메모 / Notes
- 2026-05-27 re-verification: WebFetch 재확인 완료. 5개 quote 모두 verbatim MATCH (C2 는 single-quote vs underscore quoting style 차이만 — 의미 동일하므로 official-standard 유지). C4/C5 의 anchor 가 §4.6/§1 가 아닌 §1.1 Protocol Flow 임을 정정.
- code_verifier 길이/문자셋 규칙 (§4.1) 은 본 raw에 직접 인용으로 보관 안됨 — 후속 raw 또는 wiki/concepts 정리 시 추가 발췌 필요.
Related / 관련
- 같은 주제 다른 official-doc:
- raw/official-docs/security-oauth2-pkce-rfc-8252 — RFC 8252가 native app에서 PKCE를 MUST로 의무화
- 인용하는 branch:
- 인용한 wiki 요약: (미작성)