인터넷 초안 OAuth 2.1 권한 부여 프레임워크 2026년 3월
Hardt 등 2026년 9월 3일 만료 [페이지]
작업 그룹:
OAuth 작업 그룹
인터넷 초안:
draft-ietf-oauth-v2-1-15
게시일:
의도된 상태:
표준 트랙
만료일:
저자:
D. Hardt
Hellō
A. Parecki
Okta
T. Lodderstedt
SPRIND

OAuth 2.1 권한 부여 프레임워크

초록

OAuth 2.1 권한 부여 프레임워크는 애플리케이션이 보호된 리소스에 대한 제한된 접근 권한을 얻을 수 있게 하며, 이는 리소스 소유자와 권한 부여 서비스 간의 승인 상호작용을 조율하여 리소스 소유자를 대신하거나, 애플리케이션이 자체적으로 접근 권한을 얻도록 허용하는 방식으로 이루어진다. 이 명세는 RFC 6749에 설명된 OAuth 2.0 권한 부여 프레임워크와 RFC 6750의 Bearer 토큰 사용을 대체하고 폐기한다.

논의 장소

이 참고 사항은 RFC로 게시되기 전에 제거된다.

이 문서에 대한 논의는 OAuth 작업 그룹 메일링 리스트(oauth@ietf.org)에서 이루어지며, 그 아카이브는 https://mailarchive.ietf.org/arch/browse/oauth/에 있다.

이 초안의 소스와 이슈 추적기는 https://github.com/oauth-wg/oauth-v2-1에서 찾을 수 있다.

이 메모의 상태

이 인터넷 초안은 BCP 78 및 BCP 79의 규정에 완전히 부합하도록 제출되었다.

인터넷 초안은 Internet Engineering Task Force(IETF)의 작업 문서이다. 다른 그룹도 작업 문서를 인터넷 초안으로 배포할 수 있다는 점에 유의한다. 현재 인터넷 초안 목록은 https://datatracker.ietf.org/drafts/current/에 있다.

인터넷 초안은 최대 6개월 동안 유효한 초안 문서이며, 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있다. 인터넷 초안을 참고 자료로 사용하거나 "진행 중인 작업" 이외의 방식으로 인용하는 것은 부적절하다.

이 인터넷 초안은 2026년 9월 3일에 만료된다.

목차

1. 소개

OAuth는 클라이언트의 역할을 리소스 소유자의 역할과 분리함으로써 클라이언트-서버 인증 모델에 권한 부여 계층을 도입한다. OAuth에서 클라이언트는 리소스 소유자가 제어하고 리소스 서버가 호스팅하는 리소스에 대한 접근을 요청한다. 보호된 리소스에 접근하기 위해 리소스 소유자의 자격 증명을 사용하는 대신, 클라이언트는 접근 토큰, 즉 범위와 수명 같은 특정 접근 속성 집합을 나타내는 자격 증명을 얻는다. 접근 토큰은 리소스 소유자의 승인에 따라 권한 부여 서버가 클라이언트에 발급한다. 클라이언트는 접근 토큰을 사용하여 리소스 서버가 호스팅하는 보호된 리소스에 접근한다.

더 오래되고 제한적인 클라이언트-서버 인증 모델에서 클라이언트는 리소스 소유자의 자격 증명을 사용하여 서버에 인증함으로써 서버의 접근 제한 리소스(보호된 리소스)를 요청한다. 애플리케이션에 제한된 리소스에 대한 접근을 제공하기 위해 리소스 소유자는 자신의 자격 증명을 애플리케이션과 공유한다. 이는 여러 문제와 제한을 만든다:

OAuth가 사용되는 예로, 최종 사용자(리소스 소유자)가 금융 관리 서비스(클라이언트)에 은행 서비스(리소스 서버)에 저장된 민감한 거래 내역에 대한 접근을 허용하면서도, 금융 관리 서비스와 사용자 이름 및 비밀번호를 공유하지 않는 경우가 있다. 대신 사용자는 자신의 금융 기관 서버(권한 부여 서버)에 직접 인증하고, 이 서버는 금융 관리 서비스에 위임별 자격 증명 (접근 토큰)을 발급한다.

이러한 관심사의 분리는 다중 인증과 같은 더 고급 사용자 인증 방법, 더 나아가 비밀번호 없는 인증을 애플리케이션 수정 없이 사용할 수 있는 능력도 제공한다. 모든 사용자 인증 로직이 권한 부여 서버에서 처리되므로, 애플리케이션은 특정 인증 메커니즘 구현의 세부 사항을 신경 쓸 필요가 없다. 이는 권한 부여 서버가 사용자 인증 정책을 관리하고, 향후 애플리케이션과 변경을 조율하지 않고도 이를 변경할 수 있는 능력을 제공한다.

권한 부여 계층은 리소스 서버가 요청이 권한 부여되었는지 판단하는 방식도 단순화할 수 있다. 전통적으로는 클라이언트를 인증한 후, 각 리소스 서버가 각 API 호출에서 클라이언트가 권한 부여되었는지를 계산하기 위해 정책을 평가했다. 분산 시스템에서는 정책을 모든 리소스 서버에 동기화하거나, 리소스 서버가 각 요청을 처리하기 위해 중앙 정책 서버를 호출해야 한다. OAuth에서는 새 접근 토큰이 권한 부여 서버에 의해 생성될 때에만 정책 평가가 수행된다. 권한 부여된 접근이 접근 토큰에 표현되어 있다면, 리소스 서버는 더 이상 정책을 평가할 필요가 없으며 접근 토큰만 검증하면 된다. 이러한 단순화는 애플리케이션이 리소스 소유자를 대신하여 동작하는 경우나 자기 자신을 대신하여 동작하는 경우 모두에 적용된다.

OAuth는 인증 프로토콜이 아니라 권한 부여 프로토콜이다. OAuth는 사용자 인증을 달성하는 데 필요한 구성 요소를 정의하지 않기 때문이다. 목표가 사용자를 인증하는 것이라면 인증 프로토콜이 필요하다. 예로 OpenID Connect [OpenID.Connect]가 있으며, 이는 OAuth를 기반으로 하여 인증 프로토콜에 요구되는 보안 특성과 필요한 구성 요소를 제공한다.

접근 토큰은 클라이언트에 부여된 권한 부여를 나타낸다. 클라이언트가 접근 토큰을 독점 API에 제시하고, 해당 API가 리소스 소유자의 사용자 식별자를 반환한 뒤, 그 API 결과를 사용자 인증의 대리물로 사용하는 관행이 흔하다. 이 관행은 OAuth 표준이나 보안 고려사항의 일부가 아니며, 리소스 소유자가 고려하지 않았을 수 있다. 구현자는 이 관행을 채택하기 전에 리소스 서버의 문서를 신중하게 참고해야 한다.

이 명세는 HTTP [RFC9110]와 함께 사용하도록 설계되었다. HTTP 이외의 프로토콜에서 OAuth를 사용하는 것은 범위를 벗어난다.

2012년 10월 OAuth 2.0 권한 부여 프레임워크 [RFC6749]가 게시된 이후, 이는 네이티브 앱용 OAuth 2.0 [RFC8252], OAuth 보안 모범 현행 관행 [RFC9700], 그리고 브라우저 기반 앱용 OAuth 2.0 [I-D.ietf-oauth-browser-based-apps]에 의해 갱신되었다. OAuth 2.0 권한 부여 프레임워크: Bearer 토큰 사용 [RFC6750] 역시 [RFC9700]로 갱신되었다. 이 표준 트랙 명세는 이러한 모든 문서의 정보를 통합하고 [RFC9700]에서 안전하지 않은 것으로 확인된 기능을 제거한다.

1.1. 역할

OAuth는 네 가지 역할을 정의한다:

"리소스 소유자":

보호된 리소스에 대한 접근을 부여할 수 있는 엔터티. 리소스 소유자가 사람인 경우 최종 사용자라고 한다. 이는 때때로 "RO"로 축약된다.

"리소스 서버":

보호된 리소스를 호스팅하며, 접근 토큰을 사용한 보호된 리소스 요청을 수락하고 응답할 수 있는 서버. 리소스 서버는 종종 API를 통해 접근할 수 있다. 이는 때때로 "RS"로 축약된다.

"클라이언트":

리소스 소유자를 대신하여, 그리고 그 권한 부여에 따라 보호된 리소스 요청을 수행하는 애플리케이션. "클라이언트"라는 용어는 특정 구현 특성(예: 애플리케이션이 서버, 데스크톱 또는 기타 장치에서 실행되는지 여부)을 의미하지 않는다.

"권한 부여 서버":

리소스 소유자를 성공적으로 인증하고 권한 부여를 얻은 후 클라이언트에 접근 토큰을 발급하는 서버. 이는 때때로 "AS"로 축약된다.

이 명세의 대부분은 클라이언트와 권한 부여 서버 간의 상호작용, 그리고 클라이언트와 리소스 서버 간의 상호작용을 정의한다.

권한 부여 서버와 리소스 서버 간의 상호작용은 이 명세의 범위를 벗어나지만, 리소스 서버와 권한 부여 서버 간의 상호 운용성 옵션을 제공하기 위해 여러 확장이 정의되어 있다. 권한 부여 서버는 리소스 서버와 동일한 서버일 수도 있고 별도 엔터티일 수도 있다. 단일 권한 부여 서버가 여러 리소스 서버에서 수락되는 접근 토큰을 발급할 수 있다.

리소스 소유자와 권한 부여 서버 간의 상호작용 (예: 최종 사용자가 권한 부여 서버에서 자신을 인증하는 방식) 역시 이 명세의 범위를 벗어나지만, 최종 사용자에게 동의를 요청하는 것과 관련된 보안 고려사항 같은 일부 예외가 있다.

리소스 소유자가 최종 사용자인 경우, 사용자는 클라이언트와 상호작용한다. 클라이언트가 웹 기반 애플리케이션인 경우, 사용자는 사용자 에이전트([RFC9110]의 Section 3.5에 설명된 대로)를 통해 클라이언트와 상호작용한다. 클라이언트가 네이티브 애플리케이션인 경우, 사용자는 운영 체제를 통해 클라이언트와 직접 상호작용한다. 자세한 내용은 Section 2.1을 참조한다.

1.2. 프로토콜 흐름

     +--------+                               +---------------+
     |        |--(1)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(2)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(3)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(4)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(5)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(6)--- Protected Resource ---|               |
     +--------+                               +---------------+
그림 1: 추상 프로토콜 흐름

그림 1에 표시된 추상 OAuth 2.1 흐름은 네 역할 간의 상호작용을 설명하며 다음 단계를 포함한다:

  1. 클라이언트는 리소스 소유자에게 권한 부여를 요청한다. 권한 부여 요청은 (표시된 것처럼) 리소스 소유자에게 직접 이루어질 수 있으며, 더 바람직하게는 권한 부여 서버를 중개자로 하여 간접적으로 이루어질 수 있다.

  2. 클라이언트는 권한 부여 그랜트를 받는다. 이는 리소스 소유자의 권한 부여를 나타내는 자격 증명이며, 이 명세에 정의된 권한 부여 그랜트 유형 중 하나 또는 확장 그랜트 유형을 사용하여 표현된다. 권한 부여 그랜트 유형은 클라이언트가 권한 부여를 요청하는 데 사용한 방법과 권한 부여 서버가 지원하는 유형에 따라 달라진다.

  3. 클라이언트는 권한 부여 서버에 인증하고 권한 부여 그랜트를 제시하여 접근 토큰을 요청한다.

  4. 권한 부여 서버는 클라이언트를 인증하고 권한 부여 그랜트를 검증하며, 유효한 경우 접근 토큰을 발급한다.

  5. 클라이언트는 리소스 서버에 보호된 리소스를 요청하고 접근 토큰을 제시하여 인증한다.

  6. 리소스 서버는 접근 토큰을 검증하고, 유효한 경우 요청을 처리한다.

클라이언트가 리소스 소유자로부터 권한 부여 그랜트를 얻는 선호되는 방법(단계 (1) 및 (2)에 묘사됨)은 권한 부여 서버를 중개자로 사용하는 것이며, 이는 Section 4.1그림 3에 표시되어 있다.

1.3. 권한 부여 그랜트

권한 부여 그랜트는 클라이언트가 접근 토큰을 얻기 위해 사용하는 리소스 소유자의 권한 부여(보호된 리소스에 접근하기 위한)를 나타낸다. 이 명세는 권한 부여 코드, 갱신 토큰, 클라이언트 자격 증명이라는 세 가지 그랜트 유형과, 추가 유형을 정의하기 위한 확장성 메커니즘을 정의한다.

1.3.1. 권한 부여 코드

권한 부여 코드는 접근 토큰을 얻는 데 사용되는 임시 자격 증명이다. 클라이언트가 리소스 소유자에게 직접 권한 부여를 요청하는 대신, 클라이언트는 리소스 소유자를 (사용자 에이전트를 통해) 권한 부여 서버로 안내하고, 권한 부여 서버는 다시 리소스 소유자를 권한 부여 코드와 함께 클라이언트로 되돌려 보낸다. 그러면 클라이언트는 권한 부여 코드를 접근 토큰으로 교환할 수 있다.

권한 부여 서버는 권한 부여 코드와 함께 리소스 소유자를 클라이언트로 되돌려 보내기 전에 리소스 소유자를 인증하고, 리소스 소유자의 동의를 요청하거나 클라이언트의 요청을 알릴 수 있다. 리소스 소유자는 권한 부여 서버에서만 인증하므로, 리소스 소유자의 자격 증명은 클라이언트와 공유되지 않으며, 클라이언트는 다중 인증이나 위임 계정 같은 추가 인증 단계에 대해 알 필요가 없다.

권한 부여 코드는 클라이언트를 인증할 수 있는 능력, 접근 토큰을 리소스 소유자의 사용자 에이전트를 통과시키지 않고 클라이언트로 직접 전송하여 리소스 소유자를 포함한 타인에게 노출될 가능성을 줄이는 것 같은 몇 가지 중요한 보안 이점을 제공한다.

1.3.2. 갱신 토큰

갱신 토큰은 접근 토큰을 얻는 데 사용되는 자격 증명이다. 갱신 토큰은 권한 부여 서버가 클라이언트에 발급할 수 있으며, 현재 접근 토큰이 무효가 되거나 만료될 때 새 접근 토큰을 얻거나, 동일하거나 더 좁은 범위의 추가 접근 토큰을 얻는 데 사용된다 (접근 토큰은 리소스 소유자가 권한 부여한 것보다 더 짧은 수명과 더 적은 권한을 가질 수 있다). 갱신 토큰 발급은 권한 부여 서버의 재량에 따른 선택 사항이며, 클라이언트의 속성, 요청의 속성, 권한 부여 서버 내 정책 또는 기타 기준에 따라 발급될 수 있다. 권한 부여 서버가 갱신 토큰을 발급하는 경우, 접근 토큰을 발급할 때 포함된다(즉, 그림 2의 단계 (2)). 갱신 토큰의 수명 역시 권한 부여 서버의 재량에 따른다.

갱신 토큰은 리소스 소유자가 클라이언트에 부여한 권한 부여를 나타내는 문자열이다. 이 문자열은 클라이언트에 대해 불투명한 것으로 간주된다. 갱신 토큰은 권한 부여 정보를 검색하는 데 사용되는 식별자일 수 있고, 이 정보를 문자열 자체에 인코딩할 수도 있다. 접근 토큰과 달리, 갱신 토큰은 권한 부여 서버에서만 사용되도록 의도되며 리소스 서버로 전송되지 않는다.

+--------+                                           +---------------+
|        |--(1)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(2)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(3)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(4)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(5)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(6)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(7)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(8)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+
그림 2: 만료된 접근 토큰 갱신

그림 2에 표시된 흐름은 다음 단계를 포함한다:

  1. 클라이언트는 권한 부여 서버에 인증하고 권한 부여 그랜트를 제시하여 접근 토큰을 요청한다.

  2. 권한 부여 서버는 클라이언트를 인증하고 권한 부여 그랜트를 검증하며, 유효한 경우 접근 토큰과 선택적으로 갱신 토큰을 발급한다.

  3. 클라이언트는 접근 토큰을 제시하여 리소스 서버에 보호된 리소스 요청을 한다.

  4. 리소스 서버는 접근 토큰을 검증하고, 유효한 경우 요청을 처리한다.

  5. 단계 (3)과 (4)는 접근 토큰이 만료될 때까지 반복된다. 클라이언트가 접근 토큰이 만료된 것을 알고 있다면 단계 (7)로 건너뛰고, 그렇지 않으면 또 다른 보호된 리소스 요청을 한다.

  6. 접근 토큰이 유효하지 않으므로, 리소스 서버는 유효하지 않은 토큰 오류를 반환한다.

  7. 클라이언트는 갱신 토큰을 제시하고, 자격 증명이 발급된 경우 클라이언트 인증을 제공하여 새 접근 토큰을 요청한다. 클라이언트 인증 요구사항은 클라이언트 유형과 권한 부여 서버 정책에 따라 달라진다.

  8. 권한 부여 서버는 클라이언트를 인증하고 갱신 토큰을 검증하며, 유효한 경우 새 접근 토큰(그리고 선택적으로 새 갱신 토큰)을 발급한다.

클라이언트가 수명 정보를 가지고도 달리 할 수 있는 일이 없으므로 갱신 토큰의 수명을 클라이언트에 전달할 필요는 없다. 또한 권한 부여 서버는 동적 수명(예: 갱신 토큰이 적어도 7일에 한 번 사용되는 한 갱신 토큰 만료가 연장됨)을 사용할 수 있으며, 사용자가 애플리케이션의 접근을 취소하는 경우처럼 어떤 이유로든 예정된 만료일 전에 갱신 토큰을 취소할 수 있다. 이는 클라이언트가 이미 갱신 토큰이 임의의 시점에 만료되는 경우를 처리해야 함을 의미한다.

갱신 토큰이 왜 또는 언제 만료되든, 클라이언트가 새 토큰을 얻는 유일한 경로는 처음부터 새 OAuth 흐름을 시작하는 것이다. 이러한 이유로 갱신 토큰의 만료를 클라이언트에 전달하는 속성은 정의되어 있지 않다.

1.3.3. 클라이언트 자격 증명

클라이언트 자격 증명 또는 다른 형태의 클라이언트 인증 (예: [RFC7523] 및 그 갱신판 [I-D.ietf-oauth-rfc7523bis]에 설명된 것처럼 JWT에 서명하는 데 사용되는 개인 키)은 권한 부여 범위가 클라이언트가 제어하는 보호된 리소스 또는 권한 부여 서버와 사전에 조정된 보호된 리소스로 제한될 때 권한 부여 그랜트로 사용할 수 있다. 클라이언트 자격 증명은 클라이언트가 권한 부여 서버와 사전에 조정된 권한 부여를 기반으로 보호된 리소스에 대한 접근을 요청할 때 사용된다.

1.4. 접근 토큰

접근 토큰은 보호된 리소스에 접근하는 데 사용되는 자격 증명이다. 접근 토큰은 클라이언트에 발급된 권한 부여를 나타내는 문자열이다.

이 문자열은 구조를 가지고 있더라도 클라이언트에는 불투명한 것으로 간주된다. 클라이언트는 접근 토큰 값을 파싱할 수 있을 것이라고 기대해서는 안 된다. 권한 부여 서버는 리소스 서버가 기대하는 것 외에 일관된 접근 토큰 인코딩이나 형식을 사용할 필요가 없다.

리소스 소유자가 클라이언트에 부여한 접근은 권한 부여 서버가 생성한 접근 토큰으로 표현된다. 접근 토큰은 유출된 접근 토큰의 피해 범위를 줄이기 위해 수명이 짧다. 접근 토큰의 만료는 권한 부여 서버가 설정한다.

권한 부여 서버 구현에 따라, 토큰 문자열은 리소스 서버가 권한 부여 정보를 검색하는 데 사용될 수 있거나, 토큰이 검증 가능한 방식(즉, 서명된 데이터 페이로드로 구성된 토큰 문자열)으로 권한 부여 정보를 자체 포함할 수 있다. 토큰 검색 메커니즘의 한 예는 토큰 인트로스펙션 [RFC7662]이며, 여기서 RS는 클라이언트가 제시한 토큰을 검증하기 위해 AS의 엔드포인트를 호출한다. 구조화된 토큰 형식의 한 예는 접근 토큰용 JWT 프로파일 [RFC9068]로, 접근 토큰 데이터를 JSON Web Token [RFC7519]으로 인코딩하고 서명하는 방법이다.

클라이언트가 접근 토큰을 사용하기 위해 이 명세의 범위를 벗어나는 추가 인증 자격 증명이 필요할 수 있다. 이는 일반적으로 DPoP [RFC9449] 및 상호 TLS 인증서 바인딩 접근 토큰 [RFC8705] 같은 발신자 제한 접근 토큰이라고 한다.

접근 토큰은 추상화 계층을 제공하여 서로 다른 권한 부여 구성요소(예: 사용자 이름과 비밀번호)를 리소스 서버가 이해하는 단일 토큰으로 대체한다. 이 추상화는 접근 토큰을 얻는 데 사용된 권한 부여 그랜트보다 더 제한적인 접근 토큰을 발급할 수 있게 하며, 리소스 서버가 광범위한 인증 방법을 이해해야 할 필요도 제거한다.

접근 토큰은 리소스 서버 보안 요구사항에 따라 서로 다른 형식, 구조 및 사용 방법(예: 암호학적 속성)을 가질 수 있다. 접근 토큰 속성과 보호된 리소스에 접근하는 데 사용되는 방법은 이 명세에 설명된 범위를 넘어 확장될 수 있다.

접근 토큰(및 모든 기밀 접근 토큰 속성)은 전송 및 저장 중 기밀로 유지되어야 하며, 권한 부여 서버, 접근 토큰이 유효한 리소스 서버들, 그리고 접근 토큰이 발급된 클라이언트 사이에서만 공유되어야 한다.

권한 부여 서버는 권한 없는 당사자가 유효한 접근 토큰을 만들도록 접근 토큰을 생성, 수정 또는 추측할 수 없도록 보장해야 한다.

1.4.1. 접근 토큰 범위

접근 토큰은 접근을 부여하는 사용자가 가진 권한보다 더 적은 권한으로 클라이언트에 발급되도록 의도된다. 이는 제한된 "scope" 접근 토큰으로 알려져 있다. 권한 부여 서버와 리소스 서버는 이 범위 메커니즘을 사용하여 특정 클라이언트가 가질 수 있는 리소스 유형이나 접근 수준을 제한할 수 있다.

예를 들어, 클라이언트는 사용자의 리소스에 대해 "read" 접근만 필요하고 리소스를 갱신할 필요는 없을 수 있다. 따라서 클라이언트는 권한 부여 서버가 정의한 읽기 전용 범위를 요청하고, 리소스 갱신에 사용할 수 없는 접근 토큰을 얻을 수 있다. 이는 권한 부여 서버, 리소스 서버, 클라이언트 간의 조율을 필요로 한다. 권한 부여 서버는 클라이언트가 특정 범위를 요청할 수 있는 기능을 제공하고, 클라이언트에 발급된 접근 토큰에 해당 범위를 연결한다. 그런 다음 리소스 서버는 제한된 범위의 접근 토큰이 제시될 때 범위를 집행할 책임이 있다.

OAuth는 어떤 범위 값도 정의하지 않는다. 대신 범위는 권한 부여 서버 또는 OAuth의 확장이나 프로파일이 정의한다. 범위를 정의하는 이러한 확장 중 하나가 [OpenID.Connect]이며, 이는 사용자의 프로파일 정보에 대한 세분화된 접근을 제공하는 범위 집합을 정의한다. 알려진 확장의 범위와 충돌하는 사용자 지정 범위를 정의하는 것은 피하는 것이 권장된다.

제한된 범위의 접근 토큰을 요청하기 위해, 클라이언트는 사용된 그랜트 유형에 따라 권한 부여 또는 토큰 엔드포인트에서 scope 요청 매개변수를 사용한다. 이에 따라 권한 부여 서버는 발급된 접근 토큰의 범위를 클라이언트에 알리기 위해 scope 응답 매개변수를 사용한다.

scope 매개변수의 값은 공백으로 구분된 대소문자 구분 문자열 목록으로 표현된다. 문자열은 권한 부여 서버가 정의한다. 값에 여러 공백 구분 문자열이 포함되는 경우 그 순서는 중요하지 않으며, 각 문자열은 요청된 범위에 추가 접근 범위를 더한다.

    scope       = scope-token *( SP scope-token )
    scope-token = 1*( %x21 / %x23-5B / %x5D-7E )

권한 부여 서버는 권한 부여 서버 정책 또는 리소스 소유자의 지시에 따라 클라이언트가 요청한 범위를 전부 또는 일부 무시할 수 있다. 발급된 접근 토큰 범위가 클라이언트가 요청한 범위와 다른 경우, 권한 부여 서버는 클라이언트에 실제 부여된 범위를 알리기 위해 토큰 응답 (Section 3.2.3)에 scope 응답 매개변수를 포함해야 한다.

클라이언트가 권한 부여를 요청할 때 scope 매개변수를 생략하면, 권한 부여 서버는 사전 정의된 기본값을 사용하여 요청을 처리하거나 유효하지 않은 범위를 나타내며 요청을 실패시켜야 한다. 권한 부여 서버는 자신의 범위 요구사항과 기본값(정의된 경우)을 문서화해야 한다.

1.4.2. Bearer 토큰

Bearer 토큰은 토큰을 소지한 어떤 당사자("bearer")든 그 토큰을 소지한 다른 당사자가 사용할 수 있는 방식으로 토큰을 사용할 수 있다는 속성을 가진 보안 토큰이다. Bearer 토큰 사용은 bearer가 암호학적 키 자료의 소유 (소유 증명)를 증명할 것을 요구하지 않는다.

Bearer 토큰은 DPoP [RFC9449] 및 mTLS [RFC8705] 같은 소유 증명 명세로 강화되어 소유 증명 특성을 제공할 수 있다.

접근 토큰 공개로부터 보호하기 위해, 클라이언트와 리소스 서버 간의 통신 상호작용은 Section 1.5에 설명된 기밀성 및 무결성 보호를 사용해야 한다.

bearer 토큰의 특정 구조나 형식에 대한 요구사항은 없다. bearer 토큰이 권한 부여 정보에 대한 참조인 경우, 그러한 참조는 충분히 긴 암호학적 난수 문자열을 사용하는 것처럼 공격자가 추측하기 불가능해야 한다. bearer 토큰이 토큰 자체에 권한 부여 정보를 포함하는 인코딩 메커니즘을 사용하는 경우, 접근 토큰은 토큰이 수정되는 것을 방지하기에 충분한 무결성 보호를 사용해야 한다. 접근 토큰의 인코딩 및 서명 메커니즘의 한 예는 접근 토큰용 JSON Web Token 프로파일 [RFC9068]에 설명되어 있다.

1.4.3. 발신자 제한 접근 토큰

발신자 제한 접근 토큰은 접근 토큰의 사용을 특정 발신자에게 바인딩한다. 이 발신자는 수신자(예: 리소스 서버)에서 해당 접근 토큰이 수락되기 위한 전제 조건으로 특정 비밀을 알고 있음을 입증해야 한다.

권한 부여 서버와 리소스 서버는 OAuth Demonstration of Proof of Possession (DPoP) [RFC9449] 또는 OAuth 2.0용 상호 TLS [RFC8705] 같은 발신자 제한 접근 토큰 메커니즘을 사용해야 한다. 도난 및 유출된 접근 토큰의 오용을 방지하려면 [RFC9700]의 Section 4.10.1을 참조한다.

클라이언트와 리소스 서버 간에 종단 간 TLS를 사용하는 것이 권장된다. TLS 트래픽을 중개자에서 종료해야 하는 경우, 추가 보안 조언은 [RFC9700]의 Section 4.13을 참조한다.

1.5. 통신 보안

구현은 통신 인증, 무결성 및 기밀성을 제공하는 메커니즘, 예를 들어 Transport-Layer Security [RFC8446]를 사용해야 하며, 콘텐츠나 헤더 필드에 있는 평문 자격 증명 및 토큰의 교환을 도청으로부터 보호해야 한다. 도청은 재전송을 가능하게 한다 (예: Section 2.4.1, Section 7.5.1, Section 3.2, 및 Section 1.4.2 참조).

모든 OAuth 프로토콜 URL(AS, RS 및 클라이언트가 노출하는 URL)은 루프백 인터페이스 리디렉션 URI를 제외하고 https 스킴을 사용해야 하며, 루프백 인터페이스 리디렉션 URI는 http 스킴을 사용할 수 있다. https를 사용할 때에는 TLS 인증서를 [RFC9110]의 Section 4.3.4에 따라 검사해야 한다. 이 글을 쓰는 시점에서 TLS 버전 1.3 [RFC8446]이 가장 최신 버전이다.

구현은 보안 요구사항을 충족하는 추가 전송 계층 보안 메커니즘도 지원할 수 있다.

TLS 버전과 알고리즘의 식별은 이 명세의 범위를 벗어난다. 전송 계층 보안에 대한 최신 권장사항은 [BCP195]를 참조하고, 인증서 검증 및 기타 보안 고려사항은 관련 명세를 참조한다.

1.6. HTTP 리디렉션

이 명세는 HTTP 리디렉션을 광범위하게 사용하며, 여기서 클라이언트 또는 권한 부여 서버는 리소스 소유자의 사용자 에이전트를 다른 목적지로 안내한다. 이 명세의 예는 HTTP 302 상태 코드 사용을 보여주지만, HTTP 307을 제외하고 이 리디렉션을 수행하기 위해 사용자 에이전트를 통해 사용할 수 있는 다른 모든 방법도 허용되며 구현 세부 사항으로 간주된다. 자세한 내용은 Section 7.5.3을 참조한다.

1.7. 상호 운용성

OAuth 2.1은 잘 정의된 보안 속성을 가진 풍부한 권한 부여 프레임워크를 제공한다.

이 명세는 몇 가지 필수 구성 요소를 부분적으로 또는 완전히 정의하지 않은 채 남겨둔다(예: 클라이언트 등록, 권한 부여 서버 기능, 엔드포인트 발견). 이러한 동작 중 일부는 구현이 선택하여 사용할 수 있는 선택적 확장에서 정의되며, 예는 다음과 같다:

  • [RFC8414]: 권한 부여 서버 메타데이터. 클라이언트가 특정 OAuth 서버와 상호작용하는 데 필요한 정보를 조회하는 데 사용할 수 있는 엔드포인트를 정의한다

  • [RFC7591]: 동적 클라이언트 등록. 권한 부여 서버에 클라이언트를 프로그래밍 방식으로 등록하기 위한 메커니즘을 제공한다

  • [RFC7592]: 동적 클라이언트 관리. 동적으로 등록된 클라이언트 정보를 갱신하기 위한 메커니즘을 제공한다

  • [RFC7662]: 토큰 인트로스펙션. 리소스 서버가 접근 토큰에 관한 정보를 얻기 위한 메커니즘을 정의한다

이 게시 시점에 알려진 현재 확장 목록은 부록 D를 참조한다.

1.8. OAuth 2.0과의 호환성

OAuth 2.1은 알려진 모범 현행 관행의 확장과 제한을 적용한 OAuth 2.0과 호환된다. 구체적으로, PKCE처럼 OAuth 2.0 핵심에 명시되지 않은 기능은 OAuth 2.1에서 필수이다. 또한 Implicit 또는 Resource Owner Credentials 그랜트 유형처럼 OAuth 2.0에서 사용할 수 있었던 일부 기능은 OAuth 2.1에 명시되지 않는다. 더 나아가, OAuth 2.0에서 허용되던 일부 동작은 OAuth 2.1에서 제한되며, 예를 들어 OAuth 2.1이 요구하는 리디렉션 URI의 엄격한 문자열 일치가 있다.

OAuth 2.0과의 차이에 대한 자세한 내용은 Section 10을 참조한다.

1.9. 표기 규칙

이 문서의 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 및 "OPTIONAL"은 여기에 표시된 것처럼 모두 대문자로 나타날 때, 그리고 그때에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석되어야 한다.

이 명세는 [RFC5234]의 Augmented Backus-Naur Form (ABNF) 표기법을 사용한다. 또한 규칙 URI-reference는 "Uniform Resource Identifier (URI): Generic Syntax" [RFC3986]에서 포함된다.

특정 보안 관련 용어는 [RFC4949]에 정의된 의미로 이해되어야 한다. 이러한 용어에는 "attack", "authentication", "authorization", "certificate", "confidentiality", "credential", "encryption", "identity", "sign", "signature", "trust", "validate", 및 "verify"가 포함되지만 이에 한정되지 않는다.

"content"라는 용어는 [RFC9110]의 Section 6.4에 설명된 대로 해석되어야 한다.

"user agent"라는 용어는 [RFC9110]의 Section 3.5에 설명된 대로 해석되어야 한다.

달리 명시되지 않는 한, 모든 프로토콜 매개변수 이름과 값은 대소문자를 구분한다.

2. 클라이언트 등록

프로토콜을 시작하기 전에, 클라이언트는 권한 부여 서버에서 식별자(Section 2.2)를 확립해야 한다. 클라이언트 식별자가 권한 부여 서버와 확립되는 수단은 이 명세의 범위를 벗어나지만, 일반적으로 클라이언트 개발자가 권한 부여 서버의 웹사이트에서 클라이언트를 수동으로 등록하는 것 (계정을 만들고 서비스 약관에 동의한 후) 또는 동적 클라이언트 등록 [RFC7591]을 사용하는 것을 포함한다. 확장은 클라이언트 등록을 확립하기 위한 다른 프로그래밍 방식도 정의할 수 있다.

클라이언트 등록은 클라이언트와 권한 부여 서버 간의 직접적인 상호작용을 요구하지 않는다. 권한 부여 서버가 지원하는 경우, 등록은 신뢰를 확립하고 필요한 클라이언트 속성 (예: 리디렉션 URI, 클라이언트 유형)을 얻기 위한 다른 수단에 의존할 수 있다. 예를 들어, 등록은 자체 발급 또는 제3자 발급 어설션을 사용하거나, 권한 부여 서버가 신뢰된 채널을 사용하여 클라이언트 발견을 수행함으로써 이루어질 수 있다.

클라이언트 등록에는 다음이 포함되어야 한다:

동적 클라이언트 등록 [RFC7591]은 수동 클라이언트 등록에서도 사용할 수 있는 클라이언트용 공통 일반 데이터 모델을 정의한다.

2.1. 클라이언트 유형

OAuth 2.1은 권한 부여 서버에 안전하게 인증할 수 있는 능력에 따라 두 가지 클라이언트 유형을 정의한다.

"기밀":

AS에 대한 자격 증명을 가진 클라이언트는 "기밀 클라이언트"로 지정된다

"공개":

자격 증명이 없는 클라이언트는 "공개 클라이언트"라고 한다

자격 증명을 가진 모든 클라이언트는 자격 증명의 유출과 남용을 방지하기 위한 예방 조치를 취해야 한다.

클라이언트 인증은 권한 부여 서버가 OAuth 흐름에서 특정 클라이언트(client_id로 식별됨)와 상호작용하고 있음을 보장할 수 있게 한다. 권한 부여 서버는 권한 부여마다 사용자에게 동의를 요청할지, 아니면 처음에만 요청할지와 같은 사항에 대해 정책 결정을 내릴 수 있으며, 이는 권한 부여 서버가 실제로 합법적인 클라이언트와 통신하고 있다는 확신에 기반한다.

권한 부여 서버가 클라이언트의 신원 또는 이 클라이언트를 제공/운영하는 당사자의 신원을 검증하는지와 그 방식은 이 명세의 범위를 벗어난다. 권한 부여 서버는 클라이언트 자격 증명 그랜트 유형 같은 더 민감한 리소스와 작업에 대한 클라이언트 접근을 허용할지, 그리고 사용자에게 동의를 얼마나 자주 요청할지를 결정할 때 클라이언트 신원에 대한 신뢰 수준을 고려해야 한다.

권한 부여 서버가 특정 클라이언트 유형을 지원해야 한다는 요구사항은 없다.

단일 client_id는 둘 이상의 클라이언트 유형으로 취급되어서는 안 된다.

이 명세는 다음 클라이언트 프로파일을 중심으로 설계되었다:

"웹 애플리케이션":

웹 애플리케이션은 웹 서버에서 실행되는 클라이언트이다. 리소스 소유자는 리소스 소유자가 사용하는 장치의 사용자 에이전트에서 렌더링되는 HTML 사용자 인터페이스를 통해 클라이언트에 접근한다. 클라이언트 자격 증명과 클라이언트에 발급된 모든 접근 토큰은 웹 서버에 저장되며, 리소스 소유자에게 노출되거나 접근 가능하지 않다.

"브라우저 기반 애플리케이션":

브라우저 기반 애플리케이션은 클라이언트 코드가 웹 서버에서 다운로드되어 리소스 소유자가 사용하는 장치의 사용자 에이전트(예: 웹 브라우저) 내에서 실행되는 클라이언트이다. 프로토콜 데이터와 자격 증명은 리소스 소유자가 쉽게 접근할 수 있고 종종 볼 수 있다. 이러한 애플리케이션이 클라이언트 자격 증명을 사용하려는 경우, backend for frontend 패턴을 활용하는 것이 권장된다. 이러한 애플리케이션은 사용자 에이전트 내에 있기 때문에, 권한 부여를 요청할 때 사용자 에이전트 기능을 원활하게 사용할 수 있다.

"네이티브 애플리케이션":

네이티브 애플리케이션은 리소스 소유자가 사용하는 장치에 설치되어 실행되는 클라이언트이다. 프로토콜 데이터와 자격 증명은 리소스 소유자가 접근할 수 있다. 애플리케이션에 포함된 모든 클라이언트 인증 자격 증명은 추출될 수 있다고 가정된다. 동적으로 발급된 접근 토큰과 갱신 토큰은 허용 가능한 수준의 보호를 받을 수 있다. 일부 플랫폼에서는 이러한 자격 증명이 같은 장치에 있는 다른 애플리케이션으로부터 보호된다. 이러한 애플리케이션이 클라이언트 자격 증명을 사용하려는 경우, backend for frontend 패턴을 활용하거나 런타임에 동적 클라이언트 등록 [RFC7591]을 사용하여 자격 증명을 발급하는 것이 권장된다.

2.2. 클라이언트 식별자

모든 클라이언트는 권한 부여 서버의 맥락에서 클라이언트가 제공한 등록 정보를 나타내는 고유 문자열인 클라이언트 식별자로 식별된다. 권한 부여 서버가 일반적으로 클라이언트 식별자를 직접 발급하지만, 권한 부여 서버가 아닌 당사자가 만든 클라이언트 식별자를 가진 클라이언트에 서비스를 제공할 수도 있다. 클라이언트 식별자는 비밀이 아니며, 리소스 소유자에게 노출되고 클라이언트 인증에 단독으로 사용되어서는 안 된다. 클라이언트 식별자는 권한 부여 서버의 맥락에서 고유하다.

클라이언트 식별자는 이 명세에서 크기가 정의되지 않은 불투명 문자열이다. 클라이언트는 식별자 크기에 대해 가정하지 않아야 한다. 권한 부여 서버는 자신이 발급하는 모든 식별자의 크기를 문서화해야 한다.

권한 부여 서버가 자신이 아닌 당사자가 발급한 클라이언트 식별자를 가진 클라이언트를 지원하는 경우, 권한 부여 서버는 Section 7.4에 설명된 것처럼 클라이언트가 리소스 소유자를 가장하지 못하도록 예방 조치를 취해야 한다.

2.3. 클라이언트 리디렉션 엔드포인트

클라이언트 리디렉션 엔드포인트("redirect endpoint"라고도 함)는 권한 부여 서버가 리소스 소유자와의 상호작용을 완료한 후 사용자 에이전트를 되돌려 보내는 클라이언트의 URI이다.

권한 부여 서버는 클라이언트 등록 과정에서 권한 부여 서버와 사전에 확립된 클라이언트의 리디렉션 엔드포인트 중 하나로 사용자 에이전트를 리디렉션한다.

리디렉션 URI는 [RFC3986]의 Section 4.3에 정의된 절대 URI여야 한다. 리디렉션 URI는 쿼리 문자열 구성 요소 (Appendix C.1)를 포함할 수 있으며, 추가 쿼리 매개변수를 추가할 때 이를 유지해야 한다. 리디렉션 URI는 프래그먼트 구성 요소를 포함해서는 안 된다.

2.3.1. 등록 요구사항

권한 부여 서버는 클라이언트가 완전한 리디렉션 URI(경로 구성 요소 포함)를 등록하도록 요구해야 한다. 권한 부여 서버는 등록된 것과 정확히 일치하지 않는 리디렉션 URI를 지정하는 권한 부여 요청을 거부해야 하며, 루프백 리디렉션의 경우 포트 URI 구성 요소를 제외하고 정확한 일치가 요구되는 예외가 있다. 자세한 내용은 Section 4.1.1을 참조한다.

권한 부여 서버는 클라이언트가 여러 리디렉션 URI를 등록하도록 허용할 수 있다.

등록은 권한 부여 서버에서 클라이언트 정보를 구성하는 수동 단계처럼 대역 외에서 일어날 수도 있고, Pushed Authorization Requests [RFC9126]의 초기 POST처럼 런타임에 일어날 수도 있다.

사적 사용 URI 스킴 기반 리디렉션 URI의 경우, 권한 부여 서버는 클라이언트가 역 도메인 이름 기반 스킴을 사용해야 한다는 Section 8.4.3의 요구사항을 집행해야 한다. 최소한 마침표 문자(.)를 포함하지 않는 모든 사적 사용 URI 스킴은 거부되어야 한다.

충돌 방지 속성에 더하여, 이는 두 앱이 같은 사적 사용 URI 스킴을 주장하는 분쟁 상황에서 (한 앱이 악의적으로 동작하는 경우) 소유권을 입증하는 데 도움이 될 수 있다. 예를 들어 두 앱이 com.example.app을 주장했다면, example.com의 소유자는 앱 스토어 운영자에게 위조 앱 제거를 청원할 수 있다. 일반 URI 스킴을 사용했다면 이러한 청원은 입증하기 더 어렵다.

클라이언트는 쿼리 매개변수에서 얻은 임의 URI로 사용자의 브라우저를 전달하는 URL("open redirector")을 노출해서는 안 되며, 이는 Section 7.12에 설명되어 있다. 오픈 리디렉터는 권한 부여 코드와 접근 토큰의 유출을 가능하게 할 수 있다.

클라이언트는 필요하다면 요청별 맞춤화를 달성하기 위해 요청마다 리디렉션 URI를 변경하는 대신 state 요청 매개변수를 사용할 수 있다.

리디렉션 URI 등록을 요구하지 않으면, 공격자는 Section 7.12에 설명된 것처럼 권한 부여 엔드포인트를 오픈 리디렉터로 사용할 수 있다.

2.3.2. 여러 리디렉션 URI

클라이언트에 여러 리디렉션 URI가 등록되어 있다면, 클라이언트는 redirect_uri 요청 매개변수 (Section 4.1.1)를 사용하여 권한 부여 요청에 리디렉션 URI를 포함해야 한다. 클라이언트에 단일 리디렉션 URI만 등록되어 있다면, redirect_uri 요청 매개변수는 선택 사항이다.

2.3.3. CSRF 공격 방지

클라이언트는 Cross-Site Request Forgery (CSRF) 공격을 방지해야 한다. 이 맥락에서 CSRF는 권한 부여 서버에서 유래하지 않고 악의적인 제3자에서 유래하는 리디렉션 엔드포인트 요청을 의미한다 (자세한 내용은 [RFC6819]의 Section 4.4.1.8 참조). 권한 부여 서버가 code_challenge 매개변수를 지원함을 확인한 클라이언트는 이 메커니즘이 제공하는 CSRF 보호에 의존할 수 있다. OpenID Connect 흐름에서는 nonce 매개변수를 검증하는 것이 CSRF 보호를 제공한다. 그렇지 않으면 사용자 에이전트에 안전하게 바인딩된, state 매개변수에 담긴 일회용 CSRF 토큰을 CSRF 보호에 사용해야 한다 (Section 7.9 참조).

2.3.4. Mix-Up 공격 방지

OAuth 클라이언트가 하나의 권한 부여 서버와만 상호작용할 수 있는 경우, mix-up 방어는 필요하지 않다. 그러나 OAuth 클라이언트가 둘 이상의 권한 부여 서버와 상호작용하는 시나리오에서는 클라이언트가 mix-up 공격을 방지해야 한다. mix-up 공격을 방지하기 위해, 클라이언트는 해당 요청을 보낸 발급자와 동일한 사용자 에이전트에서 시작된 권한 부여 요청의 리디렉션 응답만 처리해야 한다.

mix-up 공격에 대한 두 가지 서로 다른 방어의 자세한 설명은 Section 7.14를 참조한다.

2.3.5. 유효하지 않은 엔드포인트

권한 부여 요청이 누락, 유효하지 않음 또는 불일치하는 리디렉션 URI로 인해 검증에 실패하는 경우, 권한 부여 서버는 리소스 소유자에게 오류를 알려야 하며, 사용자 에이전트를 유효하지 않은 리디렉션 URI로 자동 리디렉션해서는 안 된다.

2.3.6. 엔드포인트 콘텐츠

클라이언트 엔드포인트로의 리디렉션 요청은 일반적으로 사용자 에이전트가 처리하는 HTML 문서 응답으로 이어진다. HTML 응답이 리디렉션 요청의 결과로 직접 제공되는 경우, HTML 문서에 포함된 모든 스크립트는 리디렉션 URI와 그 안에 포함된 산출물(예: 권한 부여 코드)에 대한 전체 접근 권한으로 실행된다. 또한 권한 부여 코드가 포함된 요청 URL이 페이지에 로드된 내장 이미지, 스타일시트 및 기타 요소로 HTTP Referer 헤더를 통해 전송될 수 있다.

클라이언트는 리디렉션 URI 엔드포인트 응답에 제3자 스크립트(예: 제3자 분석, 소셜 플러그인, 광고 네트워크)를 포함해서는 안 된다. 대신 URI에서 산출물을 추출하고, 산출물을 (URI나 다른 곳에) 노출하지 않는 다른 엔드포인트로 사용자 에이전트를 다시 리디렉션해야 한다. 제3자 스크립트가 포함되는 경우, 클라이언트는 자체 스크립트(URI에서 자격 증명을 추출하고 제거하는 데 사용됨)가 먼저 실행되도록 보장해야 한다.

2.4. 클라이언트 인증

권한 부여 서버는 기본 자격 증명의 발급/등록 및 배포 과정이 그 기밀성을 보장하는 경우에만 클라이언트 인증에 의존해야 한다.

기밀 클라이언트의 경우, 권한 부여 서버는 자신의 보안 요구사항을 충족하는 모든 형태의 클라이언트 인증 (예: 클라이언트 시크릿, 공개/개인 키 쌍)을 수락할 수 있다.

mTLS [RFC8705] 또는 [RFC7521], [RFC7523] 및 그 갱신판 [I-D.ietf-oauth-rfc7523bis]에 따른 서명된 JWT("Private Key JWT")를 사용하는 것 같은 비대칭(공개 키 기반) 방법을 클라이언트 인증에 사용하는 것이 권장된다 ([OpenID.Connect]에서 클라이언트 인증 방법 private_key_jwt로 정의됨). 이러한 클라이언트 인증 방법이 사용될 때, 권한 부여 서버는 민감한 대칭 키를 저장할 필요가 없으므로 이러한 방법은 여러 공격에 대해 더 견고해지고, 클라이언트가 자신의 키와 키 순환을 관리할 수 있게 한다.

JWT 기반 클라이언트 인증을 사용할 때, 클라이언트와 권한 부여 서버는 [I-D.ietf-oauth-rfc7523bis]aud 값에 대한 갱신된 지침을 따라야 한다.

클라이언트 인증이 불가능한 경우, 권한 부여 서버는 클라이언트의 신원을 검증하기 위한 다른 수단을 사용해야 한다. 예를 들어 클라이언트 리디렉션 URI 등록을 요구하거나 리소스 소유자가 신원을 확인하도록 할 수 있다. 유효한 리디렉션 URI는 리소스 소유자 권한 부여를 요청할 때 클라이언트의 신원을 검증하기에 충분하지 않지만, 리소스 소유자 권한 부여를 얻은 후 위조 클라이언트에 자격 증명을 전달하는 것을 방지하는 데 사용될 수 있다.

클라이언트는 각 요청에서 둘 이상의 인증 방법을 사용해서는 안 된다. 이는 어떤 인증 메커니즘이 요청에 대해 권위를 가지는지에 대한 충돌을 방지하기 위함이다.

권한 부여 서버는 인증되지 않은 클라이언트와 상호작용하는 것의 보안 영향을 고려하고, 그러한 클라이언트에 발급되는 토큰의 잠재적 노출을 제한하기 위한 조치를 취해야 한다 (예: 갱신 토큰의 수명 제한).

권한 부여 서버가 특정 클라이언트 신원과 연결하는 권한은 클라이언트 식별 및 클라이언트 자격 증명 수명 주기 관리에 대한 전체 과정의 평가에 따라 달라져야 한다. 추가 자세한 내용은 Section 7.2를 참조한다.

2.4.1. 클라이언트 시크릿

클라이언트 시크릿을 보유한 기밀 클라이언트를 지원하기 위해, 권한 부여 서버는 클라이언트가 다음 매개변수를 사용하여 요청 본문 콘텐츠에 클라이언트 자격 증명을 포함하는 것을 지원해야 한다:

"client_id":

REQUIRED. Section 2.2에 설명된 등록 과정 중 클라이언트에 발급된 클라이언트 식별자.

"client_secret":

REQUIRED. 클라이언트 시크릿.

매개변수는 요청 콘텐츠에서만 전송될 수 있으며 요청 URI에 포함되어서는 안 된다.

이는 [RFC7591]의 Section 2에 정의된 client_secret_post로도 알려져 있다.

예를 들어, 콘텐츠 매개변수를 사용하여 접근 토큰을 갱신하는 요청 (Section 4.3) (표시 목적의 추가 줄바꿈 포함):

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

권한 부여 서버는 클라이언트 시크릿을 발급받은 클라이언트를 인증하기 위해 HTTP Basic 인증 스킴을 지원할 수 있다.

권한 부여 서버에 인증하기 위해 [RFC9110]의 Section 11에 정의된 HTTP Basic 인증 스킴을 사용할 때, 클라이언트 식별자는 Appendix B에 따라 application/x-www-form-urlencoded 인코딩 알고리즘을 사용하여 인코딩되고, 인코딩된 값이 사용자 이름으로 사용된다. 클라이언트 시크릿도 같은 알고리즘으로 인코딩되어 비밀번호로 사용된다.

이는 [RFC7591]의 Section 2에 정의된 client_secret_basic으로도 알려져 있다.

예(표시 목적의 추가 줄바꿈 포함):

Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

참고: 클라이언트 식별자와 시크릿을 먼저 폼 인코딩한 다음, 인코딩된 값을 HTTP Basic 인증 사용자 이름과 비밀번호로 사용하는 이 방법은 과거에 많은 상호 운용성 문제를 초래했다. 일부 구현은 인코딩 단계를 놓쳤거나, 특정 문자만 인코딩하기로 했거나, 자격 증명을 검증할 때 인코딩 요구사항을 무시하여, 클라이언트가 개별 권한 부여 서버에 자격 증명을 제시하는 방식을 특별 처리해야 했다. 요청 본문 콘텐츠에 자격 증명을 포함하면 인코딩 문제를 피하고 더 상호 운용 가능한 구현으로 이어진다.

클라이언트 시크릿 인증 방법에는 비밀번호가 포함되므로, 권한 부여 서버는 이를 사용하는 모든 엔드포인트를 무차별 대입 공격으로부터 보호해야 한다.

2.4.2. 기타 인증 방법

권한 부여 서버는 자신의 보안 요구사항과 일치하는 적절한 인증 스킴을 지원할 수 있다. 다른 인증 방법을 사용할 때, 권한 부여 서버는 클라이언트 식별자(등록 레코드)와 인증 스킴 간의 매핑을 정의해야 한다.

mTLS [RFC8705] 및 Private Key JWT ([RFC7523], [I-D.ietf-oauth-rfc7523bis]) 같은 일부 추가 인증 방법은 "OAuth Token Endpoint Authentication Methods" 레지스트리에 정의되어 있으며, 토큰 엔드포인트 보호라는 특정 사용을 넘어 일반적인 클라이언트 인증 방법으로도 유용할 수 있다.

2.5. 등록되지 않은 클라이언트

이 명세는 클라이언트가 권한 부여 서버에 등록되어야 한다고 요구하지 않는다. 그러나 등록되지 않은 클라이언트의 사용은 이 명세의 범위를 벗어나며, 추가 보안 분석과 상호 운용성 영향에 대한 검토가 필요하다.

3. 프로토콜 엔드포인트

권한 부여 과정은 두 개의 권한 부여 서버 엔드포인트 (HTTP 리소스)를 사용한다:

그리고 하나의 클라이언트 엔드포인트도 사용한다:

모든 권한 부여 그랜트 유형이 두 엔드포인트를 모두 사용하는 것은 아니다. 확장 그랜트 유형은 필요에 따라 추가 엔드포인트를 정의할 수 있다.

3.1. 권한 부여 엔드포인트

권한 부여 엔드포인트는 리소스 소유자와 상호작용하고 권한 부여 그랜트를 얻는 데 사용된다. 권한 부여 서버는 먼저 리소스 소유자를 인증해야 한다. 권한 부여 서버가 리소스 소유자를 인증하는 방식 (예: 사용자 이름 및 비밀번호 로그인, passkey, 연합 로그인 또는 확립된 세션 사용)은 이 명세의 범위를 벗어난다.

클라이언트가 권한 부여 엔드포인트의 URL을 얻는 수단은 이 명세의 범위를 벗어나지만, URL은 일반적으로 서비스 문서에 제공되거나 권한 부여 서버의 메타데이터 문서 [RFC8414]에 제공된다.

권한 부여 엔드포인트 URL은 프래그먼트 구성 요소를 포함해서는 안 되며, 쿼리 문자열 구성 요소 Appendix C.1를 포함할 수 있다. 이는 추가 쿼리 매개변수를 추가할 때 유지되어야 한다.

권한 부여 서버는 권한 부여 엔드포인트에 대해 HTTP GET 메서드 [RFC9110]의 Section 9.3.1 사용을 지원해야 하며, POST 메서드([RFC9110]의 Section 9.3.3)도 지원할 수 있다.

권한 부여 서버는 권한 부여 엔드포인트로 전송된 인식되지 않은 요청 매개변수를 무시해야 한다.

이 명세에서 정의한 요청 및 응답 매개변수는 두 번 이상 포함되어서는 안 된다. 이 요구사항은 확장이 특정 매개변수에 대해 달리 명시적으로 정의하지 않는 한, 확장에서 정의한 매개변수에도 적용된다. 값 없이 전송된 매개변수는 요청에서 생략된 것처럼 처리되어야 한다.

사용자 자격 증명을 포함할 가능성이 있는 요청을 리디렉션하는 권한 부여 서버는 이러한 사용자 자격 증명을 우발적으로 전달하지 않도록 해야 한다 (자세한 내용은 Section 7.5.3 참조).

Cross-Origin Resource Sharing [WHATWG.CORS]은 권한 부여 엔드포인트에서 지원되어서는 안 된다. 클라이언트가 이 엔드포인트에 직접 접근하지 않고, 대신 사용자 에이전트를 해당 엔드포인트로 리디렉션하기 때문이다.

3.2. 토큰 엔드포인트

토큰 엔드포인트는 클라이언트가 Section 4Section 4.3에 설명된 것 같은 그랜트를 사용하여 접근 토큰을 얻는 데 사용된다.

클라이언트가 토큰 엔드포인트의 URL을 얻는 수단은 이 명세의 범위를 벗어나지만, URL은 일반적으로 서비스 문서에 제공되어 클라이언트 개발 중에 구성되거나, 권한 부여 서버의 메타데이터 문서 [RFC8414]에 제공되어 런타임에 프로그래밍 방식으로 가져온다.

토큰 엔드포인트 URL은 프래그먼트 구성 요소를 포함해서는 안 되며, 쿼리 문자열 구성 요소 Appendix C.1를 포함할 수 있다.

클라이언트는 토큰 엔드포인트에 요청할 때 HTTP POST 메서드를 사용해야 한다.

권한 부여 서버는 토큰 엔드포인트로 전송된 인식되지 않은 요청 매개변수를 무시해야 한다.

값 없이 전송된 매개변수는 요청에서 생략된 것처럼 처리되어야 한다. 이 명세에서 정의한 요청 및 응답 매개변수는 두 번 이상 포함되어서는 안 된다. 이 요구사항은 확장이 특정 매개변수에 대해 달리 명시적으로 정의하지 않는 한, 확장에서 정의한 매개변수에도 적용된다.

브라우저 기반 애플리케이션 (예: 지원 백엔드 서버에 접근하지 않고 전적으로 클라이언트 측 JavaScript에서 실행되는 애플리케이션)을 지원하려는 권한 부여 서버는 애플리케이션이 응답을 볼 수 있도록 토큰 엔드포인트가 필요한 CORS [WHATWG.CORS] 헤더를 지원하도록 해야 한다. 권한 부여 서버가 메타데이터 URL, 동적 클라이언트 등록, 폐기, 인트로스펙션, 발견 또는 사용자 정보 엔드포인트 같은 추가 엔드포인트를 애플리케이션에 제공하는 경우, 이러한 엔드포인트도 브라우저 기반 애플리케이션이 접근할 수 있으며, 접근을 허용하도록 정의된 CORS 헤더도 필요하다. 자세한 내용은 [I-D.ietf-oauth-browser-based-apps]를 참조한다.

3.2.1. 클라이언트 인증

기밀 클라이언트는 토큰 엔드포인트에 요청할 때 Section 2.4에 설명된 대로 권한 부여 서버에 인증해야 한다.

클라이언트 인증은 다음에 사용된다:

  • 갱신 토큰과 권한 부여 코드를 그것들이 발급된 클라이언트에 바인딩하는 것을 집행한다. 클라이언트 인증은 권한 부여 코드가 안전하지 않은 채널을 통해 리디렉션 엔드포인트로 전송될 때 추가 보안 계층을 더한다.

  • 클라이언트를 비활성화하거나 그 자격 증명을 변경하여 손상된 클라이언트로부터 복구하며, 이를 통해 공격자가 도난당한 갱신 토큰을 남용하지 못하게 한다. 단일 클라이언트 자격 증명 집합을 변경하는 것은 전체 갱신 토큰 집합을 취소하는 것보다 훨씬 빠르다.

  • 정기적인 자격 증명 순환을 요구하는 인증 관리 모범 관행을 구현한다. 전체 갱신 토큰 집합의 순환은 어려울 수 있지만, 단일 클라이언트 자격 증명 집합의 순환은 훨씬 더 쉽다.

3.2.2. 토큰 엔드포인트 요청

클라이언트는 HTTP 요청 콘텐츠에서 UTF-8 문자 인코딩을 사용하고 Appendix C.2에 따른 폼 인코딩 직렬화 형식을 사용하여 다음 매개변수를 전송함으로써 토큰 엔드포인트에 요청한다:

"grant_type":

REQUIRED. 클라이언트가 특정 토큰 요청에서 사용하는 그랜트 유형의 식별자. 이 명세는 authorization_code, refresh_token, 및 client_credentials 값을 정의한다. 그랜트 유형은 토큰 요청에서 필요한 또는 지원되는 추가 매개변수를 결정한다. 이러한 그랜트 유형의 세부 사항은 아래에 정의되어 있다.

"client_id":

OPTIONAL. 매개변수에 의존하는 형태의 클라이언트 인증이 사용되거나, grant_type이 공개 클라이언트의 식별을 요구하는 경우 클라이언트 식별자가 필요하다.

기밀 클라이언트는 Section 3.2.1에 설명된 대로 권한 부여 서버에 인증해야 한다.

예를 들어, 클라이언트는 다음 HTTPS 요청을 수행한다 (표시 목적의 추가 줄바꿈 포함):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
&code_verifier=3641a2d12d66101249cdf7a79c000c1f8c05d2aafcf14bf146497bed

권한 부여 서버는 다음을 수행해야 한다:

  • 기밀 클라이언트 (또는 다른 인증 요구사항이 있는 클라이언트)에 대해 클라이언트 인증을 요구한다,

  • 클라이언트 인증이 포함된 경우 클라이언트를 인증한다

추가적인 그랜트 유형별 처리 규칙이 적용되며, 각각의 그랜트 유형과 함께 명시된다.

3.2.3. 토큰 엔드포인트 응답

접근 토큰 요청이 유효하고 권한 부여된 경우, 권한 부여 서버는 접근 토큰과 선택적 갱신 토큰을 발급한다.

클라이언트 인증이 실패했거나 유효하지 않은 경우, 권한 부여 서버는 Section 3.2.4에 설명된 오류 응답을 반환한다.

권한 부여 서버는 Appendix C.3에 따라 HTTP 응답을 생성하고, [RFC8259]에 정의된 application/json 미디어 유형을 사용하며, 다음 매개변수와 HTTP 200 (OK) 상태 코드를 포함하여 접근 토큰과 선택적 갱신 토큰을 발급한다:

"access_token":

REQUIRED. 권한 부여 서버가 발급한 접근 토큰.

"token_type":

REQUIRED. Section 1.4에 설명된 대로 발급된 접근 토큰의 유형. 값은 대소문자를 구분하지 않는다.

"expires_in":

RECOMMENDED. 접근 토큰의 수명을 초 단위로 나타내는 JSON 숫자. 예를 들어 값 3600은 접근 토큰이 응답이 생성된 시점부터 한 시간 후에 만료됨을 나타낸다. 생략된 경우 권한 부여 서버는 다른 수단으로 수명을 제공하거나 기본값을 문서화해야 한다. 권한 부여 서버가 접근 토큰을 조기에 만료시킬 수 있으며, 클라이언트는 제공된 수명 동안 접근 토큰이 유효할 것이라고 기대해서는 안 된다는 점에 유의한다.

"scope":

클라이언트가 요청한 범위와 동일한 경우 RECOMMENDED, 그렇지 않으면 REQUIRED. 접근 토큰의 범위는 Section 1.4.1에 설명된 대로이다.

"refresh_token":

OPTIONAL. 해당 토큰 요청에 전달된 그랜트를 기반으로 새 접근 토큰을 얻는 데 사용할 수 있는 갱신 토큰.

권한 부여 서버는 위험 평가와 자체 정책에 따라 특정 클라이언트에 갱신 토큰을 발급할지 결정해야 한다. 권한 부여 서버가 갱신 토큰을 발급하지 않기로 결정한 경우, 클라이언트는 예를 들어 새 권한 부여 코드 요청을 시작하는 것처럼 OAuth 흐름을 다시 시작하여 새 접근 토큰을 얻을 수 있다. 이러한 경우 권한 부여 서버는 사용자 경험을 최적화하기 위해 쿠키와 지속 그랜트를 사용할 수 있다.

갱신 토큰이 발급되는 경우, 해당 갱신 토큰은 리소스 소유자가 동의한 범위와 리소스 서버에 바인딩되어야 한다. 이는 합법적인 클라이언트에 의한 권한 상승을 방지하고 갱신 토큰 유출의 영향을 줄이기 위함이다.

매개변수는 Appendix C.3에 설명된 대로 JavaScript Object Notation (JSON) 구조로 직렬화된다.

권한 부여 서버는 토큰, 자격 증명 또는 기타 민감한 정보를 포함하는 모든 응답에 값이 no-store인 HTTP Cache-Control 응답 헤더 필드 ([RFC9111]의 Section 5.2 참조)를 포함해야 한다.

예:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter": "example_value"
}

클라이언트는 응답에서 인식되지 않은 값 이름을 무시해야 한다. 권한 부여 서버에서 받은 토큰 및 기타 값의 크기는 정의되지 않는다. 클라이언트는 값 크기에 대해 가정하지 않아야 한다. 권한 부여 서버는 자신이 발급하는 모든 값의 크기를 문서화해야 한다.

3.2.4. 토큰 엔드포인트 오류 응답

권한 부여 서버는 HTTP 400 (Bad Request) 상태 코드(달리 명시되지 않는 한)로 응답하고 다음 매개변수를 응답에 포함한다:

"error":

REQUIRED. 다음 중 하나의 단일 ASCII [USASCII] 오류 코드:

"invalid_request":

요청에 필수 매개변수가 없거나, 지원되지 않는 매개변수 값(그랜트 유형 제외)이 포함되어 있거나, 매개변수가 반복되거나, 여러 자격 증명이 포함되어 있거나, 클라이언트 인증에 둘 이상의 메커니즘을 사용하거나, 권한 부여 요청에서 code_challenge가 전송되지 않았음에도 code_verifier를 포함하거나, 그 밖에 형식이 잘못된 경우.

"invalid_client":

클라이언트 인증이 실패했다 (예: 알 수 없는 클라이언트, 클라이언트 인증이 포함되지 않음, 또는 지원되지 않는 인증 방법). 권한 부여 서버는 어떤 HTTP 인증 스킴이 지원되는지 나타내기 위해 HTTP 401 (Unauthorized) 상태 코드를 반환할 수 있다. 클라이언트가 Authorization 요청 헤더 필드를 통해 인증을 시도한 경우, 권한 부여 서버는 HTTP 401 (Unauthorized) 상태 코드로 응답하고 클라이언트가 사용한 인증 스킴과 일치하는 WWW-Authenticate 응답 헤더 필드를 포함해야 한다.

"invalid_grant":

제공된 권한 부여 그랜트 (예: 권한 부여 코드, 리소스 소유자 자격 증명) 또는 갱신 토큰이 유효하지 않거나, 만료되었거나, 취소되었거나, 권한 부여 요청에 사용된 리디렉션 URI와 일치하지 않거나, 다른 클라이언트에 발급된 경우.

"unauthorized_client":

인증된 클라이언트가 이 권한 부여 그랜트 유형을 사용할 권한이 없는 경우.

"unsupported_grant_type":

권한 부여 그랜트 유형이 권한 부여 서버에서 지원되지 않는 경우.

"invalid_scope":

요청된 범위가 유효하지 않거나, 알 수 없거나, 형식이 잘못되었거나, 리소스 소유자가 부여한 범위를 초과한 경우.

error 매개변수의 값은 집합 %x20-21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

"error_description":

OPTIONAL. 발생한 오류를 클라이언트 개발자가 이해하는 데 도움을 주기 위해 추가 정보를 제공하는 사람이 읽을 수 있는 ASCII [USASCII] 텍스트. error_description 매개변수의 값은 집합 %x20-21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

"error_uri":

OPTIONAL. 오류에 대한 정보가 있는 사람이 읽을 수 있는 웹 페이지를 식별하는 URI로, 클라이언트 개발자에게 오류에 대한 추가 정보를 제공하는 데 사용된다. error_uri 매개변수의 값은 URI-reference 구문을 따라야 하므로 집합 %x21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

매개변수는 Appendix C.3에 정의된 application/json 미디어 유형을 사용하여 HTTP 응답의 콘텐츠에 포함된다.

예:

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
 "error": "invalid_request"
}

4. 그랜트 유형

접근 토큰을 요청하기 위해 클라이언트는 리소스 소유자로부터 권한 부여를 얻는다. 이 명세는 다음 권한 부여 그랜트 유형을 정의한다:

또한 추가 그랜트 유형을 정의하기 위한 확장 메커니즘도 제공한다.

4.1. 권한 부여 코드 그랜트

권한 부여 코드 그랜트 유형은 접근 토큰과 갱신 토큰을 모두 얻는 데 사용된다.

이 그랜트 유형은 추가 권한 부여 엔드포인트를 사용하여 권한 부여 서버가 리소스 접근에 대한 동의를 얻기 위해 리소스 소유자와 상호작용할 수 있게 한다.

이는 리디렉션 기반 흐름이므로, 클라이언트는 리소스 소유자의 사용자 에이전트(일반적으로 웹 브라우저)로 흐름을 시작할 수 있어야 하며, 권한 부여 서버에서 다시 리디렉션될 수 있어야 한다.

 +----------+
 | Resource |
 |   Owner  |
 +----------+
       ^
       |
       |
 +-----|----+          Client Identifier      +---------------+
 | .---+---------(1)-- & Redirect URI ------->|               |
 | |   |    |                                 |               |
 | |   '---------(2)-- User authenticates --->|               |
 | | User-  |                                 | Authorization |
 | | Agent  |                                 |     Server    |
 | |        |                                 |               |
 | |    .--------(3)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(4)-- Authorization Code ---------'      |
 |  Client |          & Redirect URI                     |
 |         |                                             |
 |         |<---(5)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)
그림 3: 권한 부여 코드 흐름

그림 3에 표시된 흐름은 다음 단계를 포함한다:

(1) 클라이언트는 리소스 소유자의 사용자 에이전트를 권한 부여 엔드포인트로 안내하여 흐름을 시작한다. 클라이언트는 자신의 클라이언트 식별자, 코드 챌린지(생성된 코드 검증자에서 파생됨), 선택적 요청 범위, 선택적 로컬 상태, 그리고 접근이 허용되면 (또는 거부되면) 권한 부여 서버가 사용자 에이전트를 다시 보낼 리디렉션 URI를 포함한다.

(2) 권한 부여 서버는 (사용자 에이전트를 통해) 리소스 소유자를 인증하고, 리소스 소유자가 클라이언트의 접근 요청을 허용하는지 거부하는지를 확정한다.

(3) 리소스 소유자가 접근을 허용한다고 가정하면, 권한 부여 서버는 이전에 제공된 리디렉션 URI(요청 또는 클라이언트 등록 중 제공됨)를 사용하여 사용자 에이전트를 클라이언트로 다시 리디렉션한다. 리디렉션 URI에는 권한 부여 코드와 클라이언트가 앞서 제공한 로컬 상태가 포함된다.

(4) 클라이언트는 이전 단계에서 받은 권한 부여 코드를 포함하고 코드 검증자를 포함하여 권한 부여 서버의 토큰 엔드포인트에서 접근 토큰을 요청한다. 요청할 때 클라이언트는 가능하면 권한 부여 서버에 인증한다. 클라이언트는 검증을 위해 권한 부여 코드를 얻는 데 사용한 리디렉션 URI를 포함한다.

(5) 권한 부여 서버는 가능하면 클라이언트를 인증하고, 권한 부여 코드를 검증하며, 코드 검증자를 검증하고, 수신한 리디렉션 URI가 단계 (3)에서 사용자 에이전트를 클라이언트로 리디렉션하는 데 사용된 URI와 일치하는지 확인한다. 유효한 경우, 권한 부여 서버는 접근 토큰과 선택적으로 갱신 토큰으로 응답한다.

4.1.1. 권한 부여 요청

권한 부여 요청을 시작하기 위해 클라이언트는 권한 부여 서버의 권한 부여 엔드포인트 URI에 매개변수를 추가하여 권한 부여 요청 URI를 구성한다. 클라이언트는 결국 요청을 시작하기 위해 사용자 에이전트를 이 URI로 리디렉션한다.

클라이언트는 권한 부여 코드 주입 및 CSRF 공격을 방지하기 위해 권한 부여 요청마다 "코드 검증자"라고 하는 고유한 비밀을 사용한다. 클라이언트는 먼저 코드 검증자를 생성한 다음, 권한 부여 요청에 포함할 "코드 챌린지"를 파생한다. 클라이언트는 토큰 엔드포인트에서 권한 부여 코드를 교환할 때 코드 검증자를 사용하여 권한 부여 코드를 사용하는 클라이언트가 그것을 요청한 동일한 클라이언트임을 증명한다.

클라이언트는 Appendix C.1에 설명된 대로 권한 부여 엔드포인트 URI의 쿼리 구성 요소에 다음 매개변수를 추가하여 요청 URI를 구성한다:

"response_type":

REQUIRED. 권한 부여 엔드포인트는 서로 다른 요청 및 응답 매개변수 집합을 지원한다. 클라이언트는 특정 response_type 값을 사용하여 흐름 유형을 결정한다. 이 명세는 code 값을 정의하며, 이는 클라이언트가 권한 부여 코드 흐름을 사용하려 함을 나타내기 위해 사용되어야 한다.

확장 응답 유형은 값의 순서가 중요하지 않은 공백 구분(%x20) 값 목록을 포함할 수 있다 (예: 응답 유형 a bb a와 동일하다). 이러한 복합 응답 유형의 의미는 각 명세에서 정의된다.

일부 확장 응답 유형은 [OpenID.Connect]에서 정의된다.

권한 부여 요청에 response_type 매개변수가 없거나, 응답 유형을 이해할 수 없는 경우, 권한 부여 서버는 Section 4.1.2.1에 설명된 대로 오류 응답을 반환해야 한다.

"client_id":

REQUIRED. Section 2.2에 설명된 클라이언트 식별자.

"code_challenge":

Section 7.5.1의 특정 요구사항이 충족되지 않는 한 REQUIRED. 코드 검증자에서 파생된 코드 챌린지.

"code_challenge_method":

OPTIONAL, 요청에 없으면 기본값은 plain이다. 코드 검증자 변환 방법은 S256 또는 plain이다.

"redirect_uri":

이 클라이언트에 하나의 리디렉션 URI만 등록된 경우 OPTIONAL. 이 클라이언트에 여러 리디렉션 URI가 등록된 경우 REQUIRED. Section 2.3.2를 참조한다.

"scope":

OPTIONAL. Section 1.4.1에 설명된 접근 요청의 범위.

"state":

OPTIONAL. 요청과 콜백 사이에서 상태를 유지하기 위해 클라이언트가 사용하는 불투명한 값. 권한 부여 서버는 사용자 에이전트를 클라이언트로 다시 리디렉션할 때 이 값을 포함한다.

code_verifier는 각 권한 부여 요청에 대해 생성되는 고유하고 엔트로피가 높은 암호학적 난수 문자열이며, 예약되지 않은 문자 [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"를 사용하고, 최소 길이는 43자, 최대 길이는 128자이다.

클라이언트는 code_verifier를 임시로 저장하고, 권한 부여 요청에서 사용할 code_challenge를 계산한다.

code_verifier의 ABNF는 다음과 같다.

code-verifier = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39

클라이언트는 권한 부여 요청에서 code_verifier를 노출하지 않는 코드 챌린지 방법을 사용해야 한다. 그렇지 않으면 권한 부여 요청을 읽을 수 있는 공격자 ([RFC9700]의 공격자 A4 참조)가 이 메커니즘이 제공하는 보안을 깨뜨릴 수 있다. 현재 S256이 그러한 유일한 방법이다.

참고: 코드 검증자는 값을 추측하기 어렵게 만들 만큼 충분한 엔트로피를 가져야 한다. 적절한 난수 생성기의 출력을 사용하여 32옥텟 시퀀스를 만드는 것이 권장된다. 그런 다음 옥텟 시퀀스를 base64url 인코딩하여 코드 검증자로 사용할 43옥텟 URL 안전 문자열을 생성한다.

그런 다음 클라이언트는 코드 검증자에 대해 다음 변환 중 하나를 사용하여 코드 검증자에서 파생된 code_challenge를 만든다:

S256
  code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

plain
  code_challenge = code_verifier

클라이언트가 S256을 사용할 수 있다면 반드시 S256을 사용해야 한다. S256은 서버에서 구현 필수(MTI)이기 때문이다. 클라이언트는 해싱 함수를 사용할 수 없는 제약 환경처럼 어떤 기술적 이유로 S256을 지원할 수 없고, 대역 외 구성 또는 권한 부여 서버 메타데이터 [RFC8414]를 통해 서버가 plain을 지원함을 아는 경우에만 plain을 사용할 수 있다.

code_challenge의 ABNF는 다음과 같다.

code-challenge = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39

code_challengecode_verifier 속성은 이 기법이 처음 개발된 "Proof-Key for Code Exchange", 즉 PKCE [RFC7636]로 알려진 OAuth 2.0 확장에서 채택되었다.

권한 부여 서버는 code_challengecode_verifier 매개변수를 지원해야 한다.

클라이언트는 code_challengecode_verifier를 사용해야 하며, 권한 부여 서버는 Section 7.5.1에 설명된 조건을 제외하고 그 사용을 강제해야 한다. 이 경우에도 위에서 설명한 대로 code_challengecode_verifier를 사용하고 강제하는 것이 여전히 권장된다.

statescope 매개변수는 민감한 클라이언트 또는 리소스 소유자 정보를 평문으로 포함해서는 안 된다. 이들은 안전하지 않은 채널을 통해 전송되거나 안전하지 않게 저장될 수 있기 때문이다.

클라이언트는 HTTP 리디렉션 또는 사용자 에이전트를 통해 사용할 수 있는 다른 수단을 사용하여 리소스 소유자를 구성된 URI로 안내한다.

예를 들어, 클라이언트는 사용자 에이전트가 다음 HTTPS 요청을 하도록 안내한다(표시 목적의 추가 줄바꿈 포함):

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
    &code_challenge=6fdkQaPm51l13DSukcAH3Mdx7_ntecHYd1vi3n0hMZY
    &code_challenge_method=S256 HTTP/1.1
Host: server.example.com

권한 부여 서버는 모든 필수 매개변수가 있고 유효한지 확인하기 위해 요청을 검증한다.

특히, 권한 부여 서버는 요청에 redirect_uri가 있는 경우 이를 검증해야 하며, 클라이언트 등록(Section 2) 중 이전에 확립된 등록된 리디렉션 URI 중 하나와 일치하는지 확인해야 한다. 두 URI를 비교할 때 권한 부여 서버는 두 URI가 동일함을 보장해야 하며, 자세한 내용은 [RFC3986]의 Section 6.2.1, 단순 문자열 비교를 참조한다. 유일한 예외는 localhost URI를 사용하는 네이티브 앱이다. 이 경우 권한 부여 서버는 [RFC8252]의 Section 7.3에 설명된 대로 가변 포트 번호를 허용해야 한다.

요청이 유효하면, 권한 부여 서버는 리소스 소유자를 인증하고 (리소스 소유자에게 묻거나 다른 수단으로 승인을 확립하여) 권한 부여 결정을 얻는다.

결정이 확립되면, 권한 부여 서버는 HTTP 리디렉션 응답 또는 사용자 에이전트를 통해 사용할 수 있는 다른 수단을 사용하여 사용자 에이전트를 제공된 클라이언트 리디렉션 URI로 안내한다.

4.1.2. 권한 부여 응답

리소스 소유자가 접근 요청을 허용하면, 권한 부여 서버는 권한 부여 코드를 발급하고, 확장에서 달리 명시하지 않는 한 Appendix C.1에 설명된 쿼리 문자열 직렬화를 사용하여 리디렉션 URI의 쿼리 구성 요소에 다음 매개변수를 추가함으로써 이를 클라이언트에 전달한다:

"code":

REQUIRED. 권한 부여 코드는 권한 부여 서버가 생성하며 클라이언트에는 불투명하다. 권한 부여 코드는 유출 위험을 완화하기 위해 발급 직후 만료되어야 한다. 최대 권한 부여 코드 수명은 10분이 권장된다. 권한 부여 코드는 클라이언트 식별자, 코드 챌린지 및 리디렉션 URI에 바인딩된다.

"state":

클라이언트 권한 부여 요청에 state 매개변수가 있었다면 REQUIRED. 클라이언트에서 받은 정확한 값.

"iss":

OPTIONAL. 클라이언트가 둘 이상의 권한 부여 서버와 상호작용하는 경우 mix-up 공격을 방지하기 위해 사용할 수 있는 권한 부여 서버의 식별자. 이 매개변수가 필요한 경우와 클라이언트가 이를 사용하여 mix-up 공격을 방지하는 방법에 대한 추가 자세한 내용은 Section 7.14[RFC9207]를 참조한다.

예를 들어, 권한 부여 서버는 다음 HTTP 응답을 전송하여 사용자 에이전트를 리디렉션한다:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
          &state=xyz&iss=https%3A%2F%2Fauthorization-server.example.com

클라이언트는 인식되지 않은 응답 매개변수를 무시해야 한다. 권한 부여 코드 문자열 크기는 이 명세에서 정의되지 않는다. 클라이언트는 코드 값 크기에 대해 가정하지 않아야 한다. 권한 부여 서버는 자신이 발급하는 모든 값의 크기를 문서화해야 한다.

권한 부여 서버는 발급된 권한 부여 코드와 code_challengecode_challenge_method 값을 연결해야 하며, 그래야 나중에 코드 챌린지를 검증할 수 있다.

서버가 발급된 코드와 code_challenge를 연결하는 정확한 방법은 이 명세의 범위를 벗어난다. 코드 챌린지는 서버에 저장되어 그곳에서 코드와 연결될 수 있다. code_challengecode_challenge_method 값은 코드 자체에 암호화된 형태로 저장될 수 있지만, 서버는 AS가 아닌 엔터티가 추출할 수 있는 형태로 응답 매개변수에 code_challenge 값을 포함해서는 안 된다.

클라이언트는 공격자가 권한 부여 응답에 권한 부여 코드를 주입(재전송)하는 것을 방지해야 한다. code_challengecode_verifier를 사용하면 권한 부여 서버가 일치하지 않는 code_verifier가 있는 토큰 요청을 거부하므로 권한 부여 코드 주입을 방지한다. 자세한 내용은 Section 7.5.1을 참조한다.

4.1.2.1. 권한 부여 오류 응답

요청이 누락, 유효하지 않음 또는 불일치하는 리디렉션 URI로 인해 실패하거나, 클라이언트 식별자가 없거나 유효하지 않은 경우, 권한 부여 서버는 사용자 에이전트를 유효하지 않은 리디렉션 URI로 리디렉션해서는 안 되며, 예를 들어 사용자의 브라우저에 메시지를 표시하여 리소스 소유자에게 오류를 알려야 한다.

권한 부여 서버는 공개 클라이언트의 code_challenge 없는 요청을 거부해야 하며, 클라이언트가 다른 방법으로 권한 부여 코드 주입을 완화한다는 합리적 보장이 없는 한 다른 클라이언트의 그러한 요청도 거부해야 한다. 자세한 내용은 Section 7.5.1을 참조한다.

서버가 요청된 code_challenge_method 변환을 지원하지 않는 경우, 권한 부여 엔드포인트는 error 값을 invalid_request로 설정한 권한 부여 오류 응답을 반환해야 한다. error_description 또는 error_uri의 응답은 변환 알고리즘이 지원되지 않음과 같은 오류의 성격을 설명해야 한다.

리소스 소유자가 접근 요청을 거부하거나, 누락 또는 유효하지 않은 리디렉션 URI 이외의 이유로 요청이 실패한 경우, 권한 부여 서버는 사용자 에이전트를 리디렉션 URI로 리디렉션하고 Appendix C.1에 설명된 대로 리디렉션 URI의 쿼리 구성 요소에 다음 매개변수를 추가하여 클라이언트에 알린다:

"error":

REQUIRED. 다음 중 하나의 단일 ASCII [USASCII] 오류 코드:

"invalid_request":

요청에 필수 매개변수가 없거나, 유효하지 않은 매개변수 값이 포함되어 있거나, 매개변수가 두 번 이상 포함되어 있거나, 그 밖에 형식이 잘못된 경우.

"unauthorized_client":

클라이언트가 이 방법을 사용하여 권한 부여 코드를 요청할 권한이 없는 경우.

"access_denied":

리소스 소유자 또는 권한 부여 서버가 요청을 거부한 경우.

"unsupported_response_type":

권한 부여 서버가 이 방법을 사용해 권한 부여 코드를 얻는 것을 지원하지 않는 경우.

"invalid_scope":

요청된 범위가 유효하지 않거나, 알 수 없거나, 형식이 잘못된 경우.

"server_error":

권한 부여 서버가 요청을 수행하지 못하게 하는 예기치 않은 조건을 만난 경우. (HTTP 리디렉션을 통해 클라이언트에 500 Internal Server Error HTTP 상태 코드를 반환할 수 없기 때문에 이 오류 코드가 필요하다.)

"temporarily_unavailable":

권한 부여 서버가 일시적인 과부하 또는 서버 유지관리로 인해 현재 요청을 처리할 수 없는 경우. (HTTP 리디렉션을 통해 클라이언트에 503 Service Unavailable HTTP 상태 코드를 반환할 수 없기 때문에 이 오류 코드가 필요하다.)

error 매개변수의 값은 집합 %x20-21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

"error_description":

OPTIONAL. 발생한 오류를 클라이언트 개발자가 이해하는 데 도움을 주기 위해 추가 정보를 제공하는 사람이 읽을 수 있는 ASCII [USASCII] 텍스트. error_description 매개변수의 값은 집합 %x20-21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

"error_uri":

OPTIONAL. 오류에 대한 정보가 있는 사람이 읽을 수 있는 웹 페이지를 식별하는 URI로, 클라이언트 개발자에게 오류에 대한 추가 정보를 제공하는 데 사용된다. error_uri 매개변수의 값은 URI-reference 구문을 따라야 하므로 집합 %x21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

"state":

클라이언트 권한 부여 요청에 state 매개변수가 있었다면 REQUIRED. 클라이언트에서 받은 정확한 값.

"iss":

OPTIONAL. 권한 부여 서버의 식별자. 자세한 내용은 위의 Section 4.1.2를 참조한다.

예를 들어, 권한 부여 서버는 다음 HTTP 응답으로 사용자 에이전트를 리디렉션하여 요청이 거부되었음을 나타낸다:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?error=access_denied
          &state=xyz&iss=https%3A%2F%2Fauthorization-server.example.com

4.1.3. 토큰 엔드포인트 확장

권한 부여 그랜트 유형은 토큰 엔드포인트에서 grant_typeauthorization_code로 식별된다.

이 값이 설정된 경우, Section 3.2.2 외에 다음 추가 토큰 요청 매개변수가 지원된다:

"code":

REQUIRED. 권한 부여 서버에서 받은 권한 부여 코드.

"code_verifier":

권한 부여 요청에 code_challenge 매개변수가 포함된 경우 REQUIRED. 그렇지 않으면 사용해서는 안 된다. 원래 코드 검증자 문자열.

"client_id":

클라이언트가 Section 3.2.1에 설명된 대로 권한 부여 서버에 인증하지 않는 경우 REQUIRED.

권한 부여 서버는 주어진 권한 부여 코드에 대해 접근 토큰을 한 번만 반환해야 한다.

이전에 성공한 토큰 요청과 동일한 권한 부여 코드로 두 번째 유효한 토큰 요청이 이루어지면, 권한 부여 서버는 요청을 거부해야 하며 (가능한 경우) 해당 권한 부여 코드를 기반으로 이전에 발급한 모든 접근 토큰과 갱신 토큰을 취소해야 한다. 자세한 내용은 Section 7.5.2를 참조한다.

예를 들어, 클라이언트는 다음 HTTPS 요청을 수행한다 (표시 목적의 추가 줄바꿈 포함):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&code_verifier=3641a2d12d66101249cdf7a79c000c1f8c05d2aafcf14bf146497bed

Section 3.2.2의 처리 규칙 외에도, 권한 부여 서버는 다음을 수행해야 한다:

  • 권한 부여 코드가 인증된 기밀 클라이언트에 발급되었는지 확인하거나, 클라이언트가 공개 클라이언트인 경우 코드가 요청의 client_id에 발급되었는지 확인한다,

  • 권한 부여 코드가 유효한지 검증한다,

  • code_verifier 매개변수가 권한 부여 요청에 code_challenge 매개변수가 있었던 경우에만 존재하는지 검증한다,

  • code_verifier가 있는 경우, 수신한 code_verifier에서 코드 챌린지를 계산하고, 먼저 클라이언트가 지정한 code_challenge_method 방법에 따라 변환한 뒤, 이전에 연결된 code_challenge와 비교하여 code_verifier를 검증한다, 그리고

  • 토큰 요청의 권한 부여 코드와 연결된 권한 부여 요청에 code_challenge가 없었다면, 권한 부여 서버는 토큰 요청을 거부해야 한다.

토큰 요청의 redirect_uri 매개변수와 관련하여 OAuth 2.0 클라이언트와의 하위 호환성에 대한 자세한 내용은 Section 10.2를 참조한다.

4.2. 클라이언트 자격 증명 그랜트

클라이언트가 자신이 제어하는 보호된 리소스 또는 권한 부여 서버와 사전에 조정된 다른 리소스 소유자의 보호된 리소스에 대한 접근을 요청하는 경우(그 방법은 이 명세의 범위를 벗어남), 클라이언트는 자신의 클라이언트 자격 증명(또는 다른 지원되는 인증 수단)만을 사용하여 접근 토큰을 요청할 수 있다.

클라이언트 자격 증명 그랜트 유형은 기밀 클라이언트만 사용해야 한다.

     +---------+                                  +---------------+
     |         |                                  |               |
     |         |>--(1)- Client Authentication --->| Authorization |
     | Client  |                                  |     Server    |
     |         |<--(2)---- Access Token ---------<|               |
     |         |                                  |               |
     +---------+                                  +---------------+
그림 4: 클라이언트 자격 증명 그랜트

그림 4에 표시된 클라이언트 자격 증명 그랜트 사용은 다음 단계를 포함한다:

(1) 클라이언트는 권한 부여 서버에 인증하고 토큰 엔드포인트에서 접근 토큰을 요청한다.

(2) 권한 부여 서버는 클라이언트를 인증하고, 유효한 경우 접근 토큰을 발급한다.

4.2.1. 토큰 엔드포인트 확장

클라이언트 자격 증명 그랜트 유형은 토큰 엔드포인트에서 grant_typeclient_credentials로 식별된다.

이 값이 설정된 경우, Section 3.2.2 외에 다음 추가 토큰 요청 매개변수가 지원된다:

"scope":

OPTIONAL. Section 1.4.1에 설명된 접근 요청의 범위.

예를 들어, 클라이언트는 전송 계층 보안을 사용하여 다음 HTTP 요청을 수행한다(표시 목적의 추가 줄바꿈 포함):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

권한 부여 서버는 클라이언트를 인증해야 한다.

4.3. 갱신 토큰 그랜트

갱신 토큰은 권한 부여 서버가 클라이언트에 발급하는 자격 증명이며, 기존 그랜트를 기반으로 새(신선한) 접근 토큰을 얻는 데 사용할 수 있다. 클라이언트는 이전 접근 토큰이 만료되었거나, 클라이언트가 이전에 각 그랜트가 승인한 것보다 더 좁은 범위의 접근 토큰을 얻었고 나중에 동일한 그랜트 아래에서 다른 범위의 접근 토큰이 필요하기 때문에 이 옵션을 사용한다.

갱신 토큰은 전송 및 저장 중 기밀로 유지되어야 하며, 권한 부여 서버와 갱신 토큰이 발급된 클라이언트 사이에서만 공유되어야 한다. 권한 부여 서버는 갱신 토큰과 그것이 발급된 클라이언트 사이의 바인딩을 유지해야 한다.

권한 부여 서버는 클라이언트 신원을 인증할 수 있을 때마다 갱신 토큰과 클라이언트 신원 사이의 바인딩을 검증해야 한다. 클라이언트 인증이 불가능한 경우, 권한 부여 서버는 발신자 제한 갱신 토큰을 발급하거나 Section 4.3.1에 설명된 갱신 토큰 순환을 사용해야 한다.

권한 부여 서버는 권한 없는 당사자가 유효한 갱신 토큰을 만들도록 갱신 토큰을 생성, 수정 또는 추측할 수 없도록 보장해야 한다.

4.3.1. 토큰 엔드포인트 확장

갱신 토큰 그랜트 유형은 토큰 엔드포인트에서 grant_typerefresh_token으로 식별된다.

이 값이 설정된 경우, Section 3.2.2 외에 다음 추가 매개변수가 지원된다:

"refresh_token":

REQUIRED. 클라이언트에 발급된 갱신 토큰.

"scope":

OPTIONAL. Section 1.4.1에 설명된 접근 요청의 범위. 요청된 범위는 리소스 소유자가 원래 부여하지 않은 범위를 포함해서는 안 되며, 생략된 경우 리소스 소유자가 원래 부여한 범위와 동일한 것으로 처리된다.

갱신 토큰은 일반적으로 추가 접근 토큰을 요청하는 데 사용되는 장기 지속 자격 증명이므로, 갱신 토큰은 그것이 발급된 클라이언트에 바인딩된다. 기밀 클라이언트는 Section 3.2.1에 설명된 대로 권한 부여 서버에 인증해야 한다.

예를 들어, 클라이언트는 전송 계층 보안을 사용하여 다음 HTTP 요청을 수행한다(표시 목적의 추가 줄바꿈 포함):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

Section 3.2.2의 처리 규칙 외에도, 권한 부여 서버는 다음을 수행해야 한다:

  • 요청에 클라이언트 인증이 포함된 경우, 갱신 토큰이 인증된 클라이언트에 발급되었는지 확인하거나, 요청에 client_id가 포함된 경우 갱신 토큰이 일치하는 클라이언트에 발급되었는지 확인한다

  • 이 갱신 토큰에 해당하는 그랜트가 여전히 활성 상태인지 검증한다

  • 갱신 토큰을 검증한다

권한 부여 서버는 공개 클라이언트에 대해 악의적 행위자에 의한 갱신 토큰 재전송을 탐지하기 위해 다음 방법 중 하나를 사용해야 한다:

  • 발신자 제한 갱신 토큰: 권한 부여 서버는 예를 들어 DPoP [RFC9449] 또는 mTLS [RFC8705]를 활용하여 갱신 토큰을 특정 클라이언트 인스턴스에 암호학적으로 바인딩한다.

  • 갱신 토큰 순환: 권한 부여 서버는 접근 토큰 갱신 응답마다 새 갱신 토큰을 발급한다. 이전 갱신 토큰은 무효화되지만, 관계에 대한 정보는 권한 부여 서버에 유지된다. 갱신 토큰이 손상되고 이후 공격자와 합법적인 클라이언트가 모두 사용하면, 둘 중 하나가 무효화된 갱신 토큰을 제시하게 되며, 이는 권한 부여 서버에 침해 사실을 알린다. 권한 부여 서버는 어느 당사자가 유효하지 않은 갱신 토큰을 제출했는지 판단할 수 없지만, 활성 갱신 토큰과 그에 연결된 접근 권한 부여 그랜트도 취소한다. 이는 합법적인 클라이언트가 새로운 권한 부여 그랜트를 얻어야 하는 비용으로 공격을 중단시킨다.

구현 참고: 갱신 토큰이 속한 그랜트는 갱신 토큰 자체에 인코딩될 수 있다. 이는 권한 부여 서버가 갱신 토큰이 속한 그랜트를 효율적으로 결정하고, 나아가 취소되어야 하는 모든 갱신 토큰을 결정할 수 있게 한다. 이 경우 권한 부여 서버는 예를 들어 서명을 사용하여 갱신 토큰 값의 무결성을 보장해야 한다.

4.3.2. 갱신 토큰 응답

유효하고 권한 부여된 경우, 권한 부여 서버는 Section 3.2.3에 설명된 대로 접근 토큰을 발급한다.

권한 부여 서버는 새 갱신 토큰을 발급할 수 있으며, 이 경우 클라이언트는 이전 갱신 토큰을 버리고 새 갱신 토큰으로 교체해야 한다.

4.3.3. 갱신 토큰 권장사항

권한 부여 서버는 클라이언트에 새 갱신 토큰을 발급한 후 이전 갱신 토큰을 취소할 수 있다. 새 갱신 토큰이 발급되는 경우, 갱신 토큰 범위는 클라이언트가 요청에 포함한 갱신 토큰의 범위와 동일해야 한다.

권한 부여 서버는 다음과 같은 보안 이벤트가 발생한 경우 갱신 토큰을 자동으로 취소할 수 있다:

  • 비밀번호 변경

  • 권한 부여 서버에서 로그아웃

클라이언트가 일정 시간 동안 비활성 상태인 경우, 즉 갱신 토큰이 일정 시간 동안 새 접근 토큰을 얻는 데 사용되지 않은 경우, 갱신 토큰은 만료되어야 한다. 만료 시간은 권한 부여 서버의 재량에 따른다. 이는 전역 값일 수도 있고, 클라이언트 정책 또는 갱신 토큰에 연결된 그랜트(및 그 민감도)에 따라 결정될 수도 있다.

4.4. 확장 그랜트

클라이언트는 토큰 엔드포인트의 grant_type 매개변수 값으로 (권한 부여 서버가 정의한) 절대 URI를 사용하여 그랜트 유형을 지정하고, 필요한 추가 매개변수를 추가함으로써 확장 그랜트 유형을 사용한다.

예를 들어, 사용자가 별도 장치에서 클라이언트를 권한 부여한 후 [RFC8628]에 정의된 Device Authorization Grant를 사용하여 접근 토큰을 요청하려면, 클라이언트는 다음 HTTPS 요청을 수행한다 (표시 목적의 추가 줄바꿈 포함):

  POST /token HTTP/1.1
  Host: server.example.com
  Content-Type: application/x-www-form-urlencoded

  grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code
  &device_code=GmRhmhcxhwEzkoEqiMEg_DnyEysNkuNhszIySk9eS
  &client_id=C409020731

접근 토큰 요청이 유효하고 권한 부여된 경우, 권한 부여 서버는 Section 3.2.3에 설명된 대로 접근 토큰과 선택적 갱신 토큰을 발급한다. 요청이 클라이언트 인증에 실패했거나 유효하지 않은 경우, 권한 부여 서버는 Section 3.2.4에 설명된 대로 오류 응답을 반환한다.

5. 리소스 요청

클라이언트는 접근 토큰을 리소스 서버에 제시하여 보호된 리소스에 접근한다. 리소스 서버는 접근 토큰을 검증하고, 만료되지 않았으며 그 범위가 요청된 리소스를 포함하는지 확인해야 한다. 리소스 서버가 접근 토큰을 검증하는 데 사용하는 방법은 이 명세의 범위를 벗어나지만, 일반적으로 리소스 서버와 권한 부여 서버 사이의 상호작용 또는 조율을 포함한다. 예를 들어, 리소스 서버와 권한 부여 서버가 같은 위치에 있거나 동일한 시스템의 일부인 경우 데이터베이스나 기타 저장소를 공유할 수 있고, 두 구성 요소가 독립적으로 운영되는 경우 Token Introspection [RFC7662] 또는 JWT [RFC9068] 같은 구조화된 접근 토큰 형식을 사용할 수 있다.

5.1. Bearer 토큰 요청

이 절은 리소스 서버에 대한 리소스 요청에서 Bearer 토큰을 전송하는 두 가지 방법을 정의한다. 클라이언트는 아래에 정의된 두 방법 중 하나를 사용해야 하며, 각 요청에서 토큰을 전송하기 위해 둘 이상의 방법을 사용해서는 안 된다.

특히, 클라이언트는 URI 쿼리 매개변수에 접근 토큰을 보내서는 안 되며, 리소스 서버는 URI 쿼리 매개변수의 접근 토큰을 무시해야 한다.

5.1.1. Authorization 요청 헤더 필드

HTTP/1.1 [RFC7235]에 정의된 Authorization 요청 헤더 필드에 접근 토큰을 보낼 때, 클라이언트는 Bearer 스킴을 사용하여 접근 토큰을 전송한다.

예:

 GET /resource HTTP/1.1
 Host: server.example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

이 스킴의 Authorization 헤더 필드 구문은 [RFC2617]의 Section 2에 정의된 Basic 스킴의 사용법을 따른다. Basic과 마찬가지로 [RFC2617]의 Section 1.2에 정의된 일반 구문을 따르지는 않지만, HTTP 1.1 Authentication [RFC7235]의 일반 인증 프레임워크와 호환된다. 다만 기존 배포를 반영하기 위해 그 안에 제시된 선호 관행을 따르지는 않는다. Bearer 자격 증명의 구문은 다음과 같다:

token68    = 1*( ALPHA / DIGIT /
                 "-" / "." / "_" / "~" / "+" / "/" ) *"="
credentials = "bearer" 1*SP token68

클라이언트는 Authorization 요청 헤더 필드와 Bearer HTTP 권한 부여 스킴을 사용하여 bearer 토큰으로 인증된 요청을 해야 한다. 리소스 서버는 이 방법을 지원해야 한다.

[RFC9110]의 Section 11.1에 설명된 대로, 문자열 bearer는 대소문자를 구분하지 않는다. 이는 다음 모두가 Authorization 헤더의 유효한 사용임을 의미한다:

  • Authorization: Bearer mF_9.B5f-4.1JqM

  • Authorization: bearer mF_9.B5f-4.1JqM

  • Authorization: BEARER mF_9.B5f-4.1JqM

  • Authorization: bEaReR mF_9.B5f-4.1JqM

5.1.2. 폼 인코딩 콘텐츠 매개변수

HTTP 요청 콘텐츠에 접근 토큰을 보낼 때, 클라이언트는 access_token 매개변수를 사용하여 요청 콘텐츠에 접근 토큰을 추가한다. 클라이언트는 다음 조건이 모두 충족되지 않는 한 이 방법을 사용해서는 안 된다:

  • HTTP 요청에 Content-Type 헤더 필드가 포함되어 있고 application/x-www-form-urlencoded로 설정되어 있다.

  • 콘텐츠는 URL Living Standard [WHATWG.URL]에 정의된 application/x-www-form-urlencoded content-type의 인코딩 요구사항을 따른다.

  • HTTP 요청 콘텐츠는 단일 파트이다.

  • 요청에 인코딩될 콘텐츠는 전적으로 ASCII [USASCII] 문자로 구성되어야 한다.

  • HTTP 요청 메서드는 콘텐츠에 대해 정의된 의미를 가진 것이어야 한다. 특히 이는 GET 메서드를 사용해서는 안 됨을 의미한다.

콘텐츠에는 다른 요청별 매개변수가 포함될 수 있으며, 이 경우 access_token 매개변수는 & 문자(ASCII 코드 38)를 사용하여 요청별 매개변수와 적절히 구분되어야 한다.

예를 들어, 클라이언트는 전송 계층 보안을 사용하여 다음 HTTP 요청을 수행한다:

POST /resource HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

access_token=mF_9.B5f-4.1JqM

application/x-www-form-urlencoded 방법은 참여 클라이언트가 Authorization 요청 헤더 필드에 접근할 수 없는 애플리케이션 맥락을 제외하고는 사용하지 않는 것이 좋다. 리소스 서버는 이 방법을 지원할 수 있다.

5.2. 접근 토큰 검증

접근 토큰을 받은 후, 리소스 서버는 접근 토큰이 아직 만료되지 않았는지, 요청된 리소스에 접근할 권한이 있는지, 적절한 범위로 발급되었는지, 그리고 보호된 리소스에 접근하기 위한 리소스 서버의 기타 정책 요구사항을 충족하는지 확인해야 한다.

접근 토큰은 일반적으로 두 범주, 즉 참조 토큰 또는 자체 인코딩 토큰에 속한다. 참조 토큰은 권한 부여 서버에 질의하거나 토큰 데이터베이스에서 토큰을 조회하여 검증할 수 있는 반면, 자체 인코딩 토큰은 리소스 서버가 추출할 수 있는 암호화 및/또는 서명된 문자열에 권한 부여 정보를 포함한다.

접근 토큰의 유효성을 확인하기 위해 권한 부여 서버에 질의하는 표준화된 방법은 Token Introspection [RFC7662]에 정의되어 있다.

토큰 문자열에 정보를 인코딩하는 표준화된 방법은 JWT Profile for Access Tokens [RFC9068]에 정의되어 있다.

접근 토큰 생성 및 검증과 관련된 추가 고려사항은 Section 7.1을 참조한다.

5.3. 오류 응답

리소스 접근 요청이 실패하면, 리소스 서버는 클라이언트에 오류를 알려야 한다. 오류 응답의 세부 사항은 Section 5.3.2의 Bearer 토큰 설명처럼 특정 토큰 유형에 의해 결정된다.

5.3.1. WWW-Authenticate 응답 헤더 필드

보호된 리소스 요청에 인증 자격 증명이 포함되어 있지 않거나, 보호된 리소스에 대한 접근을 가능하게 하는 접근 토큰이 포함되어 있지 않은 경우, 리소스 서버는 HTTP WWW-Authenticate 응답 헤더 필드를 포함해야 한다. 다른 조건에 대한 응답에도 이를 포함할 수 있다. WWW-Authenticate 헤더 필드는 HTTP/1.1 [RFC7235]에 정의된 프레임워크를 사용한다.

이 토큰 유형에 대한 모든 챌린지는 auth-scheme 값 Bearer를 사용해야 한다. 이 스킴 뒤에는 하나 이상의 auth-param 값이 따라야 한다. 이 토큰 유형에 대해 이 명세가 사용하거나 정의하는 auth-param 속성은 다음과 같다. 다른 auth-param 속성도 사용할 수 있다.

"realm":

realm 속성은 HTTP/1.1 [RFC7235]에 설명된 방식으로 보호 범위를 나타내기 위해 포함될 수 있다. realm 속성은 두 번 이상 나타나서는 안 된다.

"scope":

scope 속성은 Section 1.4.1에 정의되어 있다. scope 속성은 요청된 리소스에 접근하기 위해 접근 토큰에 필요한 범위를 나타내는, 공백으로 구분된 대소문자 구분 범위 값 목록이다. scope 값은 구현에서 정의하며, 중앙 집중식 레지스트리는 없고, 허용되는 값은 권한 부여 서버가 정의한다. scope 값의 순서는 중요하지 않다. 일부 경우에는 보호된 리소스를 사용할 충분한 접근 범위를 가진 새 접근 토큰을 요청할 때 scope 값이 사용된다. scope 속성의 사용은 OPTIONAL이다. scope 속성은 두 번 이상 나타나서는 안 된다. scope 값은 프로그래밍 방식 사용을 위한 것이며 최종 사용자에게 표시하기 위한 것이 아니다.

두 가지 예시 scope 값은 다음과 같다. 이들은 각각 OpenID Connect [OpenID.Messages] 및 Open Authentication Technology Committee (OATC) Online Multimedia Authorization Protocol [OMAP] OAuth 2.0 사용 사례에서 가져온 것이다:

scope="openid profile email"
scope="urn:example:channel=HBO&urn:example:rating=G,PG-13"
"error":

보호된 리소스 요청에 접근 토큰이 포함되어 있었고 인증에 실패한 경우, 리소스 서버는 접근 요청이 거절된 이유를 클라이언트에 제공하기 위해 error 속성을 포함해야 한다. 매개변수 값은 Section 5.3.2에 설명되어 있다.

"error_description":

리소스 서버는 최종 사용자에게 표시하기 위한 것이 아닌, 개발자를 위한 사람이 읽을 수 있는 설명을 제공하기 위해 error_description 속성을 포함할 수 있다.

"error_uri":

리소스 서버는 오류를 설명하는 사람이 읽을 수 있는 웹 페이지를 식별하는 절대 URI와 함께 error_uri 속성을 포함할 수 있다.

error, error_description, 및 error_uri 속성은 두 번 이상 나타나서는 안 된다.

Appendix A.4에 지정된 scope 속성의 값은 범위 값을 나타내기 위한 집합 %x21 / %x23-5B / %x5D-7E 및 범위 값 사이의 구분자로 쓰이는 %x20 밖의 문자를 포함해서는 안 된다. Appendix A.7Appendix A.8에 지정된 errorerror_description 속성의 값은 집합 %x20-21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다. Appendix A.9에 지정된 error_uri 속성의 값은 URI-reference 구문을 따라야 하므로 집합 %x21 / %x23-5B / %x5D-7E 밖의 문자를 포함해서는 안 된다.

5.3.2. 오류 코드

요청이 실패하면, 리소스 서버는 적절한 HTTP 상태 코드 (일반적으로 400, 401, 403 또는 405)를 사용하여 응답하고 응답에 다음 오류 코드 중 하나를 포함한다:

"invalid_request":

요청에 필수 매개변수가 없거나, 지원되지 않는 매개변수 또는 매개변수 값이 포함되어 있거나, 동일한 매개변수가 반복되거나, 접근 토큰을 포함하기 위해 둘 이상의 방법을 사용하거나, 그 밖에 형식이 잘못된 경우. 리소스 서버는 HTTP 400 (Bad Request) 상태 코드로 응답해야 한다.

"invalid_token":

제공된 접근 토큰이 만료되었거나, 취소되었거나, 형식이 잘못되었거나, 기타 이유로 유효하지 않은 경우. 리소스 서버는 HTTP 401 (Unauthorized) 상태 코드로 응답해야 한다. 클라이언트는 새 접근 토큰을 요청하고 보호된 리소스 요청을 다시 시도할 수 있다.

"insufficient_scope":

요청이 클라이언트에 부여되고 접근 토큰으로 표현된 범위가 제공하는 것보다 더 높은 권한(범위)을 요구하는 경우. 리소스 서버는 HTTP 403 (Forbidden) 상태 코드로 응답해야 하며, 보호된 리소스에 접근하는 데 필요한 범위와 함께 scope 속성을 포함할 수 있다.

확장은 추가 오류 코드를 정의하거나 위 오류 코드가 반환되는 추가 상황을 지정할 수 있다.

요청에 인증 정보가 없는 경우 (예: 클라이언트가 인증이 필요하다는 것을 몰랐거나 지원되지 않는 인증 방법을 사용하여 시도한 경우), 리소스 서버는 오류 코드나 기타 오류 정보를 포함하지 않는 것이 좋다.

예:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example"

그리고 만료된 접근 토큰을 사용한 인증 시도가 있는 보호된 리소스 요청에 대한 응답:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
                  error="invalid_token",
                  error_description="The access token expired"

6. 확장성

6.1. 접근 토큰 유형 정의

접근 토큰 유형은 두 가지 방법 중 하나로 정의할 수 있다: Access Token Types 레지스트리에 등록하거나 ([RFC6749]의 Section 11.1 절차에 따름), 고유한 절대 URI를 이름으로 사용하는 것이다.

6.1.1. 등록된 접근 토큰 유형

[RFC6750]은 OAuth 토큰 인증 스킴 간에 공유할 오류 값을 위한 공통 레지스트리를 [RFC6749]의 Section 11.4에서 확립한다.

주로 OAuth 토큰 인증을 위해 설계된 새 인증 스킴은 클라이언트에 오류 상태 코드를 제공하는 메커니즘을 정의해야 하며, 허용되는 오류 값은 이 명세가 확립한 오류 레지스트리에 등록된다.

그러한 스킴은 유효한 오류 코드 집합을 등록된 값의 하위 집합으로 제한할 수 있다. 오류 코드가 명명된 매개변수를 사용하여 반환되는 경우, 매개변수 이름은 error여야 한다.

OAuth 토큰 인증에 사용될 수 있지만 주로 그 목적을 위해 설계되지는 않은 다른 스킴도 같은 방식으로 오류 값을 레지스트리에 바인딩할 수 있다.

새 인증 스킴은 이 명세에서의 사용과 병렬적인 방식으로 오류 정보를 반환하기 위해 error_descriptionerror_uri 매개변수의 사용도 지정하도록 선택할 수 있다.

유형 이름은 type-name ABNF를 따라야 한다. 유형 정의가 새 HTTP 인증 스킴을 포함하는 경우, 유형 이름은 HTTP 인증 스킴 이름 ([RFC2617]에 정의된 대로)과 동일해야 한다. 토큰 유형 example은 예제 사용을 위해 예약된다.

type-name  = 1*name-char
name-char  = "-" / "." / "_" / DIGIT / ALPHA

6.1.2. 벤더별 접근 토큰 유형

URI 이름을 사용하는 유형은 일반적으로 적용되지 않고 사용되는 리소스 서버의 구현 세부 사항에 특정한 벤더별 구현으로 제한되어야 한다.

그 밖의 모든 유형은 등록되어야 한다.

6.2. 새 엔드포인트 매개변수 정의

권한 부여 엔드포인트 또는 토큰 엔드포인트와 함께 사용할 새 요청 또는 응답 매개변수는 [RFC6749]의 Section 11.2 절차에 따라 OAuth Parameters 레지스트리에 정의되고 등록된다.

매개변수 이름은 param-name ABNF를 따라야 하며, 매개변수 값 구문은 잘 정의되어야 한다(예: ABNF 사용 또는 기존 매개변수 구문에 대한 참조).

param-name  = 1*name-char
name-char   = "-" / "." / "_" / DIGIT / ALPHA

일반적으로 적용되지 않고 사용되는 권한 부여 서버의 구현 세부 사항에 특정한 등록되지 않은 벤더별 매개변수 확장은 다른 등록 값과 충돌할 가능성이 낮은 벤더별 접두사 (예: 'companyname_'으로 시작)를 사용해야 한다.

6.3. 새 권한 부여 그랜트 유형 정의

새 권한 부여 그랜트 유형은 grant_type 매개변수와 함께 사용할 고유한 절대 URI를 할당하여 정의할 수 있다. 확장 그랜트 유형이 추가 토큰 엔드포인트 매개변수를 요구하는 경우, 해당 매개변수는 [RFC6749]의 Section 11.2에 설명된 대로 OAuth Parameters 레지스트리에 등록되어야 한다.

6.4. 새 권한 부여 엔드포인트 응답 유형 정의

권한 부여 엔드포인트와 함께 사용할 새 응답 유형은 [RFC6749]의 Section 11.3 절차에 따라 Authorization Endpoint Response Types 레지스트리에 정의되고 등록된다. 응답 유형 이름은 response-type ABNF를 따라야 한다.

response-type  = response-name *( SP response-name )
response-name  = 1*response-char
response-char  = "_" / DIGIT / ALPHA

응답 유형이 하나 이상의 공백 문자(%x20)를 포함하는 경우, 이는 값의 순서가 중요하지 않은 공백 구분 값 목록으로 비교된다. 값의 한 가지 순서만 등록할 수 있으며, 이는 같은 값 집합의 다른 모든 배열을 포함한다.

예를 들어, 확장은 code other_token 응답 유형을 정의하고 등록할 수 있다. 일단 등록되면, 같은 조합을 other_token code로 등록할 수는 없지만, 두 값 모두 동일한 응답 유형을 나타내는 데 사용할 수 있다.

6.5. 추가 오류 코드 정의

프로토콜 확장(즉, 접근 토큰 유형, 확장 매개변수 또는 확장 그랜트 유형)이 권한 부여 코드 그랜트 오류 응답(Section 4.1.2.1), 토큰 오류 응답(Section 3.2.4) 또는 리소스 접근 오류 응답(Section 5.3)과 함께 사용할 추가 오류 코드를 요구하는 경우, 그러한 오류 코드를 정의할 수 있다.

확장 오류 코드는 함께 사용되는 확장이 등록된 접근 토큰 유형, 등록된 엔드포인트 매개변수 또는 확장 그랜트 유형인 경우 등록되어야 한다 ([RFC6749]의 Section 11.4 절차에 따름). 등록되지 않은 확장과 함께 사용되는 오류 코드는 등록될 수 있다.

오류 코드는 error ABNF를 따라야 하며 가능한 경우 식별 이름을 접두사로 붙여야 한다. 예를 들어 확장 매개변수 example에 설정된 유효하지 않은 값을 식별하는 오류는 example_invalid라고 이름 붙여야 한다.

error      = 1*error-char
error-char = %x20-21 / %x23-5B / %x5D-7E

7. 보안 고려사항

유연하고 확장 가능한 프레임워크로서 OAuth의 보안 고려사항은 여러 요인에 의존한다. 다음 절은 Section 2.1에 설명된 세 가지 클라이언트 프로파일, 즉 웹 애플리케이션, 브라우저 기반 애플리케이션, 네이티브 애플리케이션에 초점을 맞춘 보안 지침을 구현자에게 제공한다.

포괄적인 OAuth 보안 모델 및 분석과 프로토콜 설계 배경은 [RFC6819][RFC9700]에서 제공된다.

7.1. 접근 토큰 보안 고려사항

7.1.1. 보안 위협

다음 목록은 어떤 형태의 토큰을 사용하는 프로토콜에 대한 여러 일반적인 위협을 제시한다. 이 위협 목록은 NIST Special Publication 800-63 [NIST800-63]에 기반한다.

7.1.1.1. 접근 토큰 생성/수정

공격자는 가짜 접근 토큰을 생성하거나 기존 토큰의 콘텐츠(예: 인증 또는 속성 진술)를 수정하여, 리소스 서버가 클라이언트에 부적절한 접근을 부여하게 할 수 있다. 예를 들어 공격자는 유효 기간을 연장하도록 토큰을 수정할 수 있고, 악의적인 클라이언트는 자신이 볼 수 없어야 하는 정보에 접근하기 위해 어설션을 수정할 수 있다.

7.1.1.2. 접근 토큰 정보 공개

접근 토큰은 민감한 정보를 포함하는 인증 및 속성 진술을 포함할 수 있다.

클라이언트가 접근 토큰의 콘텐츠를 관찰하지 못하도록 해야 한다면, 콘텐츠 암호화를 적용해야 한다.

쿠키는 기본적으로 평문으로 전송되므로, 그 안에 포함된 모든 정보는 공개 위험이 있다: Bearer 토큰은 평문으로 전송될 수 있는 쿠키에 저장해서는 안 된다. 쿠키에 대한 보안 고려사항은 [RFC6265]의 Section 7 및 8을 참조한다.

7.1.1.3. 접근 토큰 리디렉션

공격자는 한 리소스 서버에서 사용하도록 생성된 접근 토큰을 사용하여, 그 토큰이 자신을 위한 것이라고 잘못 믿는 다른 리소스 서버에 접근한다.

7.1.1.4. 접근 토큰 재전송

공격자는 과거에 해당 리소스 서버에서 이미 사용된 접근 토큰을 사용하려고 시도한다.

7.1.2. 위협 완화

접근 토큰의 콘텐츠를 디지털 서명을 사용하여 보호하고, 정기적 키 순환 같은 서명 키 관리 모범 관행을 따르면 광범위한 위협을 완화할 수 있다.

또는 bearer 토큰은 권한 부여 정보를 직접 인코딩하는 대신 권한 부여 정보에 대한 참조를 포함할 수 있다. 참조를 사용하려면 참조를 권한 부여 정보로 해석하기 위해 리소스 서버와 권한 부여 서버 사이의 추가 상호작용이 필요할 수 있다. 그러한 상호작용의 메커니즘은 이 명세에서 정의하지 않지만, 그러한 메커니즘 중 하나는 Token Introspection [RFC7662]에 정의되어 있다.

이 문서는 접근 토큰의 인코딩이나 콘텐츠를 지정하지 않는다. 따라서 접근 토큰 무결성 보호를 보장하는 수단에 대한 상세 권장사항은 이 명세의 범위를 벗어난다. 접근 토큰의 인코딩 및 서명 메커니즘의 한 예는 JSON Web Token Profile for Access Tokens [RFC9068]에 설명되어 있다.

접근 토큰 리디렉션을 다루기 위해서는, 권한 부여 서버가 토큰에 의도된 수신자(대상)의 신원을, 일반적으로 단일 리소스 서버(또는 리소스 서버 목록)를 포함하는 것이 중요하다. 토큰의 사용을 특정 범위로 제한하는 것도 권장된다.

Section 1.5는 접근 토큰 공개로부터 보호하고 클라이언트, 리소스 서버 및 권한 부여 서버 간의 통신에 기밀성과 무결성을 제공하기 위한 정보를 제공한다.

7.1.3. 권장사항 요약

7.1.3.1. bearer 토큰 보호

클라이언트 구현은 bearer 토큰이 의도하지 않은 당사자에게 유출되지 않도록 보장해야 한다. 유출된 당사자는 이를 사용하여 보호된 리소스에 접근할 수 있기 때문이다. 이는 bearer 토큰을 사용할 때의 주요 보안 고려사항이며, 뒤따르는 더 구체적인 권장사항 모두의 기반이 된다.

7.1.3.2. TLS 인증서 체인 검증

클라이언트는 보호된 리소스에 요청할 때 TLS 인증서 체인을 검증해야 한다. 이를 수행하지 않으면 DNS 하이재킹 공격이 토큰을 훔치고 의도하지 않은 접근을 얻을 수 있다.

7.1.3.3. 항상 TLS (https) 사용

클라이언트는 bearer 토큰으로 요청할 때 항상 TLS (https) 또는 동등한 전송 보안을 사용해야 한다. 이를 수행하지 않으면 토큰이 공격자에게 의도하지 않은 접근을 제공할 수 있는 수많은 공격에 노출된다.

7.1.3.4. HTTP 쿠키에 bearer 토큰을 저장하지 말 것

구현은 평문으로 전송될 수 있는 쿠키(쿠키의 기본 전송 방식)에 bearer 토큰을 저장해서는 안 된다. bearer 토큰을 쿠키에 저장하는 구현은 cross-site request forgery에 대한 예방 조치를 취해야 한다.

7.1.3.5. 수명이 짧은 bearer 토큰 발급

권한 부여 서버는 특히 웹 브라우저나 정보 유출이 발생할 수 있는 다른 환경에서 실행되는 클라이언트에 토큰을 발급할 때, 수명이 짧은 bearer 토큰을 발급해야 한다. 수명이 짧은 bearer 토큰을 사용하면 유출되었을 때의 영향을 줄일 수 있다.

7.1.3.6. 범위가 지정된 bearer 토큰 발급

권한 부여 서버는 대상 제한을 포함하여 사용 범위를 의도된 리소스 서버 또는 리소스 서버 집합으로 제한하는 bearer 토큰을 발급해야 한다.

7.1.3.7. 페이지 URL에 bearer 토큰을 전달하지 말 것

Bearer 토큰은 페이지 URL(예: 쿼리 문자열 매개변수)로 전달되어서는 안 된다. 대신 bearer 토큰은 기밀성 조치가 취해진 HTTP 메시지 헤더 또는 메시지 본문으로 전달되어야 한다. 브라우저, 웹 서버 및 기타 소프트웨어는 브라우저 기록, 웹 서버 로그 및 기타 데이터 구조에서 URL을 충분히 보호하지 못할 수 있다. bearer 토큰이 페이지 URL로 전달되면, 공격자가 기록 데이터, 로그 또는 기타 보호되지 않은 위치에서 이를 훔칠 수 있다.

7.1.4. 접근 토큰 권한 제한

접근 토큰과 연결된 권한은 특정 애플리케이션 또는 사용 사례에 필요한 최소한으로 제한되어야 한다. 이는 클라이언트가 리소스 소유자가 권한 부여한 권한을 초과하는 것을 방지한다. 또한 사용자가 각 보안 정책에서 권한 부여한 권한을 초과하는 것도 방지한다. 권한 제한은 접근 토큰 유출의 영향을 줄이는 데도 도움이 된다.

특히 접근 토큰은 특정 리소스 서버 (대상 제한), 가능하면 단일 리소스 서버로 제한되어야 한다. 이를 실행하기 위해 권한 부여 서버는 접근 토큰을 특정 리소스 서버와 연결하고, 모든 리소스 서버는 각 요청에 대해 해당 요청과 함께 전송된 접근 토큰이 그 특정 리소스 서버에 사용되도록 의도된 것인지 검증할 의무가 있다. 그렇지 않은 경우, 리소스 서버는 해당 요청을 처리하기를 거부해야 한다. 클라이언트와 권한 부여 서버는 접근하려는 리소스 서버를 결정하기 위해 이 문서 및 [RFC8707]에 각각 지정된 scope 또는 resource 매개변수를 사용할 수 있다.

또한 접근 토큰은 리소스 서버의 특정 리소스 및 동작 또는 리소스로 제한되어야 한다. 이를 실행하기 위해 권한 부여 서버는 접근 토큰을 해당 리소스 및 동작과 연결하고, 모든 리소스 서버는 각 요청에 대해 그 요청과 함께 전송된 접근 토큰이 특정 리소스에 대한 특정 동작에 사용되도록 의도된 것인지 검증할 의무가 있다. 그렇지 않은 경우, 리소스 서버는 해당 요청을 처리하기를 거부해야 한다. 클라이언트와 권한 부여 서버는 그러한 리소스 및/또는 동작을 결정하기 위해 [RFC9396]에 지정된 scopeauthorization_details 매개변수를 사용할 수 있다.

7.2. 클라이언트 인증

클라이언트 등록 및 자격 증명 수명 주기 관리의 전체 과정에 따라, 이는 권한 부여 서버가 특정 클라이언트에 대해 가지는 신뢰도에 영향을 줄 수 있다.

예를 들어, 동적으로 등록된 클라이언트의 인증은 클라이언트의 신원을 증명하지 않으며, 권한 부여 서버에 대한 반복 요청이 동일한 클라이언트 인스턴스에서 이루어졌음을 보장할 뿐이다. 그러한 클라이언트는 요청할 수 있는 범위 측면에서 제한될 수 있고, 더 짧은 토큰 수명 같은 다른 제한을 가질 수도 있다.

반대로, 개발자의 신원이 검증되고 계약에 서명했으며 안전한 백엔드 서비스에서만 사용되는 클라이언트 시크릿이 발급된 등록된 애플리케이션이 있는 경우, 권한 부여 서버는 이 클라이언트가 더 민감한 범위를 요청하거나 더 오래 지속되는 토큰을 발급받도록 허용할 수 있다.

7.3. 클라이언트 가장

기밀 클라이언트의 자격 증명이 도난당한 경우, 악의적인 클라이언트는 해당 클라이언트를 가장하고 보호된 리소스에 대한 접근을 얻을 수 있다.

권한 부여 서버는 명시적인 리소스 소유자 인증을 강제하고, 리소스 소유자에게 클라이언트와 요청된 권한 부여 범위 및 수명에 대한 정보를 제공해야 한다. 현재 클라이언트의 맥락에서 정보를 검토하고 요청을 허용하거나 거부하는 것은 리소스 소유자의 몫이다.

권한 부여 서버는 클라이언트를 인증하거나 반복 요청이 원래 클라이언트에서 온 것이며 가장자가 아님을 보장하기 위한 다른 조치에 의존하지 않고, 반복된 권한 부여 요청을 (능동적인 리소스 소유자 상호작용 없이) 자동으로 처리해서는 안 된다.

7.3.1. 네이티브 앱 가장

위에서 언급한 대로, 권한 부여 서버는 클라이언트의 신원을 보장할 수 있는 경우를 제외하고 사용자 동의나 상호작용 없이 권한 부여 요청을 자동으로 처리해서는 안 된다. 여기에는 사용자가 이전에 주어진 클라이언트 ID에 대해 권한 부여 요청을 승인한 경우도 포함된다. 클라이언트의 신원을 증명할 수 없는 한, 해당 요청은 이전에 승인된 요청이 없었던 것처럼 처리되어야 한다.

claimed https 스킴 리디렉션 같은 조치는 권한 부여 서버가 신원 증명으로 수락할 수 있다. 일부 운영 체제는 적절한 경우 수락될 수 있는 대체 플랫폼별 신원 기능을 제공할 수 있다.

7.3.2. 접근 토큰 권한 제한

클라이언트는 필요한 최소 범위로 접근 토큰을 요청해야 한다. 권한 부여 서버는 요청된 범위를 어떻게 승인할지 선택할 때 클라이언트 신원을 고려해야 하며, 요청된 것보다 적은 범위의 접근 토큰을 발급할 수 있다.

접근 토큰과 연결된 권한은 특정 애플리케이션 또는 사용 사례에 필요한 최소한으로 제한되어야 한다. 이는 클라이언트가 리소스 소유자가 권한 부여한 권한을 초과하는 것을 방지한다. 또한 사용자가 각 보안 정책에서 권한 부여한 권한을 초과하는 것도 방지한다. 권한 제한은 접근 토큰 유출의 영향을 줄이는 데도 도움이 된다.

특히 접근 토큰은 특정 리소스 서버(대상 제한), 가능하면 단일 리소스 서버로 제한되어야 한다. 이를 실행하기 위해 권한 부여 서버는 접근 토큰을 특정 리소스 서버와 연결하고, 모든 리소스 서버는 각 요청에 대해 해당 요청과 함께 전송된 접근 토큰이 그 특정 리소스 서버에 사용되도록 의도된 것인지 검증할 의무가 있다. 그렇지 않은 경우 리소스 서버는 해당 요청을 처리하기를 거부해야 한다. 클라이언트와 권한 부여 서버는 접근하려는 리소스 서버를 결정하기 위해 [RFC8707]에 각각 지정된 scope 또는 resource 매개변수를 사용할 수 있다.

7.4. 리소스 소유자를 가장하는 클라이언트

리소스 서버는 접근 토큰이 발급된 리소스 소유자의 신원이나, 클라이언트 자격 증명 그랜트에서 클라이언트의 신원을 기반으로 접근 제어 결정을 내릴 수 있다. 두 옵션이 모두 가능한 경우, 구현 세부 사항에 따라 클라이언트의 신원이 리소스 소유자의 신원으로 오인될 수 있다. 예를 들어, 클라이언트가 권한 부여 서버에 등록하는 동안 자신의 client_id를 선택할 수 있다면, 악의적인 클라이언트는 이를 최종 사용자를 식별하는 값 (예: OpenID Connect가 사용되는 경우 sub 값)으로 설정할 수 있다. 리소스 서버가 클라이언트에 발급된 접근 토큰과 최종 사용자에게 발급된 접근 토큰을 적절히 구분할 수 없다면, 클라이언트는 이후 최종 사용자의 리소스에 접근할 수 있게 된다.

권한 부여 서버가 클라이언트 ID와 사용자 식별자에 대해 공통 네임스페이스를 가지고 있어, 리소스 서버가 리소스 소유자가 권한 부여한 접근 토큰과 클라이언트 자체가 권한 부여한 접근 토큰을 구분할 수 없게 되는 경우, 권한 부여 서버는 진짜 리소스 소유자와 혼동을 일으킬 수 있다면 클라이언트가 자신의 client_id 또는 다른 Claim에 영향을 주도록 허용해서는 안 된다. 이를 피할 수 없는 경우, 권한 부여 서버는 리소스 서버가 두 종류의 접근 토큰을 구분할 수 있는 다른 수단을 제공해야 한다.

7.5. 권한 부여 코드 보안 고려사항

7.5.1. 권한 부여 코드 주입

권한 부여 코드 주입은 클라이언트가 합법적인 권한 부여 서버의 권한 부여 코드 대신 공격자로부터 온 권한 부여 코드를 리디렉션 URI에서 받는 공격이다. 보호 조치가 없으면, 클라이언트가 공격이 발생했음을 알 수 있는 메커니즘이 없다. 권한 부여 코드 주입은 공격자가 피해자의 계정에 접근하게 만들 수 있을 뿐 아니라, 피해자가 실수로 공격자의 계정에 접근하게 만들 수도 있다.

7.5.1.1. 대응책

클라이언트에 권한 부여 코드가 주입되는 것을 방지하기 위해, 클라이언트에는 code_challengecode_verifier 사용이 REQUIRED이며, 권한 부여 서버는 다음 두 기준이 모두 충족되지 않는 한 그 사용을 강제해야 한다:

  • 클라이언트가 기밀 클라이언트이다.

  • 특정 배포 및 특정 요청에서, 권한 부여 서버가 클라이언트가 OpenID Connect nonce 메커니즘을 적절히 구현한다는 합리적 보장을 가지고 있다.

이 경우에도 code_challengecode_verifier를 사용하고 강제하는 것이 여전히 권장된다.

code_challenge 또는 OpenID Connect nonce 값은 트랜잭션별이어야 하며, 트랜잭션이 시작된 클라이언트와 사용자 에이전트에 안전하게 바인딩되어야 한다. 트랜잭션이 오류로 이어지는 경우, code_challenge 또는 nonce에 대해 새로운 값을 선택해야 한다.

OpenID Connect nonce 매개변수를 검증하는 것을 클라이언트에 의존한다는 것은 권한 부여 서버가 클라이언트가 실제로 권한 부여 코드 주입 공격으로부터 자신을 보호했는지 확인할 방법이 없음을 의미한다. 공격자가 클라이언트에 권한 부여 코드를 주입할 수 있다면, 클라이언트는 여전히 주입된 권한 부여 코드를 교환하고 토큰을 얻은 다음, 나중에 nonce를 검증하고 일치하지 않음을 확인한 후에야 ID 토큰을 거부할 것이다. 반대로, 권한 부여 서버가 code_challengecode_verifier 매개변수를 강제하면 권한 부여 서버가 권한 부여 코드 주입 공격을 사전에 인식하고 처음부터 어떤 토큰도 발급하지 않을 수 있으므로 더 높은 보안 결과를 제공한다.

역사적 참고: PKCE [RFC7636] (code_challengecode_verifier 매개변수가 만들어진 곳)는 원래 네이티브 앱을 권한 부여 코드 유출 공격으로부터 보호하기 위한 메커니즘으로 설계되었지만, 웹 애플리케이션 및 기타 기밀 클라이언트를 포함한 모든 종류의 OAuth 클라이언트는 권한 부여 코드 주입 공격에 취약하며, 이는 code_challengecode_verifier 메커니즘으로 해결된다.

7.5.2. 권한 부여 코드 재사용

권한 부여 코드를 두 번 이상 사용할 수 있다면 여러 유형의 공격이 가능하다.

Section 4.1.3에 설명된 대로, 권한 부여 서버는 이미 접근 토큰을 발급하는 데 사용된 권한 부여 코드로 두 번째 유효한 요청을 받으면 토큰 요청을 거부하고 발급된 모든 토큰을 취소해야 한다. 공격자가 권한 부여 코드를 유출하여 합법적인 클라이언트보다 먼저 사용할 수 있다면, 공격자는 접근 토큰을 얻고 합법적인 클라이언트는 얻지 못한다. 발급된 모든 토큰을 취소하면 공격자의 토큰도 취소되어 공격이 더 진행되는 것을 막는다.

그러나 권한 부여 서버는 권한 부여 코드가 포함된 요청도 code_verifier 및 클라이언트 인증 같은 다른 매개변수를 포함하여 유효한 경우에만 발급된 토큰을 취소해야 한다. 권한 부여 서버는 유효하지 않은 매개변수를 포함하는 재전송된 권한 부여 코드를 받을 때 발급된 토큰을 취소해서는 안 된다. 그렇게 하면 권한 부여 코드를 얻을 수는 있지만 클라이언트 인증 또는 code_verifier를 얻을 수 없는 공격자가 합법적인 클라이언트보다 먼저 유효하지 않은 권한 부여 코드 요청을 보내 합법적인 클라이언트가 유효한 요청을 할 때 그 토큰을 취소하게 하는 서비스 거부 기회를 만들 수 있다.

7.5.3. HTTP 307 리디렉션

사용자 자격 증명을 포함할 가능성이 있는 요청을 리디렉션하는 권한 부여 서버는 리디렉션에 307 상태 코드 ([RFC9110]의 Section 15.4.8)를 사용해서는 안 된다. 그러한 요청에 HTTP 리디렉션(예: JavaScript가 아닌)이 사용되는 경우, AS는 상태 코드 303 ("See Other")을 사용해야 한다.

권한 부여 엔드포인트에서 일반적인 프로토콜 흐름은 AS가 사용자에게 양식에 자격 증명을 입력하도록 요청하고, 그 양식이 (POST 메서드를 사용하여) 권한 부여 서버로 다시 제출되는 것이다. AS는 자격 증명을 확인하고, 성공하면 사용자 에이전트를 클라이언트의 리디렉션 URI로 리디렉션한다.

리디렉션에 307 상태 코드가 사용되면, 사용자 에이전트는 POST 요청을 통해 사용자 자격 증명을 클라이언트로 전송한다.

이는 민감한 자격 증명을 클라이언트에 공개한다. 클라이언트가 악의적이라면, 그 자격 증명을 사용하여 AS에서 사용자를 가장할 수 있다.

이 동작은 개발자에게 예상 밖일 수 있지만, [RFC9110]의 Section 15.4.8에 정의되어 있다. 이 상태 코드는 사용자 에이전트가 POST 요청을 GET 요청으로 다시 작성하고 POST 요청 콘텐츠의 양식 데이터를 삭제하도록 요구하지 않는다.

HTTP [RFC9110]에서, 상태 코드 303만이 HTTP POST 요청을 HTTP GET 요청으로 다시 작성하도록 명확하게 강제한다. 인기 있는 302를 포함한 다른 모든 상태 코드의 경우, 사용자 에이전트는 POST를 GET 요청으로 다시 작성하지 않도록 선택할 수 있으며, 따라서 사용자 자격 증명을 클라이언트에 노출할 수 있다. (그러나 실제로는 대부분의 사용자 에이전트가 307 리디렉션에서만 이 동작을 보인다.)

7.6. 엔드포인트 진위성 보장

중간자 공격과 관련된 위험은 권한 부여 및 토큰 엔드포인트와 통신하기 위해 [RFC8446] 같은 채널 보안 메커니즘의 필수 사용으로 완화된다. 자세한 내용은 Section 1.5를 참조한다.

7.7. 자격 증명 추측 공격

권한 부여 서버는 공격자가 접근 토큰, 권한 부여 코드, 갱신 토큰, 리소스 소유자 비밀번호 및 클라이언트 자격 증명을 추측하지 못하도록 방지해야 한다.

공격자가 생성된 토큰(및 최종 사용자가 다루도록 의도되지 않은 기타 자격 증명)을 추측할 확률은 2^(-128) 이하이어야 하며, 2^(-160) 이하가 되어야 한다.

권한 부여 서버는 최종 사용자 사용을 위한 자격 증명을 보호하기 위해 다른 수단을 활용해야 한다.

7.8. 피싱 공격

이 프로토콜 및 유사한 프로토콜이 널리 배포되면, 최종 사용자가 비밀번호 입력을 요청받는 웹사이트로 리디렉션되는 관행에 무감각해질 수 있다. 최종 사용자가 자격 증명을 입력하기 전에 이러한 웹사이트의 진위성을 주의 깊게 검증하지 않으면, 공격자가 이 관행을 악용하여 리소스 소유자의 비밀번호와 OTP 같은 기타 피싱 가능한 자격 증명을 훔칠 수 있다.

서비스 제공자는 피싱 공격이 제기하는 위험에 대해 최종 사용자를 교육하려고 시도해야 하며, 피싱 저항 인증자를 사용하는 것처럼 최종 사용자가 사이트의 진위성을 쉽게 확인할 수 있는 메커니즘을 제공해야 한다. 피싱 저항 인증자는 플랫폼이 사이트의 출처를 성공적으로 검증한 경우에만 특정 사이트에 로그인하기 위한 자격 증명을 사용자에게 제공하기 때문이다. 클라이언트 개발자는 사용자 에이전트와 상호작용하는 방식(예: 외부, 내장)의 보안 영향과 최종 사용자가 권한 부여 서버의 진위성을 검증할 수 있는 능력을 고려해야 한다.

피싱 공격 위험 완화에 대한 추가 자세한 내용은 Section 1.5를 참조한다.

7.9. Cross-Site Request Forgery

공격자는 피해자의 장치에서 합법적인 클라이언트의 리디렉션 URI로 요청을 주입하려고 시도할 수 있다. 예를 들어 클라이언트가 공격자가 제어하는 리소스에 접근하도록 만들 수 있다. 이는 Cross-Site Request Forgery (CSRF)로 알려진 공격의 변형이다.

전통적인 대응책은 클라이언트가 요청을 리디렉션 URI와 사용자 에이전트 세션에 연결하는 난수 값, 즉 CSRF Token을 state 매개변수로 전달하는 것이다. 이 대응책은 [RFC6819]의 Section 5.3.5에 자세히 설명되어 있다. 동일한 보호는 code_verifier 매개변수 또는 OpenID Connect nonce 값으로도 제공된다.

CSRF 보호를 위해 state 또는 nonce 대신 code_verifier를 사용할 때에는 다음 사항에 유의하는 것이 중요하다:

  • 클라이언트는 AS가 클라이언트가 사용하려는 code_challenge_method를 지원하는지 보장해야 한다. 권한 부여 서버가 요청된 방법을 지원하지 않는 경우, CSRF 보호를 위해 대신 state 또는 nonce를 사용해야 한다.

  • state가 애플리케이션 상태를 전달하는 데 사용되고, 그 콘텐츠의 무결성이 문제가 되는 경우, 클라이언트는 state를 변조 및 교체로부터 보호해야 한다. 이는 state의 콘텐츠를 브라우저 세션에 바인딩하거나 서명/암호화된 state 값 [I-D.bradley-oauth-jwt-encoded-state]을 사용하여 달성할 수 있다.

따라서 AS는 [RFC8414]에 따른 AS 메타데이터를 통해 또는 지원을 보장하거나 결정하기 위한 배포별 방법을 제공하여, 지원되는 코드 챌린지 방법을 탐지할 수 있는 방법을 제공해야 한다.

7.10. 클릭재킹

[RFC6819]의 Section 4.4.1.9에 설명된 대로, 권한 부여 요청은 사용자 인터페이스 위장이라고도 불리는 클릭재킹 공격에 취약하다. 그러한 공격에서 공격자는 권한 부여 엔드포인트 사용자 인터페이스를 무해해 보이는 맥락에 내장한다. 사용자가 그 맥락과 상호작용한다고 믿고, 예를 들어 버튼을 클릭하면, 의도치 않게 권한 부여 엔드포인트 사용자 인터페이스와 상호작용하게 된다. 반대도 가능하다. 사용자가 권한 부여 엔드포인트와 상호작용한다고 믿고 원래 사용자 인터페이스 위에 겹쳐진 공격자 제공 입력 필드에 비밀번호를 입력할 수 있다. 클릭재킹 공격은 사용자가 공격을 거의 알아차리지 못하도록 설계될 수 있으며, 예를 들어 다른 요소 위에 거의 보이지 않는 iframe을 겹쳐 놓을 수 있다.

공격자는 이 벡터를 사용하여 사용자의 인증 자격 증명을 얻고, 클라이언트에 부여된 접근 범위를 변경하며, 잠재적으로 사용자의 리소스에 접근할 수 있다.

권한 부여 서버는 클릭재킹 공격을 방지해야 한다. [RFC6819]에는 X-Frame-Options HTTP 응답 헤더 필드 및 frame-busting JavaScript 사용을 포함한 여러 대응책이 설명되어 있다. 이에 더하여, 권한 부여 서버는 Content Security Policy (CSP) level 2 [CSP-2] 이상도 사용해야 한다.

효과적이기 위해 CSP는 권한 부여 엔드포인트와, 해당되는 경우 사용자를 인증하고 클라이언트를 권한 부여하는 데 사용되는 다른 엔드포인트(예: 장치 권한 부여 엔드포인트, 로그인 페이지, 오류 페이지 등)에 사용되어야 한다. 이는 CSP를 지원하는 사용자 에이전트에서 권한 없는 출처에 의한 프레이밍을 방지한다. 클라이언트는 자신의 리디렉션 엔드포인트에 사용된 출처가 아닌 다른 일부 출처에 의해 프레이밍되는 것을 허용할 수 있다. 이러한 이유로, 권한 부여 서버는 관리자가 특정 클라이언트에 대해 허용된 출처를 구성하거나 클라이언트가 이를 동적으로 등록할 수 있도록 허용해야 한다.

CSP를 사용하면 권한 부여 서버가 단일 응답 헤더 필드에서 여러 출처를 지정하고 유연한 패턴을 사용하여 이를 제한할 수 있다 (자세한 내용은 [CSP-2] 참조). 이 표준의 Level 2는 (frame-ancestors를 사용하여) 프레임의 출처를 제한하는 정책과 (script-src를 사용하여) HTML 페이지에서 실행이 허용되는 스크립트의 출처를 제한하는 정책을 함께 사용함으로써, 클릭재킹을 방지하는 견고한 메커니즘을 제공한다. 그러한 정책의 비규범적 예는 다음 목록에 표시되어 있다:

HTTP/1.1 200 OK
Content-Security-Policy: frame-ancestors https://ext.example.org:8000
Content-Security-Policy: script-src 'self'
X-Frame-Options: ALLOW-FROM https://ext.example.org:8000
...

일부 사용자 에이전트가 [CSP-2]를 지원하지 않기 때문에, 권한 부여 서버가 그러한 레거시 사용자 에이전트를 명시적으로 지원하지 않는 경우가 아니라면, 이 기법은 [RFC6819]에 설명된 것들을 포함한 다른 기법과 결합되어야 한다. 그러한 경우에도 추가 대응책은 여전히 사용되어야 한다.

7.11. 주입 및 입력 검증

주입 공격은 입력 또는 기타 외부 변수가 애플리케이션에서 정제되지 않은 채 사용되어 애플리케이션 로직의 수정을 일으킬 때 발생한다. 이는 공격자가 애플리케이션 장치 또는 그 데이터에 접근하거나, 서비스 거부를 유발하거나, 광범위한 악의적 부작용을 도입하도록 허용할 수 있다.

권한 부여 서버와 클라이언트는 수신한 매개변수를 잠재적으로 악의적인 외부 입력으로 취급하고 적절한 보호를 적용해야 하며, 특히 stateredirect_uri 매개변수의 값에 대해 그러해야 한다.

7.12. 오픈 리디렉션

오픈 리디렉터는 쿼리 매개변수에서 얻은 임의 URI로 사용자의 브라우저를 전달하는 엔드포인트이다. 이러한 엔드포인트는 예를 들어 사용자가 외부 웹사이트로 리디렉션되기 전에 메시지를 보여주거나, 로그인 프롬프트와 같은 것으로 중단되기 전에 사용자가 방문하려던 URL로 다시 리디렉션하기 위해 구현되기도 한다.

AS 또는 클라이언트에 오픈 리디렉터가 있을 때 다음 공격이 발생할 수 있다.

7.12.1. 오픈 리디렉터로서의 클라이언트

클라이언트는 오픈 리디렉터를 노출해서는 안 된다. 공격자는 [RFC9700]의 Section 4.1.1에 설명된 대로 오픈 리디렉터를 사용하여 클라이언트를 가리키는 URL을 만들고 이를 활용하여 권한 부여 코드를 유출할 수 있다. 또 다른 남용 사례는 클라이언트를 가리키는 것처럼 보이는 URL을 만드는 것이다. 이는 사용자를 속여 URL을 신뢰하고 브라우저에서 따라가게 할 수 있다. 이는 피싱에 악용될 수 있다.

오픈 리디렉션을 방지하기 위해 클라이언트는 대상 URL이 허용 목록에 있거나 요청의 출처와 무결성을 인증할 수 있는 경우에만 리디렉션해야 한다. 오픈 리디렉션에 대한 대응책은 OWASP [owasp_redir]에서 설명한다.

7.12.2. 오픈 리디렉터로서의 권한 부여 서버

클라이언트의 경우와 마찬가지로, 공격자는 사용자가 권한 부여 서버(특히 그 URL)에 대해 가지는 신뢰를 피싱 공격 수행에 활용하려고 시도할 수 있다. OAuth 권한 부여 서버는 정기적으로 사용자를 다른 웹사이트(클라이언트)로 리디렉션하지만, 이를 안전하게 수행해야 한다.

Section 4.1.2.1은 이미 client_idredirect_uri의 조합이 유효하지 않은 경우 권한 부여 서버가 사용자 에이전트를 자동으로 리디렉션해서는 안 된다고 명시하여 오픈 리디렉션을 방지한다.

그러나 공격자는 올바르게 등록된 리디렉션 URI도 피싱 공격에 활용할 수 있다. 예를 들어 공격자는 동적 클라이언트 등록 [RFC7591]을 통해 클라이언트를 등록하고 다음 공격 중 하나를 실행할 수 있다:

  1. 예를 들어 유효하지 않은 scope 값을 사용하여 의도적으로 잘못된 권한 부여 요청을 보내고, 따라서 권한 부여 서버가 사용자 에이전트를 자신의 피싱 사이트로 리디렉션하도록 지시한다.

  2. 공격자가 제어하는 client_idredirect_uri로 의도적으로 유효한 권한 부여 요청을 보낸다. 사용자가 인증한 후, 권한 부여 서버는 사용자에게 요청에 대한 동의를 제공하라고 요청한다. 사용자가 요청의 문제를 알아차리고 요청을 거부하더라도, 권한 부여 서버는 여전히 사용자 에이전트를 피싱 사이트로 리디렉션한다. 이 경우 사용자 에이전트는 사용자가 취한 동작과 관계없이 피싱 사이트로 리디렉션된다.

  3. 공격자가 제어하는 client_idredirect_uri로 의도적으로 유효한 무음 인증 요청(prompt=none)을 보낸다. 이 경우 권한 부여 서버는 사용자 에이전트를 피싱 사이트로 자동 리디렉션한다.

권한 부여 서버는 이러한 위협을 방지하기 위한 예방 조치를 취해야 한다. 권한 부여 서버는 항상 사용자를 먼저 인증해야 하며, 무음 인증 사용 사례를 제외하고, 필요할 때 사용자를 리디렉션하기 전에 자격 증명을 요청해야 한다. 권한 부여 서버는 위험 평가에 따라 리디렉션 URI를 신뢰할 수 있는지 여부를 결정해야 한다. 내부적으로 또는 외부 서비스를 통해 수행된 URI 분석을 고려하여 URI 뒤의 콘텐츠의 신뢰성과 신뢰도를 평가하고, 리디렉션 URI 및 기타 클라이언트 데이터의 출처를 고려할 수 있다.

권한 부여 서버는 리디렉션 URI를 신뢰하는 경우에만 사용자 에이전트를 자동으로 리디렉션해야 한다. URI가 신뢰되지 않는 경우, 권한 부여 서버는 사용자에게 알리고 사용자가 올바른 결정을 내리도록 의존할 수 있다.

7.13. 전송 보안

로드 밸런서를 활용하는 배포를 포함한 일부 배포에서는, 리소스를 제공하는 실제 서버에 도달하기 전에 리소스 서버에 대한 TLS 연결이 종료된다. 이는 TLS 연결이 종료되는 프런트엔드 서버와 리소스를 제공하는 백엔드 서버 사이에서 토큰을 보호되지 않은 상태로 둘 수 있다. 이러한 배포에서는 프런트엔드와 백엔드 서버 사이의 접근 토큰 기밀성을 보장하기 위해 충분한 조치를 사용해야 하며, 토큰 암호화는 그러한 가능한 조치 중 하나이다.

추가 정보는 [RFC9110]의 Section 17.2를 참조한다.

7.14. 권한 부여 서버 Mix-Up 완화

Mix-up은 OAuth 클라이언트가 둘 이상의 권한 부여 서버와 상호작용하고, 그중 적어도 하나의 권한 부여 서버가 공격자의 제어 아래에 있는 시나리오에 대한 공격이다. 예를 들어 공격자가 동적 등록을 사용하여 자신의 권한 부여 서버에 클라이언트를 등록하거나, 권한 부여 서버가 손상된 경우가 이에 해당할 수 있다.

OAuth 클라이언트가 하나의 권한 부여 서버와만 상호작용할 수 있는 경우, mix-up 방어는 필요하지 않다. 그러나 OAuth 클라이언트가 둘 이상의 권한 부여 서버와 상호작용하는 시나리오에서는, 클라이언트가 mix-up 공격을 방지해야 한다. 다음에서는 두 가지 서로 다른 방법을 논의한다.

두 방어 모두에 대해, 클라이언트는 각 권한 부여 요청마다 권한 부여 요청을 보낸 발급자를 저장하고, 이 정보를 사용자 에이전트에 바인딩하며, 권한 부여 응답이 올바른 발급자에서 수신되었는지 확인해야 한다. 클라이언트는 후속 접근 토큰 요청이 해당되는 경우 동일한 발급자에게 전송되도록 보장해야 한다. 발급자는 관련 메타데이터를 통해, 흐름에서 사용될 권한 부여 엔드포인트와 토큰 엔드포인트의 조합에 대한 추상 식별자로 기능한다. 발급자 식별자를 사용할 수 없는 경우, 예를 들어 OAuth 2.0 Authorization Server Metadata [RFC8414]도 OpenID Connect Discovery [OpenID.Discovery]도 사용되지 않는 경우, 이 튜플에 대한 다른 고유 식별자 또는 튜플 자체를 대신 사용할 수 있다. 설명의 간결성을 위해, 이러한 배포별 식별자는 이하에서 발급자 (또는 발급자 식별자)에 포함되는 것으로 한다.

참고: 권한 부여 서버 URL만 저장하는 것으로는 mix-up 공격을 식별하기에 충분하지 않다. 공격자는 손상되지 않은 AS의 권한 부여 엔드포인트 URL을 "자신의" AS URL로 선언하면서, 토큰 엔드포인트는 자신의 제어 아래에 있는 것으로 선언할 수 있다.

여러 유형의 mix-up 공격에 대한 자세한 설명은 [RFC9700]의 Section 4.4를 참조한다.

7.14.1. 발급자 식별을 통한 Mix-Up 방어

이 방어는 권한 부여 서버가 자신의 발급자 식별자를 권한 부여 응답에서 클라이언트에 보내도록 요구한다. 권한 부여 응답을 받을 때, 클라이언트는 받은 발급자 식별자를 저장된 발급자 식별자와 비교해야 한다. 불일치가 있으면 클라이언트는 상호작용을 중단해야 한다.

이 발급자 식별자를 클라이언트로 전달하는 방법은 여러 가지가 있다:

  • 발급자 정보는 예를 들어 선택적 응답 매개변수 iss를 통해 전달될 수 있다 (Section 4.1.2 참조).

  • OpenID Connect가 사용되고 ID Token이 권한 부여 응답에서 반환되는 경우, 클라이언트는 ID Token의 iss 클레임을 평가할 수 있다.

두 경우 모두, iss 값은 [RFC9207]에 따라 평가되어야 한다.

이 방어는 발급자 정보를 전달하기 위해 추가 매개변수 사용을 요구할 수 있지만, mix-up에 대한 견고하고 비교적 간단한 방어이다.

7.14.2. 구별된 리디렉션 URI를 통한 Mix-Up 방어

이 방어에서 클라이언트는 상호작용하는 각 발급자마다 구별된 리디렉션 URI를 사용해야 한다.

클라이언트는 발급자에 대한 구별된 리디렉션 URI를 권한 부여 응답이 수신된 URI와 비교하여 권한 부여 응답이 올바른 발급자로부터 수신되었는지 확인해야 한다. 불일치가 있으면 클라이언트는 흐름을 중단해야 한다.

이 방어는 기존 OAuth 기능을 기반으로 하지만, 여러 다른 발급자를 사용하기 위해 클라이언트가 한 번만 등록하는 시나리오(일부 오픈뱅킹 스킴과 같은 경우)에서는 사용할 수 없고, 클라이언트 등록과 긴밀하게 통합되어 있어 자동으로 배포하기가 더 어렵다.

또한 공격자는 클라이언트가 공격자의 AS에 할당한 리디렉션 URI를 사용하여 "정직한" AS에 새 클라이언트를 등록함으로써 이 방어가 제공하는 보호를 우회할 수 있을지도 모른다. 그런 다음 공격자는 위에서 설명한 대로 공격을 실행하면서, 클라이언트 ID를 새로 만든 클라이언트의 클라이언트 ID로 바꿀 수 있다.

따라서 이 방어는 다른 옵션을 사용할 수 없는 경우에만 사용해야 한다.

8. 네이티브 애플리케이션

네이티브 애플리케이션은 리소스 소유자가 사용하는 장치에 설치되어 실행되는 클라이언트이다(즉, 데스크톱 애플리케이션 또는 네이티브 모바일 애플리케이션). 네이티브 애플리케이션은 보안, 플랫폼 기능, 그리고 전반적인 최종 사용자 경험과 관련하여 특별한 고려가 필요하다.

이 절의 지침은 주로 데스크톱 앱과 대비되는 네이티브 모바일 앱의 맥락에 있다. 네이티브 모바일 플랫폼은 여기서 설명하는 OAuth 흐름과 관련하여 앱 개발자에게 제공되는 기능 측면에서 데스크톱 플랫폼보다 더 성숙해졌다. 이 지침은 주로 모바일 앱에 초점을 맞추고 있지만, 그 상당 부분은 일반적으로 데스크톱 앱에도 적용될 수 있다.

권한 부여 엔드포인트는 클라이언트와 리소스 소유자의 사용자 에이전트 사이의 상호작용을 요구한다. 현재의 모범 관행은 OAuth 권한 부여 요청을 내장 사용자 에이전트(예: 웹뷰로 구현된 것)가 아니라 외부 사용자 에이전트(일반적으로 브라우저)에서 수행하는 것이다.

네이티브 애플리케이션은 각각 다른 보안 속성을 가진 여러 가지 방식으로 권한 부여 서버의 응답을 캡처할 수 있다. 예를 들어, 운영 체제에 등록되어 클라이언트를 핸들러로 호출하는 "앱이 소유권을 주장한 URL" 또는 사용자 지정 URL 스킴이 있는 리디렉션 URI를 사용하거나, 자격 증명의 수동 복사 및 붙여넣기, 로컬 웹 서버 실행, 사용자 에이전트 확장 설치, 또는 클라이언트가 제어하는 서버 호스팅 리소스를 식별하는 리디렉션 URI를 제공하고, 그 리소스가 다시 네이티브 애플리케이션에 응답을 제공하는 방식이 있다.

이전에는 네이티브 앱이 OAuth 권한 부여 요청에 내장 사용자 에이전트(일반적으로 웹뷰로 구현됨)를 사용하는 것이 흔했다. 이 접근 방식에는 호스트 앱이 사용자 자격 증명과 쿠키를 복사할 수 있다는 점, 사용자가 각 앱에서 처음부터 인증해야 한다는 점을 포함하여 많은 단점이 있다. OAuth에 내장 사용자 에이전트를 사용하는 단점에 대한 더 깊은 분석은 Section 8.5.1을 참조한다.

시스템 브라우저를 사용하는 네이티브 앱 권한 부여 요청은 더 안전하며 장치에서 사용자의 인증 상태를 활용할 수 있다. 브라우저의 기존 인증 세션을 사용할 수 있으면, 사용자가 새 앱을 사용할 때마다(권한 부여 서버 정책에서 요구하지 않는 한) 권한 부여 서버에 인증할 필요가 없으므로 싱글 사인온이 가능해진다.

네이티브 앱과 브라우저 사이의 권한 부여 흐름을 지원하는 것은 OAuth 프로토콜 자체를 변경하지 않고도 가능하다. OAuth 권한 부여 요청과 응답은 이미 URI를 기준으로 정의되어 있기 때문이다. 여기에는 앱 간 통신에 사용할 수 있는 URI가 포함된다. 모든 클라이언트가 기밀 웹 클라이언트라고 가정하는 일부 OAuth 서버 구현은 이 모범 관행을 지원하기 위해 공개 네이티브 앱 클라이언트와 이들이 사용하는 리디렉션 URI 유형에 대한 이해를 추가해야 한다.

8.1. 네이티브 앱의 클라이언트 인증

여러 사용자에게 배포되는 앱의 일부로 정적으로 포함된 시크릿은 기밀 시크릿이 아니다. 한 사용자가 자신의 사본을 검사하여 공유 시크릿을 알아낼 수 있기 때문이다. 이러한 이유로 권한 부여 서버는 공유 시크릿을 사용한 네이티브 앱 클라이언트의 클라이언트 인증을 요구해서는 안 된다. 이는 client_id 요청 매개변수가 이미 제공하는 클라이언트 식별 이상의 가치를 제공하지 않기 때문이다.

네이티브 앱 클라이언트에 정적으로 포함된 공유 시크릿을 여전히 요구하는 권한 부여 서버는 해당 클라이언트를 (Section 2.1에 정의된) 공개 클라이언트로 취급해야 하며, 그 시크릿을 클라이언트 신원 증명으로 받아들여서는 안 된다. 추가 조치가 없으면, 그러한 클라이언트는 클라이언트 가장의 대상이 된다 (Section 7.3.1 참조).

8.1.1. 네이티브 앱 클라이언트 등록

인스턴스별 자격 증명을 프로비저닝하기 위해 Dynamic Client Registration [RFC7591] 같은 메커니즘을 사용하는 경우를 제외하고, 네이티브 앱은 Section 2.1에 정의된 공개 클라이언트로 분류되며, 권한 부여 서버에 그렇게 등록되어야 한다. 권한 부여 서버는 요청을 그에 맞게 식별하고 처리할 수 있도록 클라이언트 등록 세부 정보에 클라이언트 유형을 기록해야 한다.

8.1.2. 네이티브 앱 증명

초안 명세 [I-D.ietf-oauth-attestation-based-client-auth]는 네이티브 앱이 권한 부여 서버 또는 리소스 서버에 인증하기 위해 키에 바인딩된 증명을 얻는 데 사용할 수 있는 메커니즘을 정의한다. 이는 모바일 앱 신원에 대해 더 높은 수준의 보증을 제공할 수 있다.

8.2. 네이티브 앱에서 OAuth를 위한 앱 간 URI 통신 사용

웹에서 OAuth가 권한 부여 요청을 시작하고 권한 부여 응답을 요청한 웹사이트로 반환하기 위해 URI를 사용하는 것처럼, 네이티브 앱도 URI를 사용하여 장치의 브라우저에서 권한 부여 요청을 시작하고 응답을 요청한 네이티브 앱으로 반환할 수 있다.

OAuth를 위해 웹에서 사용하는 동일한 방법을 채택하면, 싱글 사인온 세션의 사용성 및 별도 인증 맥락의 보안 같은 웹 맥락에서 보이는 이점이 네이티브 앱 맥락에서도 마찬가지로 얻어진다. 동일한 접근 방식을 재사용하면 특정 플랫폼에 종속되지 않는 표준 기반 웹 흐름에 의존함으로써 구현 복잡성도 줄이고 상호운용성도 높인다.

네이티브 앱은 OAuth 권한 부여 요청을 수행하기 위해 외부 사용자 에이전트를 사용해야 한다. 이는 브라우저에서 권한 부여 요청을 열고 (Section 8.3에서 자세히 설명), 권한 부여 응답을 네이티브 앱으로 다시 반환할 리디렉션 URI를 사용하는 방식으로 달성된다(Section 8.4에서 정의).

8.3. 네이티브 앱에서 권한 부여 요청 시작

사용자 권한 부여가 필요한 네이티브 앱은 네이티브 앱이 수신할 수 있는 리디렉션 URI를 사용하여 Section 4.1에 따른 권한 부여 코드 그랜트 유형으로 권한 부여 요청 URI를 만든다.

네이티브 앱 권한 부여 요청에서 리디렉션 URI의 기능은 웹 기반 권한 부여 요청의 기능과 유사하다. 권한 부여 응답을 OAuth 클라이언트의 서버로 반환하는 대신, 네이티브 앱이 사용하는 리디렉션 URI는 응답을 앱으로 반환한다. 여러 플랫폼에서 권한 부여 응답을 네이티브 앱으로 반환할 리디렉션 URI에 대한 몇 가지 옵션은 Section 8.4에 문서화되어 있다. 앱이 URI를 수신하고 그 매개변수를 검사할 수 있게 하는 모든 리디렉션 URI는 실행 가능하다.

권한 부여 요청 URI를 구성한 후, 앱은 플랫폼별 API를 사용하여 외부 사용자 에이전트에서 URI를 연다. 일반적으로 사용되는 외부 사용자 에이전트는 기본 브라우저, 즉 시스템에서 httphttps 스킴 URI를 처리하도록 구성된 애플리케이션이다. 그러나 다른 브라우저 선택 기준과 다른 범주의 외부 사용자 에이전트가 사용될 수 있다.

이 모범 관행은 네이티브 앱에 권장되는 외부 사용자 에이전트로 브라우저에 초점을 맞춘다. 사용자 권한 부여를 위해 특별히 설계되고 브라우저처럼 권한 부여 요청과 응답을 처리할 수 있는 외부 사용자 에이전트도 사용될 수 있다. 권한 부여 서버가 제공하는 네이티브 앱 같은 다른 외부 사용자 에이전트도 동일한 리디렉션 URI 속성 사용을 포함하여 이 모범 관행에서 정한 기준을 충족할 수 있지만, 그 사용은 이 명세의 범위를 벗어난다.

일부 플랫폼은 "인앱 브라우저 탭"으로 알려진 브라우저 기능을 지원한다. 이 기능에서는 앱이 앱 맥락 내에서 브라우저의 탭을 표시할 수 있으므로 앱 전환 없이도 공유 인증 상태와 보안 맥락 같은 브라우저의 핵심 이점을 유지할 수 있다. 이러한 기능이 지원되는 플랫폼에서는 사용성 이유로 앱이 권한 부여 요청에 인앱 브라우저 탭을 사용하는 것이 권장된다.

8.4. 네이티브 앱에서 권한 부여 응답 수신

브라우저에서 권한 부여 응답을 수신하기 위해 네이티브 앱이 사용할 수 있는 여러 리디렉션 URI 옵션이 있으며, 그 가용성과 사용자 경험은 플랫폼마다 다르다.

8.4.1. 소유권이 주장된 "https" 스킴 URI 리디렉션

일부 운영 체제, 특히 모바일 운영 체제는 앱이 자신이 제어하는 도메인에서 https URI (Section 4.2.2 of [RFC9110] 참조)의 소유권을 주장하도록 허용한다. 브라우저가 소유권이 주장된 URI를 만나면, 페이지가 브라우저에 로드되는 대신 네이티브 앱이 시작되고 URI가 시작 매개변수로 제공된다.

그러한 URI는 네이티브 앱에서 리디렉션 URI로 사용할 수 있다. 권한 부여 서버 입장에서는 일반 웹 기반 클라이언트 리디렉션 URI와 구별되지 않는다. 예는 다음과 같다:

https://app.example.com/oauth2redirect/example-provider

리디렉션 URI만으로는 공개 네이티브 앱 클라이언트와 기밀 웹 클라이언트를 구별하기에 충분하지 않으므로, Section 8.1.1에서는 서버가 클라이언트 유형을 결정하고 그에 따라 동작할 수 있도록 클라이언트 등록 중 클라이언트 유형을 기록하는 것을 REQUIRED로 한다.

앱이 소유권을 주장한 https 스킴 리디렉션 URI는 다른 네이티브 앱 리디렉션 옵션과 비교할 때, 운영 체제가 대상 앱의 신원을 권한 부여 서버에 보장한다는 장점이 있다. 이러한 이유로 네이티브 앱은 가능한 경우 다른 옵션보다 이를 사용하는 것이 좋다.

8.4.2. 루프백 인터페이스 리디렉션

특별한 권한 없이 루프백 네트워크 인터페이스에서 포트를 열 수 있는 네이티브 앱(일반적으로 데스크톱 운영 체제의 앱)은 루프백 인터페이스를 사용하여 OAuth 리디렉션을 수신할 수 있다.

루프백 리디렉션 URI는 http 스킴을 사용하며, 루프백 IP 리터럴과 클라이언트가 수신 대기 중인 포트로 구성된다.

즉, IPv4의 경우 http://127.0.0.1:{port}/{path}, IPv6의 경우 http://[::1]:{port}/{path}이다. 임의로 할당된 포트와 IPv4 루프백 인터페이스를 사용하는 리디렉션 예는 다음과 같다:

http://127.0.0.1:51004/oauth2redirect/example-provider

임의로 할당된 포트와 IPv6 루프백 인터페이스를 사용하는 리디렉션 예는 다음과 같다:

http://[::1]:61023/oauth2redirect/example-provider

localhost라는 이름을 사용하는 리디렉션 URI (즉, http://localhost:{port}/{path})도 루프백 IP 리디렉션과 유사하게 동작하지만, localhost 사용은 권장되지 않는다. 리디렉션 URI에 localhost 대신 루프백 IP 리터럴을 지정하면 루프백 인터페이스가 아닌 네트워크 인터페이스에서 의도치 않게 수신 대기하는 일을 피할 수 있다. 또한 사용자 장치의 클라이언트 측 방화벽 및 잘못 구성된 호스트 이름 해석에 덜 취약하다.

권한 부여 서버는 요청 시점에 루프백 IP 리디렉션 URI에 임의의 포트가 지정되는 것을 허용해야 한다. 이는 요청 시점에 운영 체제에서 사용 가능한 임시 포트를 얻는 클라이언트를 수용하기 위한 것이다.

클라이언트는 장치가 특정 버전의 인터넷 프로토콜을 지원한다고 가정해서는 안 된다. 클라이언트가 IPv4와 IPv6 모두를 사용하여 루프백 인터페이스에 바인딩을 시도하고, 사용 가능한 것을 사용하는 것이 권장된다.

8.4.3. 사설 사용 URI 스킴 리디렉션

많은 모바일 및 데스크톱 컴퓨팅 플랫폼은 앱이 com.example.app 같은 사설 사용 URI 스킴(구어적으로 "사용자 지정 URL 스킴"이라고도 함)을 등록하도록 허용함으로써 URI를 통한 앱 간 통신을 지원한다. 브라우저나 다른 앱이 사설 사용 URI 스킴이 있는 URI를 로드하려고 하면, 이를 등록한 앱이 요청을 처리하기 위해 시작된다.

사설 사용 URI 스킴을 지원하는 많은 환경은 어떤 스킴의 소유권을 주장하고 다른 당사자가 다른 애플리케이션의 스킴을 사용하는 것을 방지하는 메커니즘을 제공하지 않는다. 따라서 사설 사용 URI 스킴을 사용하는 클라이언트는 리디렉션 URI에 대한 잠재적 공격에 취약하므로, 앞서 언급한 더 안전한 옵션을 사용할 수 없는 경우에만 이 옵션을 사용해야 한다.

사설 사용 URI 스킴 리디렉션으로 권한 부여 요청을 수행하려면, 네이티브 앱은 표준 권한 부여 요청으로 브라우저를 실행하지만, 이때 리디렉션 URI는 운영 체제에 등록한 사설 사용 URI 스킴을 사용한다.

앱과 연결할 URI 스킴을 선택할 때, 앱은 사설 사용 URI 스킴에 대해 Section 3.8 of [RFC7595]에서 권장한 대로, 자신이 제어하는 도메인 이름을 역순으로 표현한 URI 스킴을 사용해야 한다.

예를 들어 app.example.com 도메인 이름을 제어하는 앱은 com.example.app을 스킴으로 사용할 수 있다. 일부 권한 부여 서버는 도메인 이름을 기반으로 클라이언트 식별자를 할당한다. 예를 들어 client1234.usercontent.example.net은 같은 방식으로 역순으로 표현하여 스킴의 도메인 이름으로도 사용할 수 있다. 그러나 myapp 같은 스킴은 도메인 이름을 기반으로 하지 않으므로 이 요구사항을 충족하지 않는다.

같은 게시자의 앱이 여러 개 있는 경우, 각 스킴이 그 그룹 안에서 고유하도록 주의해야 한다. 역순 도메인 이름 기반 앱 식별자를 사용하는 플랫폼에서는, 이러한 식별자를 OAuth 리디렉션을 위한 사설 사용 URI 스킴으로 재사용하여 이 문제를 피하는 데 도움을 줄 수 있다.

Section 3.2 of [RFC3986]의 요구사항에 따라, 사설 사용 URI 스킴 리디렉션에는 명명 기관이 없으므로 스킴 구성 요소 뒤에는 단일 슬래시(/)만 나타난다. 사설 사용 URI 스킴을 활용하는 완전한 리디렉션 URI 예는 다음과 같다:

com.example.app:/oauth2redirect/example-provider

권한 부여 서버가 요청을 완료하면, 평소처럼 클라이언트의 리디렉션 URI로 리디렉션한다. 리디렉션 URI가 사설 사용 URI 스킴을 사용하므로, 그 결과 운영 체제가 네이티브 앱을 실행하고 URI를 시작 매개변수로 전달한다. 그런 다음 네이티브 앱은 권한 부여 응답에 대해 일반 처리를 사용한다.

8.5. 네이티브 앱의 보안 고려사항

8.5.1. 네이티브 앱의 내장 사용자 에이전트

내장 사용자 에이전트는 네이티브 앱을 권한 부여하기 위한 기술적으로 가능한 방법이다. 이러한 내장 사용자 에이전트는 정의상 권한 부여 서버의 제3자 사용에 안전하지 않다. 내장 사용자 에이전트를 호스팅하는 앱이 앱을 위해 의도된 OAuth 권한 부여 그랜트뿐 아니라 사용자의 전체 인증 자격 증명에도 접근할 수 있기 때문이다. 또한 일반적으로 운영 체제에 의해 샌드박스화되며, 웹 출처에 의존하는 WebAuthn 같은 메커니즘은 비활성화된다.

웹뷰 기반 내장 사용자 에이전트의 일반적인 구현에서, 호스트 애플리케이션은 로그인 양식에 입력되는 모든 키 입력을 기록하여 사용자 이름과 비밀번호를 캡처하고, 사용자 동의를 우회하기 위해 자동으로 양식을 제출하며, 세션 쿠키를 복사하여 사용자로 인증된 동작을 수행하는 데 사용할 수 있다.

권한 부여 서버와 같은 당사자에 속한 신뢰할 수 있는 앱이 사용하는 경우에도, 내장 사용자 에이전트는 필요한 것보다 더 강력한 자격 증명에 접근하게 되어 최소 권한 원칙을 위반하며, 잠재적으로 공격 표면을 증가시킨다.

브라우저가 갖는 일반적인 주소 표시줄과 보이는 인증서 검증 기능 없이 내장 사용자 에이전트에 자격 증명을 입력하도록 사용자를 유도하면, 사용자는 자신이 합법적인 사이트에 로그인하고 있는지 알 수 없다. 실제로 합법적인 사이트라 하더라도, 이는 사용자가 먼저 사이트를 검증하지 않고 자격 증명을 입력해도 괜찮다고 학습하게 만든다.

보안 우려와 별개로, 내장 사용자 에이전트는 다른 앱이나 브라우저와 인증 상태를 공유하지 않으므로, 사용자가 모든 권한 부여 요청마다 로그인해야 하며, 이는 종종 열등한 사용자 경험으로 간주된다.

8.5.2. 네이티브 앱의 가짜 외부 사용자 에이전트

권한 부여 요청을 시작하는 네이티브 앱은 사용자 인터페이스에 대해 큰 제어권을 가지고 있으며, 잠재적으로 가짜 외부 사용자 에이전트, 즉 외부 사용자 에이전트처럼 보이도록 만든 내장 사용자 에이전트를 표시할 수 있다.

모든 선의의 행위자가 외부 사용자 에이전트를 사용할 때의 장점은, 외부 사용자 에이전트를 위조하는 사람은 입증 가능하게 악의적이므로 보안 전문가가 악의적 행위자를 탐지할 수 있다는 것이다. 반면 선의의 행위자와 악의적 행위자 모두가 내장 사용자 에이전트를 사용한다면, 악의적 행위자는 아무것도 위조할 필요가 없어 탐지가 더 어려워진다. 악성 앱이 탐지되면, 이 지식을 사용하여 악성 코드 검사 소프트웨어에서 앱의 서명을 블랙리스트에 올리거나, 앱 스토어에서 배포되는 앱의 경우 제거 조치를 취하고, 악성 앱의 영향과 확산을 줄이기 위한 다른 조치를 취할 수 있다.

권한 부여 서버는 진짜 외부 사용자 에이전트에서만 사용할 수 있는 인증 요소를 요구함으로써 가짜 외부 사용자 에이전트에 직접적으로도 보호할 수 있다.

인앱 브라우저 탭을 사용할 때 보안에 특히 우려가 있는 사용자는, 인앱 브라우저 탭에서 전체 브라우저로 요청을 열고 그곳에서 권한 부여를 완료하는 추가 조치를 취할 수도 있다. 대부분의 인앱 브라우저 탭 패턴 구현이 그러한 기능을 제공하기 때문이다.

8.5.3. 네이티브 앱의 악의적인 외부 사용자 에이전트

악성 앱이 운영 체제에서 https 스킴 URI의 기본 핸들러로 자신을 구성할 수 있다면, 기본 브라우저를 사용하는 권한 부여 요청을 가로채고 이 신뢰 위치를 악용하여 사용자를 피싱하는 등 악의적인 목적을 달성할 수 있다.

이 공격은 OAuth에 국한되지 않는다. 이러한 방식으로 구성된 악성 앱은 네이티브 앱의 OAuth 사용을 넘어 사용자에게 일반적이고 지속적인 위험을 제시한다. 많은 운영 체제는 httphttps 스킴 URI의 기본 핸들러를 변경하려면 명시적인 사용자 동작을 요구함으로써 이 문제를 완화한다.

8.5.4. 네이티브 앱의 루프백 리디렉션 고려사항

루프백 인터페이스 리디렉션 URI는 http 스킴(즉, TLS 없이)을 사용할 수 있다. 이는 HTTP 요청이 장치를 벗어나지 않기 때문에 루프백 인터페이스 리디렉션 URI에 허용된다.

클라이언트는 권한 부여 요청을 시작할 때만 네트워크 포트를 열고, 응답이 반환되면 포트를 닫는 것이 좋다.

클라이언트는 다른 네트워크 행위자의 간섭을 피하기 위해 루프백 네트워크 인터페이스에서만 수신 대기하는 것이 좋다.

클라이언트는 Section 8.4.2에 설명된 대로 문자열 localhost보다 루프백 IP 리터럴을 사용하는 것이 좋다.

9. 브라우저 기반 앱

브라우저 기반 앱은 웹 브라우저에서 실행되는 클라이언트이며, 일반적으로 JavaScript로 작성되고 "single-page apps"라고도 한다. 이러한 유형의 앱은 네이티브 앱과 유사한 특정 보안 고려사항을 가진다.

TODO: 브라우저 기반 앱 BCP가 최종화되면 그 규범 텍스트를 가져온다.

10. OAuth 2.0과의 차이점

이 초안은 OAuth 2.0 [RFC6749], OAuth 2.0 for Native Apps [RFC8252], Proof Key for Code Exchange [RFC7636], OAuth 2.0 for Browser-Based Apps [I-D.ietf-oauth-browser-based-apps], OAuth Security Best Current Practice [RFC9700], 및 Bearer Token Usage [RFC6750]의 기능을 통합한다.

이후 초안이 원래의 [RFC6749]에서 발견되는 기능을 갱신하거나 폐기하는 경우, 이 초안의 해당 기능은 이후 초안에서 설명한 규범적 변경사항으로 갱신되거나 완전히 제거된다.

OAuth 2.0에서 변경된 사항의 비규범적 목록은 아래와 같다:

10.1. OAuth 2.0 Implicit 그랜트 제거

OAuth 2.0 Implicit 그랜트는 [RFC9700]에서 폐기되었으므로 OAuth 2.1에서 생략된다.

Implicit 그랜트를 제거하는 의도는 더 이상 권한 부여 응답에서 접근 토큰을 발급하지 않는 것이다. 그러한 토큰은 유출 및 주입에 취약하고, 클라이언트에 발신자 제한될 수 없기 때문이다. 이 동작은 클라이언트가 response_type=token 매개변수를 사용하여 나타냈다. response_type 매개변수의 이 값은 OAuth 2.1에서 더 이상 정의되지 않는다.

response_type=token의 제거는 권한 부여 엔드포인트에서 다른 산출물을 반환하는 다른 확장 응답 유형, 예를 들어 [OpenID.Connect]가 정의한 response_type=id_token에는 영향을 주지 않는다.

10.2. 토큰 요청의 Redirect URI 매개변수

OAuth 2.0에서 권한 부여 코드 흐름의 토큰 엔드포인트 요청 (Section 4.1.3 of [RFC6749])은 선택적 redirect_uri 매개변수를 포함한다. 이 매개변수는 권한 부여 코드 주입 공격을 방지하기 위한 것이었으며, 원래 권한 부여 요청에 redirect_uri 매개변수가 전송된 경우 필수였다. 권한 부여 요청은 특정 클라이언트에 여러 리디렉션 URI가 등록된 경우에만 redirect_uri 매개변수를 요구했다. 그러나 실제로는 많은 권한 부여 서버 구현이 하나만 등록된 경우에도 권한 부여 요청에서 redirect_uri 매개변수를 요구했고, 그 결과 토큰 엔드포인트에서도 redirect_uri 매개변수가 요구되었다.

OAuth 2.1에서는 권한 부여 코드 주입이 code_challengecode_verifier 매개변수로 방지되므로, 토큰 요청에 redirect_uri 매개변수를 포함하는 것은 아무 목적도 제공하지 않는다. 따라서 이 매개변수는 제거되었다.

OAuth 2.0 및 OAuth 2.1 클라이언트를 모두 지원하려는 권한 부여 서버의 하위 호환성을 위해, 권한 부여 서버는 클라이언트가 토큰 요청 (Section 4.1.3)에서 redirect_uri 매개변수를 보내도록 허용해야 하며, [RFC6749]에 설명된 대로 해당 매개변수를 강제해야 한다. 권한 부여 서버는 요청의 client_id를 사용하여 특정 클라이언트가 더 오래된 OAuth 2.0 동작을 사용할 것임을 알고 있는 경우 이 동작을 강제할지 결정할 수 있다.

OAuth 2.1 권장사항만 따르는 클라이언트는 토큰 요청에서 redirect_uri를 보내지 않으므로, 토큰 요청에서 해당 매개변수를 기대하는 권한 부여 서버와 호환되지 않는다.

11. IANA 고려사항

이 문서는 어떤 IANA 조치도 요구하지 않는다.

참조된 모든 레지스트리는 [RFC6749] 및 이 작업이 기반으로 하는 관련 문서에서 정의된다. 이 명세에 의해 그러한 레지스트리에 대한 변경은 요구되지 않는다.

12. 참고문헌

12.1. 규범 참고문헌

[BCP195]
Saint-Andre, P., "Transport Layer Security (TLS)의 안전한 사용을 위한 권장사항", .
[RFC2119]
Bradner, S., "요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC2617]
Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, "HTTP 인증: Basic 및 Digest 접근 인증", RFC 2617, DOI 10.17487/RFC2617, , <https://www.rfc-editor.org/info/rfc2617>.
[RFC3629]
Yergeau, F., "UTF-8, ISO 10646의 변환 형식", STD 63, RFC 3629, DOI 10.17487/RFC3629, , <https://www.rfc-editor.org/info/rfc3629>.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): 일반 구문", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>.
[RFC4949]
Shirey, R., "인터넷 보안 용어집, 버전 2", FYI 36, RFC 4949, DOI 10.17487/RFC4949, , <https://www.rfc-editor.org/info/rfc4949>.
[RFC5234]
Crocker, D., Ed. and P. Overell, "구문 명세를 위한 확장 BNF: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, , <https://www.rfc-editor.org/info/rfc5234>.
[RFC6749]
Hardt, D., Ed., "OAuth 2.0 권한 부여 프레임워크", RFC 6749, DOI 10.17487/RFC6749, , <https://www.rfc-editor.org/info/rfc6749>.
[RFC6750]
Jones, M. and D. Hardt, "OAuth 2.0 권한 부여 프레임워크: Bearer 토큰 사용", RFC 6750, DOI 10.17487/RFC6750, , <https://www.rfc-editor.org/info/rfc6750>.
[RFC7235]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): 인증", RFC 7235, DOI 10.17487/RFC7235, , <https://www.rfc-editor.org/info/rfc7235>.
[RFC7521]
Campbell, B., Mortimore, C., Jones, M., and Y. Goland, "OAuth 2.0 클라이언트 인증 및 권한 부여 그랜트를 위한 어설션 프레임워크", RFC 7521, DOI 10.17487/RFC7521, , <https://www.rfc-editor.org/info/rfc7521>.
[RFC7523]
Jones, M., Campbell, B., and C. Mortimore, "OAuth 2.0 클라이언트 인증 및 권한 부여 그랜트를 위한 JSON Web Token (JWT) 프로파일", RFC 7523, DOI 10.17487/RFC7523, , <https://www.rfc-editor.org/info/rfc7523>.
[RFC7595]
Thaler, D., Ed., Hansen, T., and T. Hardie, "URI 스킴을 위한 지침 및 등록 절차", BCP 35, RFC 7595, DOI 10.17487/RFC7595, , <https://www.rfc-editor.org/info/rfc7595>.
[RFC8174]
Leiba, B., "RFC 2119 핵심 단어에서 대문자와 소문자의 모호성", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8252]
Denniss, W. and J. Bradley, "네이티브 앱을 위한 OAuth 2.0", BCP 212, RFC 8252, DOI 10.17487/RFC8252, , <https://www.rfc-editor.org/info/rfc8252>.
[RFC8259]
Bray, T., Ed., "JavaScript Object Notation (JSON) 데이터 교환 형식", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/info/rfc8259>.
[RFC8446]
Rescorla, E., "Transport Layer Security (TLS) 프로토콜 버전 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/info/rfc8446>.
[RFC9110]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP 의미론", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/info/rfc9110>.
[RFC9111]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP 캐싱", STD 98, RFC 9111, DOI 10.17487/RFC9111, , <https://www.rfc-editor.org/info/rfc9111>.
[RFC9207]
Meyer zu Selhausen, K. and D. Fett, "OAuth 2.0 권한 부여 서버 발급자 식별", RFC 9207, DOI 10.17487/RFC9207, , <https://www.rfc-editor.org/info/rfc9207>.
[RFC9700]
Lodderstedt, T., Bradley, J., Labunets, A., and D. Fett, "OAuth 2.0 보안을 위한 Best Current Practice", BCP 240, RFC 9700, DOI 10.17487/RFC9700, , <https://www.rfc-editor.org/info/rfc9700>.
[USASCII]
Institute, A. N. S., "부호화 문자 집합 -- 7비트 American Standard Code for Information Interchange, ANSI X3.4", .
[W3C.REC-xml-20081126]
Bray, T., Paoli, J., Sperberg-McQueen, C. M., Maler, E., and F. Yergeau, "Extensible Markup Language", , <https://www.w3.org/TR/REC-xml/REC-xml-20081126.xml>.
[WHATWG.CORS]
WHATWG, "Fetch Standard: CORS 프로토콜", , <https://fetch.spec.whatwg.org/#http-cors-protocol>.
[WHATWG.URL]
WHATWG, "URL", , <https://url.spec.whatwg.org/>.

12.2. 정보 참고문헌

[CSP-2]
"Content Security Policy Level 2", , <https://www.w3.org/TR/CSP2>.
[I-D.bradley-oauth-jwt-encoded-state]
Bradley, J., Lodderstedt, T., and H. Zandbelt, "JWT를 사용해 OAuth 2 state 매개변수에 클레임 인코딩", 진행 중인 작업, Internet-Draft, draft-bradley-oauth-jwt-encoded-state-09, , <https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-09>.
[I-D.ietf-oauth-attestation-based-client-auth]
Looker, T., Bastian, P., and C. Bormann, "OAuth 2.0 증명 기반 클라이언트 인증", 진행 중인 작업, Internet-Draft, draft-ietf-oauth-attestation-based-client-auth-07, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-attestation-based-client-auth-07>.
[I-D.ietf-oauth-browser-based-apps]
Parecki, A., De Ryck, P., and D. Waite, "브라우저 기반 애플리케이션을 위한 OAuth 2.0", 진행 중인 작업, Internet-Draft, draft-ietf-oauth-browser-based-apps-26, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps-26>.
[I-D.ietf-oauth-rfc7523bis]
Jones, M. B., Campbell, B., Mortimore, C., and F. Skokan, "OAuth 2.0 JSON Web Token (JWT) 클라이언트 인증 및 어설션 기반 권한 부여 그랜트에 대한 갱신", 진행 중인 작업, Internet-Draft, draft-ietf-oauth-rfc7523bis-05, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rfc7523bis-05>.
[NIST800-63]
Burr, W., Dodson, D., Newton, E., Perlner, R., Polk, T., Gupta, S., and E. Nabbus, "NIST Special Publication 800-63-1, INFORMATION SECURITY", , <http://csrc.nist.gov/publications/>.
[OMAP]
Huff, J., Schlacht, D., Nadalin, A., Simmons, J., Rosenberg, P., Madsen, P., Ace, T., Rickelton-Abdi, C., and B. Boyer, "Online Multimedia Authorization Protocol: 인터넷 멀티미디어 리소스에 대한 승인된 접근을 위한 산업 표준", , <https://www.svta.org/product/online-multimedia-authorization-protocol/>.
[OpenID.Connect]
Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and C. Mortimore, "정오표 세트 2를 통합한 OpenID Connect Core 1.0", , <https://openid.net/specs/openid-connect-core-1_0.html>.
[OpenID.Discovery]
Sakimura, N., Bradley, J., Jones, M., and E. Jay, "정오표 세트 2를 통합한 OpenID Connect Discovery 1.0", , <https://openid.net/specs/openid-connect-discovery-1_0.html>.
[OpenID.Messages]
Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., Mortimore, C., and E. Jay, "OpenID Connect Messages 1.0", , <http://openid.net/specs/openid-connect-messages-1_0.html>.
[owasp_redir]
"OWASP Cheat Sheet Series - 검증되지 않은 리디렉션 및 포워드", , <https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html>.
[RFC6265]
Barth, A., "HTTP 상태 관리 메커니즘", RFC 6265, DOI 10.17487/RFC6265, , <https://www.rfc-editor.org/info/rfc6265>.
[RFC6819]
Lodderstedt, T., Ed., McGloin, M., and P. Hunt, "OAuth 2.0 위협 모델 및 보안 고려사항", RFC 6819, DOI 10.17487/RFC6819, , <https://www.rfc-editor.org/info/rfc6819>.
[RFC7009]
Lodderstedt, T., Ed., Dronia, S., and M. Scurtescu, "OAuth 2.0 토큰 취소", RFC 7009, DOI 10.17487/RFC7009, , <https://www.rfc-editor.org/info/rfc7009>.
[RFC7519]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, , <https://www.rfc-editor.org/info/rfc7519>.
[RFC7591]
Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol", RFC 7591, DOI 10.17487/RFC7591, , <https://www.rfc-editor.org/info/rfc7591>.
[RFC7592]
Richer, J., Ed., Jones, M., Bradley, J., and M. Machulak, "OAuth 2.0 Dynamic Client Registration Management Protocol", RFC 7592, DOI 10.17487/RFC7592, , <https://www.rfc-editor.org/info/rfc7592>.
[RFC7636]
Sakimura, N., Ed., Bradley, J., and N. Agarwal, "OAuth 공개 클라이언트의 Proof Key for Code Exchange", RFC 7636, DOI 10.17487/RFC7636, , <https://www.rfc-editor.org/info/rfc7636>.
[RFC7662]
Richer, J., Ed., "OAuth 2.0 토큰 인트로스펙션", RFC 7662, DOI 10.17487/RFC7662, , <https://www.rfc-editor.org/info/rfc7662>.
[RFC8414]
Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 권한 부여 서버 메타데이터", RFC 8414, DOI 10.17487/RFC8414, , <https://www.rfc-editor.org/info/rfc8414>.
[RFC8628]
Denniss, W., Bradley, J., Jones, M., and H. Tschofenig, "OAuth 2.0 장치 권한 부여 그랜트", RFC 8628, DOI 10.17487/RFC8628, , <https://www.rfc-editor.org/info/rfc8628>.
[RFC8705]
Campbell, B., Bradley, J., Sakimura, N., and T. Lodderstedt, "OAuth 2.0 상호 TLS 클라이언트 인증 및 인증서 바인딩 접근 토큰", RFC 8705, DOI 10.17487/RFC8705, , <https://www.rfc-editor.org/info/rfc8705>.
[RFC8707]
Campbell, B., Bradley, J., and H. Tschofenig, "OAuth 2.0의 리소스 지시자", RFC 8707, DOI 10.17487/RFC8707, , <https://www.rfc-editor.org/info/rfc8707>.
[RFC9068]
Bertocci, V., "OAuth 2.0 접근 토큰을 위한 JSON Web Token (JWT) 프로파일", RFC 9068, DOI 10.17487/RFC9068, , <https://www.rfc-editor.org/info/rfc9068>.
[RFC9126]
Lodderstedt, T., Campbell, B., Sakimura, N., Tonge, D., and F. Skokan, "OAuth 2.0 Pushed Authorization Requests", RFC 9126, DOI 10.17487/RFC9126, , <https://www.rfc-editor.org/info/rfc9126>.
[RFC9396]
Lodderstedt, T., Richer, J., and B. Campbell, "OAuth 2.0 Rich Authorization Requests", RFC 9396, DOI 10.17487/RFC9396, , <https://www.rfc-editor.org/info/rfc9396>.
[RFC9449]
Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/info/rfc9449>.
[RFC9470]
Bertocci, V. and B. Campbell, "OAuth 2.0 Step Up Authentication Challenge Protocol", RFC 9470, DOI 10.17487/RFC9470, , <https://www.rfc-editor.org/info/rfc9470>.
[W3C.REC-html401-19991224]
Hors, A. L., Ed., Raggett, D., Ed., and I. Jacobs, Ed., "HTML 4.01 명세", W3C REC REC-html401-19991224, W3C REC-html401-19991224, , <https://www.w3.org/TR/1999/REC-html401-19991224/>.

Appendix A. Augmented Backus-Naur Form (ABNF) 구문

이 절은 [RFC5234]의 표기법을 사용하여 이 명세에서 정의된 요소에 대한 Augmented Backus-Naur Form (ABNF) 구문 설명을 제공한다. 아래 ABNF는 Unicode 코드 포인트 [W3C.REC-xml-20081126]를 기준으로 정의되며, 이러한 문자는 일반적으로 UTF-8로 인코딩된다. 요소는 처음 정의된 순서로 제시된다.

다음 정의 중 일부는 [RFC3986]의 "URI-reference" 정의를 사용한다.

다음 정의 중 일부는 이러한 공통 정의를 사용한다:

VSCHAR     = %x20-7E
NQCHAR     = %x21 / %x23-5B / %x5D-7E
NQSCHAR    = %x20-21 / %x23-5B / %x5D-7E

A.1. "client_id" 구문

client_id 요소는 Section 2.4.1에 정의되어 있다:

client-id     = *VSCHAR

A.2. "client_secret" 구문

client_secret 요소는 Section 2.4.1에 정의되어 있다:

client-secret = *VSCHAR

A.3. "response_type" 구문

response_type 요소는 Section 4.1.1Section 6.4에 정의되어 있다:

response-type = response-name *( SP response-name )
response-name = 1*response-char
response-char = "_" / DIGIT / ALPHA

A.4. "scope" 구문

scope 요소는 Section 1.4.1에 정의되어 있다:

 scope       = scope-token *( SP scope-token )
 scope-token = 1*NQCHAR

A.5. "state" 구문

state 요소는 Section 4.1.1, Section 4.1.2, 및 Section 4.1.2.1에 정의되어 있다:

 state      = 1*VSCHAR

A.6. "redirect_uri" 구문

redirect_uri 요소는 Section 4.1.1Section 4.1.3에 정의되어 있다:

 redirect-uri      = URI-reference

A.7. "error" 구문

error 요소는 Section 4.1.2.1, Section 3.2.4, 및 Section 5.3에 정의되어 있다:

 error             = 1*NQSCHAR

A.8. "error_description" 구문

error_description 요소는 Section 4.1.2.1, Section 3.2.4, 및 Section 5.3에 정의되어 있다:

 error-description = 1*NQSCHAR

A.9. "error_uri" 구문

error_uri 요소는 Section 4.1.2.1, Section 3.2.4, 및 Section 5.3에 정의되어 있다:

 error-uri         = URI-reference

A.10. "grant_type" 구문

grant_type 요소는 Section 3.2.2에 정의되어 있다:

 grant-type = grant-name / URI-reference
 grant-name = 1*name-char
 name-char  = "-" / "." / "_" / DIGIT / ALPHA

A.11. "code" 구문

code 요소는 Section 4.1.3에 정의되어 있다:

 code       = 1*VSCHAR

A.12. "access_token" 구문

access_token 요소는 Section 3.2.3에 정의되어 있다:

 access-token = 1*VSCHAR

A.13. "token_type" 구문

token_type 요소는 Section 3.2.3Section 6.1에 정의되어 있다:

 token-type = type-name / URI-reference
 type-name  = 1*name-char
 name-char  = "-" / "." / "_" / DIGIT / ALPHA

A.14. "expires_in" 구문

expires_in 요소는 Section 3.2.3에 정의되어 있다:

 expires-in = 1*DIGIT

A.15. "refresh_token" 구문

refresh_token 요소는 Section 3.2.3Section 4.3에 정의되어 있다:

 refresh-token = 1*VSCHAR

A.16. 엔드포인트 매개변수 구문

새 엔드포인트 매개변수의 구문은 Section 6.2에 정의되어 있다:

 param-name = 1*name-char
 name-char  = "-" / "." / "_" / DIGIT / ALPHA

A.17. "code_verifier" 구문

code_verifier의 ABNF는 다음과 같다.

code-verifier = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39

A.18. "code_challenge" 구문

code_challenge의 ABNF는 다음과 같다.

code-challenge = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39

Appendix B. application/x-www-form-urlencoded 미디어 타입 사용

[RFC6749] 발행 당시, application/x-www-form-urlencoded 미디어 타입은 [W3C.REC-html401-19991224]의 Section 17.13.4에 정의되어 있었지만, IANA MIME Media Types 레지스트리 (http://www.iana.org/assignments/media-types)에는 등록되어 있지 않았다. 또한 그 정의는 비 US-ASCII 문자를 고려하지 않으므로 불완전하다.

이 미디어 타입을 사용하여 콘텐츠를 생성할 때 이러한 결함을 해결하기 위해, 이름과 값은 먼저 UTF-8 문자 인코딩 스킴 [RFC3629]을 사용하여 인코딩되어야 한다. 그런 다음 결과 옥텟 시퀀스는 [W3C.REC-html401-19991224]에 정의된 이스케이프 규칙을 사용하여 추가로 인코딩되어야 한다.

이 미디어 타입을 사용하는 콘텐츠에서 데이터를 파싱할 때, 이름/값 인코딩을 되돌린 결과로 얻은 이름과 값은 옥텟 시퀀스로 취급되어야 하며, UTF-8 문자 인코딩 스킴을 사용하여 디코딩되어야 한다.

예를 들어, 여섯 개의 Unicode 코드 포인트 (1) U+0020 (SPACE), (2) U+0025 (PERCENT SIGN), (3) U+0026 (AMPERSAND), (4) U+002B (PLUS SIGN), (5) U+00A3 (POUND SIGN), 및 (6) U+20AC (EURO SIGN)로 구성된 값은 아래 옥텟 시퀀스(16진수 표기 사용)로 인코딩된다:

20 25 26 2B C2 A3 E2 82 AC

그리고 콘텐츠에서는 다음과 같이 표현된다:

+%25%26%2B%C2%A3%E2%82%AC

Appendix C. 직렬화

이 명세의 여러 메시지는 아래에 설명된 방법 중 하나를 사용하여 직렬화된다. 이 절은 이러한 직렬화 방법의 구문을 설명하며, 다른 절은 언제 그것들을 사용할 수 있고 사용해야 하는지를 설명한다. 모든 방법을 모든 메시지에 사용할 수 있는 것은 아님에 유의한다.

C.1. 쿼리 문자열 직렬화

Query String Serialization을 사용하여 매개변수를 직렬화하기 위해, 클라이언트는 [WHATWG.URL]이 정의한 application/x-www-form-urlencoded 형식을 사용하여 URL의 쿼리 구성 요소에 매개변수와 값을 추가함으로써 문자열을 구성한다. Query String Serialization은 일반적으로 HTTP GET 요청에서 사용된다.

C.2. 폼 인코딩 직렬화

매개변수와 그 값은 Appendix B가 정의한 application/x-www-form-urlencoded 형식을 사용하여 HTTP 요청의 엔터티 본문에 매개변수 이름과 값을 추가함으로써 Form Serialized된다. Form Serialization은 일반적으로 HTTP POST 요청에서 사용된다.

C.3. JSON 직렬화

매개변수는 각 매개변수를 최상위 구조 수준에 추가하여 JSON [RFC8259] 객체 구조로 직렬화된다. 매개변수 이름과 문자열 값은 JSON 문자열로 표현된다. 숫자 값은 JSON 숫자로 표현된다. 불리언 값은 JSON 불리언으로 표현된다. 생략된 매개변수와 값이 없는 매개변수는 달리 명시되지 않는 한 객체에서 생략되고 JSON null 값으로 표현되지 않는 것이 좋다. 매개변수는 값으로 JSON 객체 또는 JSON 배열을 가질 수 있다. 매개변수의 순서는 중요하지 않으며 달라질 수 있다.

Appendix D. 확장

아래는 발행 시점에 잘 확립된 확장의 목록이다:

Appendix E. 감사의 말

이 명세는 OAuth Working Group의 작업이며, 그 출발점은 다음 명세들의 내용을 기반으로 했다: OAuth 2.0 Authorization Framework (RFC 6749), OAuth 2.0 for Native Apps (RFC 8252), OAuth Security Best Current Practice, 및 OAuth 2.0 for Browser-Based Apps. 편집자들은 이 명세가 기반으로 하는 그러한 명세들의 작성에 관여한 모든 사람에게 감사를 표한다.

편집자들은 또한 이 명세 버전의 형성에 도움이 된 아이디어, 피드백, 수정 및 문구를 제공한 다음 개인들에게도 감사를 표한다: Andrii Deinega, Bob Hamburg, Brian Campbell, Daniel Fett, Deng Chao, Emelia Smith, Falko, Filip Skokan, Joseph Heenan, Justin Richer, Karsten Meyer zu Selhausen, Michael Jones, Michael Peck, Roberto Polli, Tim Würtele and Vittorio Bertocci.

이 명세에 대한 논의는 2021년과 2022년 OAuth Security Workshop에서도 이루어졌다. 저자들은 협업과 커뮤니티 의견에 도움이 되는 행사를 주최한 워크숍 주최자(Guido Schmitz, Steinar Noem, and Daniel Fett)에게 감사를 표한다.

Appendix F. 문서 이력

[[ 최종 명세에서 제거될 예정 ]]

-15

-14

-13

-12

-11

-10

-09

-08

-07

-06

-05

-04

-03

-02

-01

-00

저자 주소

Dick Hardt
Hellō
Aaron Parecki
Okta
Torsten Lodderstedt
SPRIND