기존의 OAuth 2.0을 보완하기 위한 여러 시도가 있습니다. 그 중 PKCE 그리고 더 발전된 형태인 OAuth 2.1에 대해 간략히 알아보겠습니다.
PKCE (Proof Key for Code Exchange)
PKCE는 악의적인 애플리케이션이 인증 코드를 가로채는 것을 방지하는 방법에 대한 내용입니다.
OAuth 2.0 인증과정 중 Authorization code가 탈취
OAuth 2.0의 흐름 중 다음과 같은 과정이 있습니다.
- Resource Owner(사용자)는 Authorization Server에 대한 인증을 진행
- 인증되면 Authorization Server는 Resource Owner(사용자)의 에이전트(브라우저)에게 redirect와 함께 Authorization code를 전달
- 에이전트(브라우저)에서 받은 Authorization code를 Client에게 전달
- Client는 Authorization code와 Client ID, Client Secret을 제출하여 Access Token을 발급받음.
여기서 문제는 Authorization code가 탈취되어 다른 Client에서도 사용할 수 있다는 점입니다.
3-1. 에이전트(브라우저)에서 받은 Authorization code를 악의적인 Client에게 전달 4-1. 악의적인 Client는 Authorization code와 탈취한 Client ID, Client Secret을 제출하여 Access Token을 발급받음.
PKCE의 원리
그럼 공격을 방지하려면 요청을 시작한 앱만이 액세스 토큰을 요청하고 얻을 수 있도록 해야 합니다.
PKCE는 “보증 키” 개념을 도입하여 이 문제를 해결합니다.
“보증 키”는 다음 3개로 구성됩니다.
- code_verifier: random한 문자열을 생성
- code_challenge: code_verifier를 해시 함수에 적용한 값
- code_challenge_method: 해시 함수 메서드
PKCE 절차
추가된 PKCE 절차를 중심으로 나열해보겠습니다.
- (PKCE 절차) code_verifier를 생성하고 code_challenge를 생성
- (PKCE 절차) code_challenge와 code_challenge_method를 Authorization Server에 제출
- 사용자가 Authorization Server에 인증 진행.
- 사용자의 인증이 완료되면 사용자의 브라우저는 redirect_url로 redirect되고 Client 서버로 Authorization code 전달
- (PKCE 절차) Client 서버는 Authorization code와 code_verifier를 제출하여 Access Token을 발급받음
- Access Token 사용…
PKCE reference
https://www.rfc-editor.org/rfc/rfc7636
https://oauth.net/2/pkce/
https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce
https://devocean.sk.com/blog/techBoardDetail.do?ID=166255&boardType=techBlog
https://sabarada.tistory.com/263
https://blog.logto.io/ko/how-pkce-protects-the-authorization-code-flow-for-native-apps
https://bluecheat.medium.com/oauth-2-1-pkce-%EB%B0%A9%EC%8B%9D-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-14500950cdbf
https://velog.io/@darren-kk/OAuth2.0%EA%B3%BC-PKCE
OAuth 2.1
이어서 2025년 9월 현재 IETF에서 논의중인 OAuth 2.1에 대해 간단히 알아보겠습니다.
OAuth 2.1은 OAuth 2.0를 개선한 프로토콜입니다.
주요 변경점
- PKCE는 Authorization Code Flow를 사용하는 모든 OAuth 클라이언트에서 필수 • 이제는 SPA나 네이티브 앱뿐 아니라, 서버 앱도 Code Flow를 쓴다면 무조건 PKCE 사용이 요구됩니다.
- Redirect URI는 문자열을 정확히 일치시켜야 함 • 기존에는 일부 느슨한 매칭(프리픽스 등)이 허용되었는데, 이제는 정확한 문자열 비교만 허용됩니다.
- Implicit Grant(response_type=token)는 더 이상 스펙에서 제외됨 • 보안상의 이유로, 토큰을 직접 브라우저로 전달하는 암시적 플로우는 사용하지 않습니다.
- Resource Owner Password Credentials Grant(ROPC)는 제외됨 • 사용자 비밀번호를 직접 애플리케이션에 입력받아 토큰을 교환하는 ROPC 방식은 더 이상 허용되지 않습니다.
- Bearer 토큰은 URI 쿼리스트링으로 전달 불가 • 토큰은 반드시 Authorization 헤더 등 안전한 방식으로만 전달해야 하며, URL 쿼리 파라미터로 넣는 건 금지입니다.
- 퍼블릭 클라이언트의 Refresh Token은 ‘발급 시 제약(sender-constrained)’ 또는 ‘1회용(one-time use)’이어야 함 • 퍼블릭 클라이언트(SPA, 모바일 앱 등)는 Refresh Token 탈취 위험이 크므로, 반드시 바인딩(예: DPoP, MTLS)하거나 1회만 쓰고 새로 발급받아야 합니다.
- Public/Confidential 클라이언트 정의가 단순화됨 • 더 이상 복잡한 조건 없이, 클라이언트가 비밀(Client Secret) 자격 증명을 가졌는지 여부로만 구분합니다.
OAuth 2.1 reference
https://oauth.net/2.1/
https://tech.kakaopay.com/post/spring-oauth2-authorization-server-practice/
https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/