RFC 9700 OAuth 2.0 보안 BCP 2025년 1월
Lodderstedt 외 최신 모범 사례 [페이지]
스트림:
인터넷 엔지니어링 태스크 포스 (IETF)
RFC:
9700
BCP:
240
갱신:
6749, 6750, 6819
범주:
최신 모범 사례
발행일:
ISSN:
2070-1721
저자:
T. Lodderstedt
SPRIND
J. Bradley
Yubico
A. Labunets
독립 연구자
D. Fett
Authlete

RFC 9700

OAuth 2.0 보안을 위한 최신 모범 사례

초록

이 문서는 OAuth 2.0에 대한 현재 최선의 보안 실무를 설명한다. 이는 RFC 6749, RFC 6750 및 RFC 6819에서 제시한 위협 모델과 보안 권고를 실제 OAuth 2.0이 공개된 이후 축적된 실제 경험을 반영하도록 갱신하고 확장하며, OAuth 2.0의 더 광범위한 적용으로 인해 관련성이 생긴 새로운 위협을 다룬다. 또한 덜 안전하거나 심지어 안전하지 않은 것으로 간주되는 일부 동작 방식을 폐기한다.

이 메모의 상태

이 메모는 인터넷 최신 모범 사례를 문서화한다.

이 문서는 인터넷 엔지니어링 태스크 포스 (IETF)의 산출물이다. 이는 IETF 커뮤니티의 합의를 나타낸다. 이는 공개 검토를 거쳤으며 인터넷 엔지니어링 운영 그룹 (IESG)의 발행 승인을 받았다. BCP에 대한 추가 정보는 RFC 7841의 2절에서 확인할 수 있다.

이 문서의 현재 상태, 정오표 및 이에 대한 피드백 제공 방법에 관한 정보는 https://www.rfc-editor.org/info/rfc9700에서 얻을 수 있다.

목차

1. 소개

[RFC6749][RFC6750]로 공개된 이후, OAuth 2.0(이 문서에서는 간단히 "OAuth"라고 함)은 시장에서 엄청난 관심을 얻었으며 API 보호를 위한 표준이자 OpenID Connect [OpenID.Core]를 사용하는 연합 로그인의 기반이 되었다. OAuth는 다양한 시나리오와 서로 다른 종류의 배포에서 사용되지만, 다음과 같은 과제를 관찰할 수 있다.

이 문서는 이러한 과제를 해결하기 위한 갱신된 보안 권고사항을 제공한다. 이는 OAuth 2.0 [RFC6749] 및 OpenID Connect [OpenID.Core]와 같은 기존 명세에 정의된 것을 넘어서는 새로운 요구사항을 도입하고, 덜 안전하거나 심지어 안전하지 않은 것으로 간주되는 일부 동작 방식을 폐기한다. 그러나 이 문서는 [RFC6749], [RFC6750][RFC6819]에서 제시한 보안 권고를 대체하지 않고, 이러한 문서들을 보완한다.

당연히 모든 기존 생태계와 구현이 새로운 요구사항과 호환되는 것은 아니며, 이 문서에 설명된 모범 사례를 따르면 상호운용성이 깨질 수 있다. 그럼에도 불구하고 구현자가 가능한 한 빨리 자신의 구현과 생태계를 업그레이드하는 것이 RECOMMENDED된다.

개발 중인 OAuth 2.1 [OAUTH-V2.1]은 이 문서의 보안 권고사항을 통합할 것이다.

1.1. 구조

이 문서의 나머지 부분은 다음과 같이 구성된다. Section 2는 모든 OAuth 구현자에게 가장 중요한 모범 사례를 요약한다. Section 3은 갱신된 OAuth 공격자 모델을 제시한다. Section 4는 실제 환경에서 발견될 수 있는 위협과 구현 문제에 대한 상세한 분석을 잠재적 대응책에 대한 논의와 함께 제공한다(작성 시점 기준).

1.2. 관례와 용어

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

이 명세는 OAuth 2.0 [RFC6749]에서 정의한 "access token", "authorization endpoint", "authorization grant", "authorization server", "client", "client identifier" (client ID), "protected resource", "refresh token", "resource owner", "resource server" 및 "token endpoint"라는 용어를 사용한다.

"open redirector"는 쿼리 매개변수에서 얻은 임의의 URI로 사용자의 브라우저를 전달하는 웹 서버의 엔드포인트이다.

2. 모범 사례

이 절은 작성 시점에 모범 사례로 간주되는 핵심 보안 메커니즘과 조치들을 설명한다. 이러한 보안 메커니즘과 조치에 대한 세부사항(상세한 공격 설명 포함) 및 덜 일반적으로 사용되는 옵션에 대한 요구사항은 Section 4에서 제공된다.

2.1. 리디렉션 기반 흐름 보호

클라이언트 리디렉션 URI를 사전 등록된 URI와 비교할 때, 인가 서버는 네이티브 앱의 localhost 리디렉션 URI에 있는 포트 번호를 제외하고는 정확한 문자열 일치를 사용해야 MUST 한다 (Section 4.1.3 참조). 이 조치는 인가 코드와 액세스 토큰의 유출 방지에 기여한다(Section 4.1 참조). 또한 믹스업 공격을 탐지하는 데 도움이 될 수도 있다 (Section 4.4 참조).

클라이언트와 인가 서버는 Section 4.11에 설명된 것처럼 쿼리 매개변수에서 얻은 임의의 URI로 사용자의 브라우저를 전달하는 URL(open redirector)을 노출해서는 MUST NOT 된다. 오픈 리디렉터는 인가 코드와 액세스 토큰의 유출을 가능하게 할 수 있다.

클라이언트는 Cross-Site Request Forgery (CSRF)를 방지해야 MUST 한다. 이 맥락에서 CSRF는 인가 서버가 아니라 악의적인 제3자로부터 발생하는 리디렉션 엔드포인트에 대한 요청을 의미한다 (자세한 내용은 Section 4.4.1.8 of [RFC6819] 참조). 인가 서버가 Proof Key for Code Exchange (PKCE) [RFC7636]를 지원함을 확인한 클라이언트는 PKCE가 제공하는 CSRF 보호에 의존할 수 MAY 있다. OpenID Connect 흐름에서는 nonce 매개변수가 CSRF 보호를 제공한다. 그렇지 않은 경우, 사용자 에이전트에 안전하게 바인딩된 state 매개변수에 담긴 일회용 CSRF 토큰을 CSRF 보호에 사용해야 MUST 한다 (Section 4.7.1 참조).

OAuth 클라이언트가 둘 이상의 인가 서버와 상호작용할 수 있는 경우, 믹스업 공격(Section 4.4 참조)에 대한 방어가 REQUIRED된다. 이를 위해 클라이언트는 SHOULD

  • [RFC9207]에 따라 iss 매개변수를 대응책으로 사용하거나,
  • 인가 응답의 iss 값([OpenID.Core]의 ID Token에 있는 iss 클레임 또는 [OpenID.JARM] 응답의 값 등)을 기반으로 하는 대체 대응책을 사용하고, 그 값을 [RFC9207]에 설명된 대로 처리해야 한다.

이러한 옵션이 없는 경우, 클라이언트는 대신 Section 4.4.2에 설명된 것처럼 인가 엔드포인트와 토큰 엔드포인트를 식별하기 위해 서로 다른 리디렉션 URI를 사용할 수 MAY 있다.

사용자 자격 증명을 포함할 가능성이 있는 요청을 리디렉션하는 인가 서버는 이러한 사용자 자격 증명이 실수로 전달되지 않도록 해야 MUST 한다(자세한 내용은 Section 4.12 참조).

2.1.1. 인가 코드 그랜트

클라이언트는 다음 옵션 중 하나를 사용하여 인가 코드 주입 공격(Section 4.5 참조)과 인가 코드의 오용을 방지해야 MUST 한다.

  • 공개 클라이언트는 이를 위해 Section 4.5.3.1에서 동기가 설명된 것처럼 PKCE [RFC7636]를 사용해야 MUST 한다.
  • 기밀 클라이언트의 경우, Section 4.5.3.1에 설명된 것처럼 인가 코드의 오용과 주입에 대한 강력한 보호를 제공하므로 PKCE [RFC7636] 사용이 RECOMMENDED된다. 또한 부수 효과로, Section 4.7.1에 설명된 강력한 공격자가 존재하는 경우에도 CSRF를 방지한다.
  • Section 4.5.3.2에 설명된 추가 예방조치를 적용하면, 기밀 OpenID Connect [OpenID.Core] 클라이언트는 대신 nonce 매개변수와 ID Token의 해당 Claim을 사용할 수 MAY 있다.

어떤 경우에도 PKCE challenge 또는 OpenID Connect nonce는 트랜잭션별이어야 하며, 트랜잭션이 시작된 클라이언트와 사용자 에이전트에 안전하게 바인딩되어야 MUST 한다. 인가 서버는 PKCE challenge 또는 OpenID Connect nonce에 상수 값이 사용되는 것을 탐지하고 방지하기 위해 합리적인 노력을 기울이는 것이 권장된다.

참고: PKCE는 네이티브 앱을 보호하기 위한 메커니즘으로 설계되었지만, 이 권고는 웹 애플리케이션을 포함한 모든 종류의 OAuth 클라이언트에 적용된다.

PKCE를 사용할 때 클라이언트는 인가 요청에서 PKCE verifier를 노출하지 않는 PKCE code challenge methods를 사용해야 SHOULD 한다. 그렇지 않으면 인가 요청을 읽을 수 있는 공격자(Section 3의 Attacker (A4) 참조)가 PKCE가 제공하는 보안을 깨뜨릴 수 있다. 현재 S256이 그러한 유일한 방법이다.

인가 서버는 PKCE [RFC7636]를 지원해야 MUST 한다.

클라이언트가 인가 요청에서 유효한 PKCE code_challenge 매개변수를 보내는 경우, 인가 서버는 토큰 엔드포인트에서 code_verifier의 올바른 사용을 강제해야 MUST 한다.

인가 서버는 code_verifier 매개변수를 포함한 토큰 요청을 인가 요청에 code_challenge 매개변수가 있었던 경우에만 허용함으로써 PKCE 다운그레이드 공격을 완화해야 MUST 한다. 자세한 내용은 Section 4.8.2를 참조한다.

인가 서버는 PKCE 지원을 탐지할 수 있는 방법을 제공해야 MUST 한다. 인가 서버가 Authorization Server Metadata [RFC8414]에 지원되는 PKCE challenge methods를 포함하는 code_challenge_methods_supported 요소(클라이언트가 PKCE 지원을 탐지하는 데 사용할 수 있음)를 공개하는 것이 RECOMMENDED된다. 인가 서버는 대신 배포별 방식으로 인가 서버의 PKCE 지원을 보장하거나 확인하는 방법을 제공할 수 MAY 있다.

2.1.2. 암시적 그랜트

암시적 그랜트(response type token) 및 인가 서버가 인가 응답에서 액세스 토큰을 발급하게 하는 다른 response type은 Sections 4.1, 4.2, 4.34.6에 설명된 것처럼 액세스 토큰 유출 및 액세스 토큰 리플레이에 취약하다.

또한 액세스 토큰이 인가 응답에서 발급될 때, Section 2.2에서 권고한 것처럼 액세스 토큰을 특정 클라이언트에 바인딩하기 위한 표준화된 발신자 제한 방법은 존재하지 않는다. 이는 공격자가 유출되거나 탈취한 액세스 토큰을 리소스 엔드포인트에서 사용할 수 있음을 의미한다.

이러한 문제를 피하기 위해, 클라이언트는 인가 응답에서의 액세스 토큰 주입이 방지되고 앞서 언급한 토큰 유출 벡터가 완화되지 않는 한, 암시적 그랜트(response type token) 또는 인가 응답에서 액세스 토큰을 발급하는 다른 response type을 사용하지 않아야 SHOULD NOT 한다.

클라이언트는 대신 Section 2.1.1에 명시된 response type code(즉, authorization code grant type) 또는 code id_token response type과 같이 인가 서버가 토큰 응답에서 액세스 토큰을 발급하게 하는 다른 response type을 사용해야 SHOULD 한다. 이를 통해 인가 서버는 공격자의 리플레이 시도를 탐지할 수 있으며, 액세스 토큰이 URL에 노출되지 않으므로 일반적으로 공격 표면이 줄어든다. 또한 인가 서버가 발급된 토큰에 발신자 제한을 적용할 수 있게 한다 (Section 2.2 참조).

2.2. 토큰 리플레이 방지

2.2.1. 액세스 토큰

발신자 제한 액세스 토큰은 액세스 토큰의 적용 범위를 특정 발신자로 한정한다. 이 발신자는 해당 토큰이 수신자 (예: 리소스 서버)에서 수락되기 위한 전제조건으로 특정 비밀에 대한 지식을 입증해야 한다.

인가 서버와 리소스 서버는 탈취되거나 유출된 액세스 토큰의 오용을 방지하기 위해 OAuth 2.0을 위한 상호 TLS [RFC8705] 또는 OAuth 2.0 Demonstrating Proof of Possession (DPoP) [RFC9449]와 같은 액세스 토큰 발신자 제한 메커니즘(Section 4.10.1 참조)을 사용해야 SHOULD 한다.

2.2.2. 갱신 토큰

공개 클라이언트를 위한 갱신 토큰은 발신자 제한이 적용되거나 Section 4.14에 설명된 갱신 토큰 회전을 사용해야 MUST 한다. [RFC6749]는 이미 기밀 클라이언트를 위한 갱신 토큰은 해당 토큰이 발급된 클라이언트만 사용할 수 있다고 요구한다.

2.3. 액세스 토큰 권한 제한

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

특히 액세스 토큰은 특정 리소스 서버로, 또는 그것이 가능하지 않은 경우 소수의 리소스 서버 집합으로 대상 제한되어야 SHOULD 한다. 이를 실행하기 위해 인가 서버는 액세스 토큰을 특정 리소스 서버와 연결하고, 모든 리소스 서버는 각 요청에 대해 그 요청과 함께 전송된 액세스 토큰이 해당 특정 리소스 서버에서 사용되도록 의도되었는지 검증해야 한다. 그렇지 않다면 리소스 서버는 해당 요청의 처리를 거부해야 MUST 한다. [RFC9068]에 정의된 aud 클레임은 액세스 토큰의 대상 제한에 사용될 수 MAY 있다. 클라이언트와 인가 서버는 접근하려는 리소스 서버를 결정하기 위해 각각 [RFC6749][RFC8707]에 명시된 scope 또는 resource 매개변수를 활용할 수 MAY 있다.

추가로 액세스 토큰은 특정 리소스와 리소스 서버 또는 리소스에 대한 작업으로 제한되어야 SHOULD 한다. 이를 실행하기 위해 인가 서버는 액세스 토큰을 해당 리소스 및 작업과 연결하고, 모든 리소스 서버는 각 요청에 대해 그 요청과 함께 전송된 액세스 토큰이 특정 리소스의 특정 작업에 사용되도록 의도되었는지 검증해야 한다. 그렇지 않다면 리소스 서버는 해당 요청의 처리를 거부해야 한다. 클라이언트와 인가 서버는 이러한 리소스 및/또는 작업을 결정하기 위해 [RFC6749]에 명시된 scope 매개변수와 [RFC9396]에 명시된 authorization_details를 활용할 수 MAY 있다.

2.4. 리소스 소유자 비밀번호 자격 증명 그랜트

리소스 소유자 비밀번호 자격 증명 그랜트 [RFC6749]는 사용해서는 MUST NOT 된다. 이 그랜트 유형은 리소스 소유자의 자격 증명을 클라이언트에 안전하지 않게 노출한다. 클라이언트가 선의라 하더라도 이 그랜트를 사용하면 공격 표면이 증가하고(즉, 자격 증명이 인가 서버뿐 아니라 더 많은 곳에서 유출될 수 있음), 사용자에게 인가 서버가 아닌 곳에 자신의 자격 증명을 입력하도록 학습시키는 결과를 낳는다.

또한 리소스 소유자 비밀번호 자격 증명 그랜트는 2단계 인증 및 여러 사용자 상호작용 단계가 필요한 인증 프로세스와 함께 동작하도록 설계되지 않았다. 암호학적 자격 증명을 사용하는 인증 (cf. WebCrypto [W3C.WebCrypto], WebAuthn [W3C.WebAuthn])은 일반적으로 특정 웹 출처에 바인딩되므로 이 그랜트 유형으로 구현하는 것이 불가능할 수 있다.

2.5. 클라이언트 인증

인가 서버는 특정 배포에서 클라이언트에 대한 자격 증명의 발급/등록 프로세스를 수립하고 그러한 자격 증명의 기밀성을 보장하는 것이 가능하다면, 클라이언트 인증을 강제해야 SHOULD 한다.

클라이언트 인증에는 OAuth 2.0을 위한 상호 TLS [RFC8705] 또는 [RFC7521][RFC7523]에 따른 서명된 JWT ("Private Key JWT")와 같은 비대칭 암호화를 사용하는 것이 RECOMMENDED된다. 후자는 [OpenID.Core]에서 클라이언트 인증 방법 private_key_jwt로 정의된다). 클라이언트 인증에 비대칭 암호화를 사용하는 경우, 인가 서버는 민감한 대칭 키를 저장할 필요가 없으므로 이러한 방법은 키 유출에 대해 더 강건하다.

2.6. 기타 권고사항

OAuth Authorization Server Metadata [RFC8414]의 사용은 OAuth 배포의 보안을 향상시키는 데 도움이 될 수 있다.

  • 이는 보안 기능 및 기타 새로운 OAuth 기능이 준수 소프트웨어 라이브러리에 의해 자동으로 활성화될 수 있도록 보장한다.
  • 이는 잘못 구성된 엔드포인트 URL(공격자에게 속할 수 있음) 또는 잘못 구성된 보안 기능과 같은 오구성 가능성을 줄인다.
  • 이는 암호학적 키의 회전을 용이하게 하고 암호학적 민첩성을 보장하는 데 도움이 될 수 있다.

따라서 인가 서버가 [RFC8414]에 따라 OAuth Authorization Server Metadata를 공개하고, 클라이언트가 이 Authorization Server Metadata를 (사용 가능한 경우) 사용하여 자신을 구성하는 것이 RECOMMENDED된다.

Section 4.15.1에 설명된 조건에서, 인가 서버는 클라이언트가 자신의 client_id 또는 진짜 리소스 소유자와 혼동을 일으킬 수 있는 다른 클레임에 영향을 미치도록 허용해서는 SHOULD NOT 된다.

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

인가 응답은 암호화되지 않은 네트워크 연결을 통해 전송되어서는 MUST NOT 된다. 이를 위해 인가 서버는 Section 7.3 of [RFC8252]에 설명된 것처럼 loopback interface redirection을 사용하는 네이티브 클라이언트를 제외하고, http 스킴을 사용하는 리디렉션 URI를 허용해서는 MUST NOT 된다.

인가 응답이 HTTP 리디렉션 대신 postMessage [WHATWG.postmessage_api]와 같은 브라우저 내 통신 기법으로 전송되는 경우, 브라우저 내 메시지의 시작자와 수신자는 모두 Section 4.17에 설명된 대로 엄격하게 검증되어야 MUST 한다.

브라우저 기반 클라이언트를 지원하기 위해, Token Endpoint, Authorization Server Metadata Endpoint, jwks_uri Endpoint 및 Dynamic Client Registration Endpoint를 포함하여 이러한 클라이언트가 직접 접근하는 엔드포인트는 Cross-Origin Resource Sharing (CORS) [WHATWG.CORS] 사용을 지원할 수 MAY 있다. 그러나 클라이언트는 authorization endpoint에 직접 접근하지 않고 사용자 에이전트를 해당 엔드포인트로 리디렉션하므로, authorization endpoint에서는 CORS를 지원해서는 MUST NOT 된다.

3. 갱신된 OAuth 2.0 공격자 모델

[RFC6819]에서는 OAuth 배포가 보호되어야 하는 위협을 설명하는 위협 모델을 제시한다. 그러면서 [RFC6819]는 공격자와 그 역량에 관한 특정 가정을 두며, 즉 암묵적으로 공격자 모델을 설정한다. 다음에서는 이 공격자 모델을 명시적으로 만들고, 여러 당사자가 관련된 잠재적으로 동적인 관계 (Section 1에서 설명한 것처럼)를 고려하고, 새로운 유형의 공격자를 포함하며, 공격자 모델을 더 명확하게 정의하도록 갱신하고 확장한다.

이 문서의 목표는 인가 서버에서 리소스 소유자(사용자 에이전트 포함)의 인가와 이후 리소스 서버에서의 액세스 토큰 사용이, 적어도 다음 공격자에 대해 실질적으로 가능한 한 보호되도록 보장하는 것이다.

(A1)

브라우저와 서버를 포함하여 ("정직한" 엔드포인트 외에) 임의 개수의 네트워크 엔드포인트를 설정하고 운영할 수 있는 웹 공격자. 웹 공격자는 리소스 소유자가 방문하는 웹사이트를 설정하고, 자신의 사용자 에이전트를 운영하며, 프로토콜에 참여할 수 있다.

특히 웹 공격자는 인가 서버에 등록된 OAuth 클라이언트를 운영할 수 있으며, 리소스 소유자와 다른 리소스 소유자가 ("정직한" 서버와 병렬로) 사용할 수 있는 자신만의 인가 서버와 리소스 서버를 운영할 수 있다.

또한 웹 공격자가 언제든지 공격자가 선택한 임의의 URI로 사용자가 브라우저를 탐색하도록 유인할 수 있다고 가정해야 한다. 실제로 이는 예를 들어 광고 네트워크에 악성 광고를 주입하거나 정상처럼 보이는 이메일을 보내는 등 여러 방식으로 달성될 수 있다.

웹 공격자는 자신의 사용자 자격 증명과 이전에 알게 된 모든 비밀을 사용하여 새 메시지를 만들 수 있다. 예를 들어, 웹 공격자가 잘못 구성된 리디렉션 URI를 통해 사용자의 인가 코드를 알게 되면, 웹 공격자는 그 코드를 액세스 토큰으로 교환하려고 시도할 수 있다.

그러나 이들은 자신을 대상으로 하지 않은 메시지 (예: 공격자가 제어하지 않는 인가 서버의 URL로 전송된 메시지)를 읽거나 조작할 수 없다.

(A2)

프로토콜 참여자들이 통신하는 네트워크에 대해 추가로 완전한 제어권을 가진 네트워크 공격자. 이들은 메시지가 암호학적 방법(예: TLS)으로 적절히 보호되는 경우를 제외하고, 메시지를 도청하고, 조작하고, 위조할 수 있다. 네트워크 공격자는 임의의 메시지도 차단할 수 있다.

웹 공격자의 예는 인터넷 서비스 제공자의 고객일 수 있는 반면, 네트워크 공격자는 인터넷 서비스 제공자 자체, ARP spoofing을 사용하는 공용 (Wi-Fi) 네트워크의 공격자, 또는 예를 들어 인터넷 교환 지점에 접근할 수 있는 국가 후원 공격자일 수 있다.

앞서 언급한 공격자 (A1)(A2)는 OAuth에 대한 형식 분석 작업 [arXiv.1601.01229]에서 사용된 공격자 모델을 따른다. 이는 최소 공격자 모델이다. 구현자는 자신의 OAuth 구현 환경에 존재할 수 있는 모든 유형의 공격자를 고려해야 MUST 한다. 예를 들어, [arXiv.1901.11520]에서는 토큰 엔드포인트를 완전히 제어하는 공격자를 포함하는 매우 강력한 공격자 모델이 사용된다. 이는 생태계의 엔드포인트 오구성 가능성의 영향을 모델링하며, Section 2.6에 설명된 인가 서버 메타데이터를 사용하면 피할 수 있다. 따라서 이러한 공격자는 여기에는 나열하지 않는다.

그러나 OAuth에 대한 이전 공격들은 특히 다음 유형의 공격자가 관련이 있음을 보여주었다.

(A3)

인가 응답의 내용을 읽을 수는 있지만 수정할 수는 없는 공격자 (즉, 인가 응답이 공격자에게 유출될 수 있음).

이러한 공격의 예에는 오픈 리디렉터 공격과 믹스업 공격(Section 4.4 참조)이 포함되며, 여기서 클라이언트는 자격 증명을 공격자가 제어하는 인가 서버로 보내도록 속는다.

또한 여기에는 다음을 악용하는 공격이 포함된다.

  • 리디렉션 URI의 불충분한 검사 (Section 4.1 참조);
  • 서로 다른 앱이 같은 URI에 자신을 등록할 수 있는 모바일 운영체제상의 문제; 및
  • 브라우저(기록), 프록시 서버 및 운영체제에 저장/기록된 URL.
(A4)

인가 요청의 내용을 읽을 수는 있지만 수정할 수는 없는 공격자(즉, 인가 요청이 위와 같은 방식으로 공격자에게 유출될 수 있음).

(A5)

인가 서버가 발급한 액세스 토큰을 획득할 수 있는 공격자. 예를 들어, 리소스 서버가 공격자에게 손상될 수 있고, 오구성으로 인해 액세스 토큰이 공격자가 제어하는 리소스 서버로 전송될 수 있으며, 또는 사회공학을 사용하여 리소스 소유자가 공격자가 제어하는 리소스 서버를 사용하도록 만들 수 있다. Section 4.9.2도 참조한다.

(A3), (A4)(A5)는 일반적으로 (A1) 또는 (A2)와 함께 발생한다. 공격자들은 공동의 목표를 달성하기 위해 협력할 수 있다.

공격자 (A1) 또는 (A2)는 리소스 소유자이거나 리소스 소유자처럼 행동할 수 있음에 유의한다. 예를 들어, 그러한 공격자는 자신의 브라우저를 사용하여 위에서 설명한 공격 중 하나로 클라이언트 또는 리소스 서버에서 획득한 토큰이나 인가 코드를 리플레이할 수 있다.

이 문서는 공격자 (A1)부터 (A5)까지에서 비롯되는 위협에 초점을 둔다.

4. 공격과 완화책

이 절은 OAuth 구현에 대한 공격과 잠재적인 대응책을 상세히 설명한다. [RFC6819]에서 이미 다룬 공격과 완화책은, 새로운 권고사항이 제시되는 경우를 제외하고 여기에는 나열하지 않는다.

이 절은 또한 특정 사례와 프로토콜 옵션에 대해 (Section 2에서 정의한 것을 넘어서는) 추가 요구사항을 정의한다.

4.1. 불충분한 리디렉션 URI 검증

일부 인가 서버는 클라이언트가 완전한 리디렉션 URI 대신 리디렉션 URI 패턴을 등록할 수 있게 한다. 그런 다음 인가 서버는 런타임에 인가 엔드포인트의 리디렉션 URI 매개변수 값을 등록된 패턴과 대조한다. 이 접근 방식은 클라이언트가 추가 리디렉션 URI 매개변수에 트랜잭션 상태를 인코딩하거나 여러 리디렉션 URI에 대해 단일 패턴을 등록할 수 있게 한다.

이 접근 방식은 정확한 리디렉션 URI 일치보다 구현하기가 더 복잡하고 관리 시 오류가 더 발생하기 쉬운 것으로 드러났다. 패턴 일치 구현 또는 구체적인 구성의 결함을 악용한 여러 성공적인 공격이 실제 환경에서 관찰되었다(예: [research.rub2] 참조). 리디렉션 URI의 불충분한 검증은 사실상 클라이언트 식별 또는 인증 (그랜트와 클라이언트 유형에 따라)을 깨뜨리며, 공격자가 다음 중 하나를 통해 인가 코드 또는 액세스 토큰을 획득할 수 있게 한다.

  • 사용자 에이전트를 공격자가 제어하는 URI로 직접 보내거나,
  • 사용자 에이전트가 URL 프래그먼트를 처리하는 방식과 결합하여 클라이언트의 오픈 리디렉터를 활용함으로써 OAuth 자격 증명을 공격자에게 노출하는 방식이다.

이러한 공격은 다음 하위 절에서 자세히 보여준다.

4.1.1. 인가 코드 그랜트에 대한 리디렉션 URI 검증 공격

그랜트 유형 code를 사용하는 클라이언트의 경우, 공격은 다음과 같이 작동할 수 있다.

클라이언트 ID가 s6BhdRkqt3인 클라이언트에 대해 리디렉션 URL 패턴 https://*.somesite.example/*이 등록되어 있다고 가정한다. 의도는 somesite.example의 모든 하위 도메인이 클라이언트의 유효한 리디렉션 URI가 되도록 허용하는 것이다. 예를 들어 https://app1.somesite.example/redirect가 해당된다. 그러나 인가 서버의 순진한 구현은 와일드카드 *를 "도메인 이름에 유효한 임의의 문자"가 아니라 "임의의 문자"로 해석할 수 있다. 따라서 인가 서버는 https://attacker.example/.somesite.example를 리디렉션 URI로 허용할 수 있는데, attacker.example은 악의적인 당사자가 제어할 수 있는 다른 도메인이다.

그런 다음 공격은 다음과 같이 수행될 수 있다.

시작하려면, 공격자는 사용자가 공격자가 제어하는 페이지, 예를 들어 https://www.evil.example을 여는 변조된 URL을 브라우저에서 열도록 속여야 한다 (Section 3의 공격자 A1 참조).

이 URL은 합법적인 클라이언트의 클라이언트 ID를 사용하여 인가 엔드포인트로 다음 인가 요청을 시작한다(줄바꿈은 표시 목적일 뿐임).

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=9ad67f13
     &redirect_uri=https%3A%2F%2Fattacker.example%2F.somesite.example
     HTTP/1.1
Host: server.somesite.example

인가 서버는 리디렉션 URI를 검증하고 이를 클라이언트 s6BhdRkqt3에 대해 등록된 리디렉션 URL 패턴과 비교한다. 인가 요청은 처리되어 사용자에게 제시된다.

사용자가 리디렉션 URI를 보지 못하거나 공격을 인식하지 못하면, 코드가 발급되어 즉시 공격자의 도메인으로 전송된다. 인가의 자동 승인이 활성화되어 있다면 ([RFC6749]에 따르면 공개 클라이언트에는 권장되지 않음), 사용자 상호작용 없이도 공격을 수행할 수 있다.

공격자가 공개 클라이언트를 가장하는 경우, 공격자는 해당 토큰 엔드포인트에서 코드를 토큰으로 교환할 수 있다.

기밀 클라이언트의 경우 코드 교환에 합법적인 클라이언트의 비밀로 인증해야 하므로 이 공격이 그렇게 쉽게 작동하지는 않는다. 그러나 공격자는 인가 코드 주입 공격을 수행하여 합법적인 기밀 클라이언트가 코드를 교환하도록 사용할 수 있다. Section 4.5를 참조한다.

인가 서버가 와일드카드를 적절히 처리하더라도 리디렉션 URI 검증 취약점이 존재할 수 있다는 점에 유의하는 것이 중요하다. 예를 들어, 클라이언트가 리디렉션 URL 패턴 https://*.somesite.example/*을 등록하고, 인가 서버가 이를 "somesite.example 도메인에 있는 모든 호스트를 가리키는 리디렉션 URI를 허용"으로 해석한다고 가정한다. 공격자가 somesite.example에 호스트 또는 하위 도메인을 설정하는 데 성공하면, 공격자는 합법적인 클라이언트를 가장할 수 있다. 예를 들어 이는 [research.udel]의 하위 도메인 탈취 공격으로 인해 발생할 수 있는데, 오래된 CNAME 레코드(예: external-service.somesite.example)가 더 이상 존재하지 않는 외부 DNS 이름(예: customer-abc.service.example)을 가리키고, 공격자가 이를 탈취할 수 있는 경우(예: 외부 서비스에 customer-abc로 등록)이다.

4.1.2. 암시적 그랜트에 대한 리디렉션 URI 검증 공격

위에서 설명한 공격은 암시적 그랜트에도 작동한다. 공격자가 인가 응답을 공격자가 제어하는 URI로 보낼 수 있다면, 공격자는 액세스 토큰을 담은 프래그먼트에 직접 접근할 수 있게 된다.

추가로, 암시적 그랜트(및 [OAuth.Responses]에 정의된 response_mode=fragment를 사용할 때의 다른 그랜트)는 또 다른 종류의 공격 대상이 될 수 있다. 이 공격은 Location 헤더에 프래그먼트가 포함되어 있지 않은 경우 사용자 에이전트가 리디렉션의 대상 URL에 프래그먼트를 다시 붙인다는 사실을 이용한다 (Section 17.11 of [RFC9110] 참조). 여기서 설명하는 공격은 액세스 토큰을 획득하기 위해 이 동작을 오픈 리디렉터로서의 클라이언트 (Section 4.11.1 참조)와 결합한다. 이는 매우 좁은 리디렉션 URI 패턴도 우회할 수 있게 하지만, 엄격한 URL 일치는 우회하지 못한다.

클라이언트 s6BhdRkqt3의 등록된 URL 패턴이 https://client.somesite.example/cb?*, 즉 https://client.somesite.example/cb로의 리디렉션에는 어떤 매개변수든 허용된다고 가정한다. 불행히도 클라이언트는 오픈 리디렉터를 노출한다. 이 엔드포인트는 대상 URL을 받는 redirect_to 매개변수를 지원하고, HTTP Location 헤더 리디렉션 303을 사용하여 브라우저를 이 URL로 보낸다.

이제 공격은 다음과 같이 수행될 수 있다.

시작하려면, 위와 같이 공격자는 사용자가 공격자가 제어하는 페이지, 예를 들어 https://www.evil.example을 여는 변조된 URL을 브라우저에서 열도록 속여야 한다.

그 후 웹사이트는 코드 흐름에 대한 공격의 요청과 매우 유사한 인가 요청을 시작한다. 위와 다른 점은 redirect_to=https://attacker.example를 리디렉션 URI의 매개변수 안에 인코딩하여 오픈 리디렉터를 활용하고, response type token을 사용한다는 것이다(줄바꿈은 표시 목적일 뿐임).

GET /authorize?response_type=token&state=9ad67f13
    &client_id=s6BhdRkqt3
    &redirect_uri=https%3A%2F%2Fclient.somesite.example
     %2Fcb%26redirect_to%253Dhttps%253A%252F
     %252Fattacker.example%252F HTTP/1.1
Host: server.somesite.example

그런 다음, 리디렉션 URI가 등록된 패턴과 일치하므로 인가 서버는 요청을 허용하고 결과 액세스 토큰을 303 리디렉션으로 보낸다(일부 응답 매개변수는 가독성을 위해 생략됨).

HTTP/1.1 303 See Other
Location: https://client.somesite.example/cb?
          redirect_to%3Dhttps%3A%2F%2Fattacker.example%2Fcb
          #access_token=2YotnFZFEjr1zCsicMWpAA&...

client.somesite.example에서 요청은 오픈 리디렉터에 도착한다. 엔드포인트는 redirect 매개변수를 읽고 https://attacker.example/ URL로 HTTP 303 Location 헤더 리디렉션을 발행한다.

HTTP/1.1 303 See Other
Location: https://attacker.example/

client.somesite.example의 리디렉터가 Location 헤더에 프래그먼트를 포함하지 않으므로, 사용자 에이전트는 원래의 프래그먼트 #access_token=2YotnFZFEjr1zCsicMWpAA&...를 URL에 다시 붙이고 다음 URL로 이동한다.

https://attacker.example/#access_token=2YotnFZFEjr1z...

그런 다음 attacker.example의 공격자 페이지는 프래그먼트에 접근하여 액세스 토큰을 획득할 수 있다.

4.1.3. 대응책

패턴 일치를 올바르게 구현하고 관리하는 복잡성은 명백히 보안 문제를 야기한다. 따라서 이 문서는 정확한 리디렉션 URI 일치를 사용하여 필요한 로직과 구성을 단순화할 것을 권고한다. 이는 인가 서버가 두 URI가 동일함을 보장해야 MUST 함을 의미한다. 자세한 내용은 Section 6.2.1 of [RFC3986], Simple String Comparison을 참조한다. 유일한 예외는 localhost URI를 사용하는 네이티브 앱이다. 이 경우 인가 서버는 Section 7.3 of [RFC8252]에 설명된 것처럼 가변 포트 번호를 허용해야 MUST 한다.

추가 권고사항:

  • 리디렉션 URI가 호스팅되는 웹 서버는 오픈 리디렉터를 노출해서는 MUST NOT 된다 (Section 4.11 참조).
  • 브라우저는 Location 헤더의 URL에 이미 프래그먼트가 포함되어 있지 않은 경우에만 URL 프래그먼트를 Location 리디렉션 URL에 다시 붙인다. 따라서 서버는 Location 헤더의 URL에 임의의 프래그먼트 식별자, 예를 들어 #_를 붙임으로써 브라우저가 프래그먼트를 리디렉션 URL에 다시 붙이는 것을 방지할 수 MAY 있다.
  • 클라이언트는 인가 엔드포인트에서 액세스 토큰 발급을 유발하는 response type 대신 인가 코드 response type을 사용해야 SHOULD 한다. 이는 인가 서버와의 교환 과정을 통한 유출된 자격 증명의 재사용에 대한 대응책과, 액세스 토큰의 발신자 제한을 통한 토큰 리플레이에 대한 대응책을 제공한다.

예를 들어 클라이언트 인증과 함께 [RFC9101] 또는 [RFC9126]를 사용할 때처럼, 리디렉션 URI를 포함한 인가 요청의 출처와 무결성을 검증할 수 있다면, 인가 서버는 추가 검사 없이 리디렉션 URI를 신뢰할 수 MAY 있다.

4.2. Referer 헤더를 통한 자격 증명 유출

인가 요청 URI 또는 인가 응답 URI의 내용은 각각 인가 서버 또는 클라이언트의 웹사이트에서 유출되어 Referer HTTP 헤더(Section 10.1.3 of [RFC9110] 참조)를 통해 의도치 않게 공격자에게 공개될 수 있다. 가장 중요하게는 인가 코드 또는 state 값이 이런 방식으로 공개될 수 있다. Section 10.1.3 of [RFC9110]에서 달리 명시되어 있음에도 불구하고, Chromium 프로젝트의 (현재는 수정된) 이슈 [bug.chromium]에서 설명된 것처럼 브라우저 구현 문제로 인해 URI 프래그먼트에 실려 전달되는 액세스 토큰에도 같은 일이 발생할 수 있다.

4.2.1. OAuth 클라이언트로부터의 유출

OAuth 클라이언트로부터의 유출은 성공적인 인가 요청의 결과로 클라이언트가 다음과 같은 페이지를 렌더링해야 발생한다.

  • 공격자가 제어하는 다른 페이지로 연결되는 링크를 포함하고 사용자가 그러한 링크를 클릭하는 경우, 또는
  • 예를 들어 페이지에 사용자 생성 콘텐츠 (블로그)가 포함되어 있는 경우처럼 제3자 콘텐츠(iframe의 광고, 이미지 등)를 포함하는 경우이다.

브라우저가 공격자의 페이지로 이동하거나 제3자 콘텐츠를 로드하자마자, 공격자는 인가 응답 URL을 받게 되고 code 또는 state(그리고 잠재적으로 access_token)를 추출할 수 있다.

4.2.2. 인가 서버로부터의 유출

비슷한 방식으로, 인가 서버의 인가 엔드포인트가 위와 같은 링크나 제3자 콘텐츠를 포함하면, 공격자는 인가 요청에서 state를 알 수 있다.

4.2.3. 결과

Referer 헤더를 통해 유효한 코드 또는 액세스 토큰을 알게 된 공격자는 Sections 4.1.1, 4.54.6에 설명된 공격을 수행할 수 있다. 공격자가 state를 알게 되면, state 사용으로 달성되는 CSRF 보호가 상실되어 Section 4.4.1.8 of [RFC6819]에 설명된 CSRF 공격으로 이어진다.

4.2.4. 대응책

OAuth 인가 응답의 결과로 렌더링되는 페이지와 인가 엔드포인트는 제3자 리소스나 외부 사이트로의 링크를 포함해서는 SHOULD NOT 된다.

다음 조치들은 성공적인 공격 가능성을 추가로 낮춘다.

  • 문서에 적절한 Referrer Policy [W3C.webappsec-referrer-policy]를 적용하여 ( "referrer" meta 속성의 일부로 또는 Referrer-Policy 헤더를 설정하여) Referer 헤더를 억제한다. 예를 들어, 응답의 헤더 Referrer-Policy: no-referrer는 결과 문서에서 발생하는 모든 요청의 Referer 헤더를 완전히 억제한다.
  • 인가 엔드포인트에서 액세스 토큰 발급을 유발하는 response type 대신 인가 코드를 사용한다.
  • 인가 코드를 기밀 클라이언트 또는 PKCE challenge에 바인딩한다. 이 경우 공격자에게는 코드 교환을 요청할 비밀이 없다.
  • Section 4.1.2 of [RFC6749]에 설명된 것처럼, 인가 코드는 토큰 엔드포인트에서 처음 사용된 후 인가 서버에 의해 무효화되어야 MUST 한다. 예를 들어, 합법적인 클라이언트가 코드를 교환한 후 인가 서버가 코드를 무효화했다면, 공격자는 나중에 이 코드를 교환하는 데 실패한다.

    공격자가 합법적인 클라이언트보다 먼저 코드를 토큰으로 교환하는 데 성공하면 이는 공격을 완화하지 못한다. 따라서 [RFC6749]는 코드를 두 번 교환하려는 시도가 있을 때, 인가 서버가 해당 코드에 기반해 이전에 발급된 모든 토큰을 취소해야 SHOULD 한다고 추가로 권고한다.

  • state 값은 리디렉션 엔드포인트에서 처음 사용된 후 클라이언트가 무효화해야 SHOULD 한다. 이것이 구현되어 있고, 공격자가 클라이언트의 웹사이트에서 Referer 헤더를 통해 토큰을 받는 경우, state는 이미 사용되었고 클라이언트에 의해 무효화되었으므로 공격자가 다시 사용할 수 없다. (이는 state가 인가 서버의 웹사이트에서 유출되는 경우에는 도움이 되지 않는다. 그 경우 state가 아직 클라이언트의 리디렉션 엔드포인트에서 사용되지 않았기 때문이다.)

  • 인가 응답에 대해 리디렉션 대신 form post response mode를 사용한다([OAuth.Post] 참조).

4.3. 브라우저 기록을 통한 자격 증명 유출

인가 코드와 액세스 토큰은 브라우저의 방문 URL 기록에 남을 수 있으며, 이는 다음에 설명하는 공격을 가능하게 한다.

4.3.1. 브라우저 기록의 인가 코드

브라우저가 제공자의 인가 엔드포인트에서의 리디렉션 결과로 client.example/redirection_endpoint?code=abcd로 이동하면, 인가 코드를 포함한 URL이 브라우저 기록에 남을 수 있다. 기기에 접근할 수 있는 공격자는 코드를 획득하고 이를 리플레이하려고 시도할 수 있다.

대응책:

4.3.2. 브라우저 기록의 액세스 토큰

클라이언트 또는 이미 토큰을 가진 웹사이트가 provider.com/get_user_profile?access_token=abcdef와 같은 페이지로 의도적으로 이동하면, 액세스 토큰이 브라우저 기록에 남을 수 있다. [RFC6750]은 이러한 관행을 권장하지 않으며 헤더를 통해 토큰을 전송할 것을 권고하지만, 실제로 웹사이트는 종종 쿼리 매개변수로 액세스 토큰을 전달한다.

암시적 그랜트의 경우, 제공자의 인가 엔드포인트에서 리디렉션된 결과로 client.example/redirection_endpoint#access_token=abcdef와 같은 URL도 브라우저 기록에 남을 수 있다.

대응책:

  • 클라이언트는 Section 2.3 of [RFC6750]에 설명된 방식으로 URI 쿼리 매개변수에 액세스 토큰을 전달해서는 MUST NOT 된다. 이를 위해 인가 코드 그랜트 또는 form post response mode [OAuth.Post]와 같은 대체 OAuth response mode를 사용할 수 있다.

4.4. 믹스업 공격

믹스업 공격은 OAuth 클라이언트가 둘 이상의 인가 서버와 상호작용하고, 그중 적어도 하나의 인가 서버가 공격자의 제어하에 있는 시나리오에서 발생할 수 있다. 예를 들어, 공격자가 동적 등록을 사용하여 자신의 인가 서버에 클라이언트를 등록하거나, 인가 서버가 손상된 경우에 이런 일이 발생할 수 있다.

공격의 목표는 손상되지 않은 인가 서버에 대한 인가 코드 또는 액세스 토큰을 획득하는 것이다. 이는 클라이언트가 해당 자격 증명을 손상되지 않은 인가/리소스 서버의 해당 엔드포인트에서 사용하는 대신, 손상된 인가 서버(공격자)로 보내도록 속임으로써 달성된다.

4.4.1. 공격 설명

여기서의 설명은 [arXiv.1601.01229]를 따르며, 공격의 변형은 아래에 개략적으로 설명한다.

전제 조건: 이 공격 변형이 작동하려면 다음이 가정된다.

  • 암시적 또는 인가 코드 그랜트가 여러 인가 서버와 함께 사용되며, 그중 하나는 "정직한" 서버(H-AS)로 간주되고 하나는 공격자(A-AS)가 운영한다. 그리고
  • 클라이언트는 사용자가 선택한 인가 서버를 사용자의 브라우저에 바인딩된 세션에 저장하고, 각 인가 서버에 대해 동일한 리디렉션 URI를 사용한다.

다음에서는 클라이언트가 H-AS (URI: https://honest.as.example, 클라이언트 ID: 7ZGZldHQ)와 A-AS (URI: https://attacker.example, 클라이언트 ID: 666RVZJTA)에 등록되어 있다고 추가로 가정한다. 다음 예시에 표시된 URL은 공격과 관련된 매개변수만 포함하도록 표시를 위해 축약되어 있다.

인가 코드 그랜트에 대한 공격:

  1. 사용자는 A-AS를 사용하여 그랜트를 시작하도록 선택한다(예: 클라이언트 웹사이트의 버튼을 클릭함).
  2. 클라이언트는 사용자가 "A-AS"를 선택했다는 사실을 사용자의 세션에 저장하고, https://attacker.example/authorize?response_type=code&client_id=666RVZJTA URL을 포함한 Location 헤더와 함께 사용자를 A-AS의 인가 엔드포인트로 리디렉션한다.
  3. 사용자의 브라우저가 공격자의 인가 엔드포인트로 이동하면, 공격자는 즉시 브라우저를 H-AS의 인가 엔드포인트로 리디렉션한다. 인가 요청에서 공격자는 A-AS에 있는 클라이언트의 클라이언트 ID를 H-AS에 있는 클라이언트의 ID로 대체한다. 따라서 브라우저는 https://honest.as.example/authorize?response_type=code&client_id=7ZGZldHQ를 가리키는 Location 헤더가 포함된 리디렉션(303 See Other)을 받는다.
  4. 사용자는 H-AS에서 자신의 리소스에 클라이언트가 접근하도록 인가한다. (주의 깊은 사용자는 이 시점에서 자신이 H-AS 대신 A-AS를 사용하려 했음을 감지할 수 있다. 첫 번째 공격 변형에는 이러한 제한이 없다.) H-AS는 코드를 발급하고 이를 (브라우저를 통해) 클라이언트로 다시 보낸다.

  5. 클라이언트는 여전히 코드가 A-AS에 의해 발급되었다고 가정하므로, A-AS의 토큰 엔드포인트에서 코드를 교환하려고 시도한다.

  6. 따라서 공격자는 코드를 획득하며, 코드를 액세스 토큰으로 교환하거나(공개 클라이언트의 경우), Section 4.5에 설명된 인가 코드 주입 공격을 수행할 수 있다.

변형:

  • 가로채기를 동반한 믹스업: 이 변형은 공격자가 사용자의 브라우저에서 클라이언트로 가는 첫 번째 요청/응답 쌍(사용자가 특정 인가 서버를 선택하고, 클라이언트가 사용자를 해당 인가 서버로 리디렉션하는 과정)을 가로채고 조작할 수 있는 경우에만 작동한다. Attacker (A2) (Section 3 참조)와 같다. 이러한 능력은 예를 들어 사용자의 클라이언트 연결에 대한 중간자 공격의 결과일 수 있다. 공격에서 사용자는 H-AS로 흐름을 시작한다. 공격자는 이 요청을 가로채고 사용자의 선택을 A-AS로 변경한다. 나머지 공격은 위의 Step 2 및 그 이후와 같이 진행된다.
  • 암시적 그랜트: 암시적 그랜트에서는 공격자가 Step 4에서 코드 대신 액세스 토큰을 받는다. 클라이언트가 A-AS userinfo 엔드포인트([OpenID.Core]에 정의됨)나 공격자의 리소스 서버에 요청을 보낼 때 (클라이언트는 자신이 A-AS와의 흐름을 완료했다고 믿기 때문), 공격자의 인가 서버는 액세스 토큰을 받는다.
  • AS별 리디렉션 URI: 클라이언트가 서로 다른 인가 서버에 대해 서로 다른 리디렉션 URI를 사용하고, 클라이언트가 사용자의 세션에 선택된 인가 서버를 저장하지 않으며, 인가 서버가 리디렉션 URI를 올바르게 검사하지 않는 경우, 공격자는 "Cross Social-Network Request Forgery"라는 공격을 실행할 수 있다. 이러한 공격은 실제로 관찰되었다. 자세한 내용은 [research.jcs_14]를 참조한다.
  • OpenID Connect: 일부 변형은 OpenID Connect를 공격하는 데 사용될 수 있다. 이러한 공격에서 공격자는 OpenID Connect Discovery [OpenID.Discovery] 메커니즘의 기능을 오용하거나 액세스 토큰 또는 ID Token을 리플레이하여 믹스업 공격을 수행한다. 공격은 [arXiv.1704.08539]의 Appendix A 및 [arXiv.1508.04324v2]의 Section 6 ("Malicious Endpoints Attacks")에 자세히 설명되어 있다.

4.4.2. 대응책

OAuth 클라이언트가 하나의 인가 서버와만 상호작용할 수 있는 경우, 믹스업 방어는 필요하지 않다. 그러나 OAuth 클라이언트가 둘 이상의 인가 서버와 상호작용하는 시나리오에서는, 클라이언트가 믹스업 공격을 방지해야 MUST 한다. 아래에서는 두 가지 서로 다른 방법을 논의한다.

두 방어 모두에서, 클라이언트는 각 인가 요청마다 인가 요청을 보낸 발급자를 저장하고 이 정보를 사용자 에이전트에 바인딩해야 MUST 한다. 발급자는 관련 메타데이터를 통해 흐름에서 사용될 인가 엔드포인트와 토큰 엔드포인트의 조합에 대한 추상 식별자 역할을 한다. 발급자 식별자를 사용할 수 없는 경우 (예를 들어 OAuth Authorization Server Metadata [RFC8414]나 OpenID Connect Discovery [OpenID.Discovery]가 사용되지 않는 경우), 이 튜플에 대한 다른 고유 식별자 또는 튜플 자체를 대신 사용할 수 있다. 표시의 간결성을 위해, 이러한 배포별 식별자는 이하에서 발급자(또는 발급자 식별자)에 포함되는 것으로 본다.

단순히 인가 서버 URL을 저장하는 것만으로는 믹스업 공격을 식별하기에 충분하지 않다는 점에 유의하는 것이 중요하다. 공격자는 손상되지 않은 인가 서버의 인가 엔드포인트 URL을 "자신의" 인가 서버 URL로 선언하면서, 토큰 엔드포인트는 자신의 제어하에 있는 것으로 선언할 수 있다.

4.4.2.1. 발급자 식별을 통한 믹스업 방어

이 방어는 인가 서버가 자신의 발급자 식별자를 인가 응답에서 클라이언트로 보내야 한다. 인가 응답을 수신할 때, 클라이언트는 수신한 발급자 식별자를 저장된 발급자 식별자와 비교해야 MUST 한다. 불일치가 있으면, 클라이언트는 상호작용을 중단해야 MUST 한다.

이 발급자 식별자가 클라이언트로 전달될 수 있는 방법은 여러 가지가 있다.

  • 예를 들어 발급자 정보는 [RFC9207]에 정의된 별도의 응답 매개변수 iss를 통해 전달될 수 있다.
  • OpenID Connect가 사용되고 ID Token이 인가 응답에서 반환되는 경우, 클라이언트는 ID Token의 iss 클레임을 평가할 수 있다.

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

이 방어는 발급자 정보를 전달하기 위해 새로운 OAuth 기능 배포가 필요할 수 있지만, 믹스업에 대한 견고하고 비교적 단순한 방어이다.

4.4.2.2. 서로 다른 리디렉션 URI를 통한 믹스업 방어

이 방어를 위해, 클라이언트는 상호작용하는 각 발급자마다 서로 다른 리디렉션 URI를 사용해야 MUST 한다.

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

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

또한 공격자는 클라이언트가 공격자의 인가 서버에 할당한 redirect URI를 사용하여 "정직한" 인가 서버에 새 클라이언트를 등록함으로써 이 방어가 제공하는 보호를 우회할 수 있을지도 모른다. 그런 다음 공격자는 위에서 설명한 공격을 실행하면서 클라이언트 ID를 새로 생성한 클라이언트의 클라이언트 ID로 대체할 수 있다.

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

4.5. 인가 코드 주입

인가 응답에 포함된 인가 코드에 접근할 수 있게 된 공격자 (Section 3Attacker (A3) 참조)는 인가 코드를 액세스 토큰으로 교환하거나 다른 방식으로 인가 코드를 사용하려고 시도할 수 있다.

인가 코드가 공개 클라이언트를 위해 생성된 경우, 공격자는 인가 코드를 인가 서버의 토큰 엔드포인트로 보내 액세스 토큰을 얻을 수 있다. 이 공격은 Section 4.4.1.1 of [RFC6819]에 설명되어 있다.

기밀 클라이언트의 경우, 또는 일부 특수한 상황에서는, 공격자가 다음에 설명하는 인가 코드 주입 공격을 실행할 수 있다.

인가 코드 주입 공격에서 공격자는 훔친 인가 코드를 클라이언트와의 공격자 자신의 세션에 주입하려고 시도한다. 목표는 클라이언트에서 공격자의 세션을 피해자의 리소스 또는 신원과 연결하여, 공격자가 피해자의 리소스에 적어도 제한적으로 접근할 수 있게 하는 것이다.

기밀 클라이언트의 클라이언트 인증을 우회하는 것 외에도, 이 공격의 다른 사용 사례는 다음과 같다.

  • 공격자가 이 특정 클라이언트의 특정 기능에 접근하려는 경우. 예를 들어, 공격자가 특정 앱 또는 특정 웹사이트에서 피해자를 가장하려는 경우이다.
  • 인가 서버 또는 리소스 서버가 공격자가 직접 접근할 수 없는 특정 네트워크로 제한되어 있는 경우.

이러한 특수한 경우를 제외하면, 공개 클라이언트를 위해 코드가 생성된 경우 인가 코드 주입은 일반적으로 흥미롭지 않다. 위에서 설명한 것처럼 코드를 토큰 엔드포인트로 보내는 것이 더 단순하고 강력한 공격이기 때문이다.

4.5.1. 공격 설명

인가 코드 주입 공격은 다음과 같이 작동한다.

  1. 공격자가 인가 코드를 획득한다 (Section 3Attacker (A3) 참조). 공격의 나머지 부분에는 웹 공격자 (A1)의 역량만 필요하다.
  2. 공격자의 기기에서, 공격자는 합법적인 클라이언트와 일반적인 OAuth 인가 프로세스를 시작한다.
  3. 인가 서버가 합법적인 클라이언트에 보내는 응답에서, 공격자는 새로 생성된 인가 코드를 훔친 인가 코드로 대체한다. 이 응답은 공격자의 기기를 통과하므로, 공격자는 이를 위해 인가 응답을 가로채고 조작할 수 있는 어떤 도구든 사용할 수 있다. 공격자는 네트워크를 제어할 필요가 없다.
  4. 합법적인 클라이언트는 redirect_uri, 클라이언트의 클라이언트 ID 및 클라이언트 비밀(또는 다른 클라이언트 인증 수단)과 함께 코드를 인가 서버의 토큰 엔드포인트로 보낸다.
  5. 인가 서버는 클라이언트 비밀, 코드가 해당 특정 클라이언트에 발급되었는지 여부, 그리고 실제 리디렉션 URI가 redirect_uri 매개변수와 일치하는지 여부를 검사한다 ([RFC6749] 참조).
  6. 모든 검사가 성공하고 인가 서버는 액세스 토큰과 기타 토큰을 클라이언트에 발급한다. 공격자는 이제 합법적인 클라이언트와의 자신의 세션을 피해자의 리소스 및/또는 신원과 연결한 상태가 된다.

4.5.2. 논의

분명히, 코드가 다른 클라이언트 ID(예: 공격자가 설정한 클라이언트)에 발급된 경우 check-in 단계(Step 5)는 실패한다. 또한 인가 코드가 합법적인 사용자에 의해 이미 교환되었고 일회용이었다면 검사도 실패한다.

인가 서버가 인가 요청에 사용된 완전한 리디렉션 URI를 저장하고 이를 redirect_uri 매개변수와 비교한다면, 조작된 리디렉션 URI를 통해 얻은 코드를 주입하려는 시도도 탐지되어야 한다.

Section 4.1.3 of [RFC6749]은 인가 서버에 다음을 요구한다.

ensure that the "redirect_uri" parameter is present if the "redirect_uri" parameter was included in the initial authorization request as described in Section 4.1.1, and if included ensure that their values are identical.

Section 4.5.1에 설명된 공격 시나리오에서, 합법적인 클라이언트는 인가 요청에 항상 사용하는 올바른 리디렉션 URI를 사용하게 된다. 그러나 이 URI는 공격자가 사용한 조작된 리디렉션 URI와 일치하지 않는다(그렇지 않다면 리디렉션이 공격자의 페이지에 도착하지 않았을 것이다). 따라서 인가 서버는 공격을 탐지하고 코드 교환을 거부한다.

특정 조건이 충족된다면, 이 검사는 다른 기기에 있는 동일한 클라이언트의 다른 인스턴스에서 획득한 인가 코드를 주입하려는 시도도 탐지할 수 있다.

  • 리디렉션 URI 자체가 nonce 또는 다른 종류의 일회용 비밀 데이터를 포함하고,
  • 클라이언트가 이 데이터를 해당 클라이언트의 특정 인스턴스에 바인딩한 경우이다.

그러나 이 접근 방식은 인가 엔드포인트에서 정확한 redirect URI 일치를 강제하려는 생각과 충돌한다. 또한 제공자들이 이 단계에서 redirect_uri 검사 요구사항을 매우 자주 무시하는 것으로 관찰되었는데, 이는 아마 명세를 읽을 때 그것이 보안상 중요해 보이지 않기 때문일 수 있다.

다른 제공자들은 redirect_uri 매개변수를 등록된 리디렉션 URI 패턴과 단순히 패턴 매칭한다. 이는 인가 서버가 모든 트랜잭션마다 실제 redirect URI와 해당 인가 코드 사이의 연결을 저장하지 않아도 되게 한다. 그러나 이러한 종류의 검사는 조작된 리디렉션 URI를 고려하지 않으므로 명세의 의도를 명백히 충족하지 못한다. 따라서 합법적인 클라이언트의 client_id를 사용하거나 다른 기기에서 합법적인 클라이언트를 활용하여 얻은 인가 코드를 주입하려는 모든 시도는 해당 배포에서 탐지되지 않는다.

Section 4.1.3 of [RFC6749]에 정의된 요구사항은 클라이언트가 토큰 엔드포인트 호출에 사용할 올바른 리디렉션 URI를 저장하거나 재구성해야 하므로 클라이언트 구현 복잡성을 증가시키는 것으로도 가정된다.

클라이언트 인증을 위한 비대칭 방식은 이 공격을 막지 못한다. 합법적인 클라이언트가 토큰 엔드포인트에서 인증하기 때문이다.

따라서 이 문서는 대신 다음에 설명하는 메커니즘 중 하나를 사용하여, 특정 트랜잭션의 맥락에서 모든 인가 코드를 특정 기기 (또는 특정 사용자 에이전트)의 특정 클라이언트 인스턴스에 바인딩할 것을 권고한다.

4.5.3. 대응책

인가 코드를 클라이언트 인스턴스에 바인딩하는 데에는 다음과 같은 두 가지 좋은 기술적 해결책이 있다.

4.5.3.1. PKCE

[RFC7636]에 명시된 PKCE 메커니즘은 대응책으로 사용될 수 있다(원래는 네이티브 앱을 보호하기 위해 설계되었지만). 공격자가 인가 코드를 주입하려고 시도하면, code_verifier 검사가 실패한다. 클라이언트는 자신의 올바른 verifier를 사용하지만, 코드는 이 verifier와 일치하지 않는 code_challenge와 연결되어 있기 때문이다.

PKCE는 인가 코드 주입 공격뿐 아니라 공개 클라이언트를 위해 생성된 인가 코드도 보호한다. PKCE는 공격자가 code_verifier를 알지 못하면 인가 서버의 토큰 엔드포인트에서 훔친 인가 코드를 교환할 수 없도록 보장한다.

4.5.3.2. Nonce

OpenID Connect의 기존 nonce 매개변수는 인가 코드 주입 공격으로부터 보호할 수 있다. nonce 값은 일회용이며 클라이언트가 생성한다. 클라이언트는 이를 사용자 에이전트 세션에 바인딩하고 OpenID Provider (OP)로 보내는 최초 요청과 함께 전송해야 한다. OP는 토큰 엔드포인트에서의 코드 교환의 일부로 발급되는 ID Token 안에 수신한 nonce 값을 넣는다. 공격자가 인가 응답에 인가 코드를 주입하면, 클라이언트 세션의 nonce 값과 토큰 엔드포인트에서 받은 ID Token의 nonce 값이 일치하지 않으며, 공격이 탐지된다. 가정은 공격자가 (해당 인가 코드를 훔친) 피해자의 기기에서 사용자 에이전트 상태를 획득할 수 없다는 것이다.

이 대응책은 클라이언트가 토큰 엔드포인트에서 얻은 ID Token의 nonce 매개변수를 적절히 검사하고, 이 검사가 성공할 때까지 발급된 토큰을 어떤 용도로도 사용하지 않는 경우에만 작동한다는 점에 유의하는 것이 중요하다. 더 정확히 말하면, nonce 매개변수를 사용하여 코드 주입으로부터 자신을 보호하는 클라이언트는

  1. 인가 응답에서 다른 ID Token을 얻었더라도 (예: response_type=code+id_token), 토큰 엔드포인트에서 얻은 ID Token의 nonce를 검증해야 MUST 하며,
  2. 해당 검사가 성공하지 않는 한, 그리고 성공할 때까지 모든 토큰(ID Tokens 및 액세스 토큰)을 무시하고 다른 어떤 목적에도 사용하지 않도록 보장해야 MUST 한다.

nonce는 공개 클라이언트의 인가 코드를 보호하지 않는다는 점에 유의하는 것이 중요하다. 공격자는 인가 코드 주입 공격을 실행할 필요가 없기 때문이다. 대신 공격자는 훔친 인가 코드로 토큰 엔드포인트를 직접 호출할 수 있다.

4.5.3.3. 기타 해결책

state를 코드에 바인딩하거나, 암호학적 수단을 사용하여 코드를 발신자 제한하거나, 인스턴스별 클라이언트 자격 증명을 사용하는 것과 같은 다른 해결책도 생각할 수 있지만, 지원이 부족하고 새로운 보안 요구사항을 가져온다.

PKCE는 작성 시점에 사용할 수 있으므로 OAuth 클라이언트에 가장 명백한 해결책이며, nonce는 OpenID Connect 클라이언트에 적합하다.

4.5.4. 제한 사항

공격자가 피해자의 인가 요청에서 사용되는 nonce 또는 code_challenge 값을 수정할 수 있다면, 위에서 설명한 대응책을 우회할 수 있다. 공격자는 위 공격의 Step 2에서 자신의 세션에서 클라이언트가 선택한 값과 동일한 값으로 이 값들을 수정할 수 있다. (이는 피해자의 클라이언트 세션이 공격자가 클라이언트와 세션을 시작한 후에 시작되어야 한다.) 그런 다음 공격자가 피해자로부터 인가 코드를 포착할 수 있다면, PKCE 또는 nonce가 사용되더라도 Step 3에서 훔친 코드를 주입할 수 있게 된다.

이 공격은 복잡하며 공격자와 피해자의 세션 사이의 긴밀한 상호작용을 필요로 한다. 그럼에도 불구하고 인가 응답의 내용을 공격자가 읽지 못하도록 하는 조치는 여전히 취해야 하며, 이는 Sections 4.1, 4.2, 4.3, 4.44.11에 설명되어 있다.

4.6. 액세스 토큰 주입

액세스 토큰 주입 공격에서 공격자는 훔친 액세스 토큰을 (공격자의 제어하에 있지 않은) 합법적인 클라이언트에 주입하려고 시도한다. 이는 일반적으로 공격자가 유출된 액세스 토큰을 활용하여 특정 클라이언트에서 사용자를 가장하려는 경우에 발생한다.

공격을 수행하기 위해, 공격자는 암시적 그랜트를 사용하여 클라이언트와 OAuth 흐름을 시작하고, 인가 서버가 발급한 액세스 토큰을 대체하거나 유출된 액세스 토큰을 포함하는 인가 서버 응답을 직접 만들어 인가 응답을 수정한다. 응답에는 이 특정 트랜잭션을 위해 클라이언트가 생성한 state 값이 포함되어 있으므로, 클라이언트는 이 응답을 CSRF 공격으로 처리하지 않고 공격자가 주입한 액세스 토큰을 사용한다.

4.6.1. 대응책

순수 OAuth 흐름에서는 토큰이 트랜잭션 또는 특정 사용자 에이전트에 대한 어떠한 바인딩 없이 발급되므로 이러한 주입 공격을 탐지할 방법이 없다.

OpenID Connect에서는 인가 응답에 at_hash 클레임을 포함하는 ID Token이 추가로 포함되므로 공격을 완화할 수 있다. 따라서 공격자는 응답에서 액세스 토큰과 ID Token을 모두 대체해야 한다. 공격자는 ID Token을 위조할 수 없다. ID Token은 인증과 함께 서명되거나 암호화되기 때문이다. 또한 공격자는 훔친 액세스 토큰과 일치하는 유출된 ID Token을 주입할 수도 없다. 유출된 ID Token의 nonce 클레임에는 인가 응답에서 예상되는 값과 (매우 높은 확률로) 다른 값이 포함되어 있기 때문이다.

발신자 제한 액세스 토큰과 같은 추가 보호는 공격자가 리소스 엔드포인트에서 액세스 토큰을 직접 사용하는 것을 방지하기 위해 여전히 필요하다는 점에 유의한다.

Section 2.1.2의 권고사항은 여기에서 도출된다.

4.7. 크로스 사이트 요청 위조

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

4.7.1. 대응책

오랫동안 확립된 대응책은 클라이언트가 CSRF Token이라고도 알려진 무작위 값을 state 매개변수에 전달하여, 설명된 대로 리디렉션 URI에 대한 요청을 사용자 에이전트 세션과 연결하는 것이다. 이 대응책은 Section 5.3.5 of [RFC6819]에 자세히 설명되어 있다. PKCE 또는 OpenID Connect nonce 값도 동일한 보호를 제공한다.

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

  • 클라이언트는 CSRF 보호를 위해 PKCE를 사용하기 전에 인가 서버가 PKCE를 지원함을 보장해야 MUST 한다. 인가 서버가 PKCE를 지원하지 않으면, CSRF 보호를 위해 state 또는 nonce를 사용해야 MUST 한다.

  • state가 애플리케이션 상태를 전달하는 데 사용되고 그 내용의 무결성이 문제라면, 클라이언트는 state를 변조와 교체로부터 보호해야 MUST 한다. 이는 state의 내용을 브라우저 세션에 바인딩하거나 state 값을 서명/암호화함으로써 달성할 수 있다. 그 한 예가 만료된 Internet-Draft [JWT-ENCODED-STATE]에서 논의된다.

따라서 인가 서버는 PKCE 지원을 탐지할 수 있는 방법을 제공해야 MUST 한다. [RFC8414]에 따른 Authorization Server Metadata를 사용하는 것이 RECOMMENDED되지만, 인가 서버는 대신 배포별 방식으로 PKCE 지원을 보장하거나 확인하는 방법을 제공할 수 MAY 있다.

PKCE는 인가 응답을 읽을 수 있는 공격자 (Section 3Attacker (A3) 참조)가 존재하는 경우에도 CSRF 공격에 대해 견고한 보호를 제공한다. state가 사용되거나 인가 응답에서 ID Token이 반환되는 경우(예: response_type=code+id_token), 공격자는 state 값을 알게 되어 위조된 인가 응답에 이를 리플레이할 수 있거나, ID Token에서 nonce를 추출하여 동일한 nonce를 가진 ID Token을 만들기 위해 인가 서버에 새 요청에서 사용할 수 있다. 그런 다음 새 ID Token은 CSRF 공격에 사용될 수 있다.

4.8. PKCE 다운그레이드 공격

PKCE를 지원하지만 모든 흐름에서 그 사용을 의무화하지 않는 인가 서버는 PKCE 다운그레이드 공격에 취약할 수 있다.

이 공격의 첫 번째 전제 조건은 특정 흐름에 대해 PKCE를 활성화하거나 비활성화하는, 공격자가 제어할 수 있는 플래그가 인가 요청에 존재한다는 것이다. code_challenge 매개변수의 존재 여부는 이 목적에 적합하다. 즉 인가 서버는 이 매개변수가 인가 요청에 존재하면 PKCE를 활성화하고 강제하지만, 매개변수가 없으면 PKCE를 강제하지 않는다.

이 공격의 두 번째 전제 조건은 클라이언트가 state를 전혀 사용하지 않거나(예: 클라이언트가 CSRF 방지에 PKCE에 의존하기 때문), 클라이언트가 state를 올바르게 검사하지 않는 것이다.

대략적으로 말하면, 이 공격은 CSRF 공격의 변형이다. 공격자는 Section 4.7에 설명된 공격과 동일한 목표를 달성한다. 즉 공격자의 리소스에 바인딩된 인가 코드(그리고 그에 따른 액세스 토큰)를 피해자와 클라이언트 사이의 세션에 주입한다.

4.8.1. 공격 설명

  1. 사용자는 인가 서버에서 어떤 클라이언트를 사용하여 OAuth 세션을 시작했다. 인가 요청에서 클라이언트는 PKCE code challenge로 code_challenge=hash(abc) 매개변수를 설정했다 (해시 함수와 매개변수 인코딩은 [RFC7636]에 정의된 대로). 이제 클라이언트는 사용자의 브라우저에서 인가 응답을 받기를 기다리고 있다.
  2. 공격을 수행하기 위해, 공격자는 자신의 기기를 사용해 대상 클라이언트와 인가 흐름을 시작한다. 클라이언트는 이제 인가 요청에서 다른 PKCE code challenge, 예를 들어 code_challenge=hash(xyz)를 사용한다. 공격자는 요청을 가로채고 전체 code_challenge 매개변수를 요청에서 제거한다. 이 단계는 공격자의 기기에서 수행되므로, 공격자는 예를 들어 브라우저 디버그 도구를 사용하여 요청 내용에 완전히 접근할 수 있다.
  3. 인가 서버가 PKCE 없는 흐름을 허용하면, 어떤 PKCE code challenge에도 바인딩되지 않은 코드를 생성한다.
  4. 이제 공격자는 인가 서버와의 공격자 세션에 대한 코드를 포함하는 인가 응답 URL로 사용자의 브라우저를 리디렉션한다.
  5. 사용자의 브라우저는 인가 코드를 클라이언트에 보내고, 클라이언트는 이제 인가 서버에서 코드를 액세스 토큰으로 교환하려고 시도한다. 클라이언트는 토큰 요청에서 PKCE code verifier로 code_verifier=abc를 보낸다.
  6. 인가 서버는 이 코드가 어떤 PKCE code challenge에도 바인딩되지 않았음을 보게 되므로, code_verifier 매개변수의 존재나 내용을 검사하지 않는다. 그리고 사용자가 제어하는 클라이언트에 (공격자의 리소스에 속한) 액세스 토큰을 발급한다.

4.8.2. 대응책

state를 적절히 사용하면 이 공격을 방지할 수 있다. 그러나 실제로 많은 OAuth 클라이언트가 state를 사용하지 않거나 올바르게 검사하지 않는 것으로 나타났다.

따라서 인가 서버는 이 공격을 완화해야 MUST 한다.

인가 서버의 관점에서 보면, 위에서 설명한 공격에서는 인가 코드가 발급된 OAuth 흐름의 인가 요청에 code_challenge 매개변수가 없었음에도 불구하고, 토큰 엔드포인트에서 code_verifier 매개변수가 수신된다는 점에 유의한다.

이 사실은 공격을 완화하는 데 사용될 수 있다. [RFC7636]는 이미 다음을 요구한다.

  • PKCE를 지원하는 인가 서버는 인가 요청에 code challenge가 포함되어 있는지 확인하고, 이 정보를 발급되는 코드에 바인딩해야 MUST 한다. 그리고
  • 코드가 토큰 엔드포인트에 도착하고, 이 코드가 발급된 인가 요청에 code_challenge가 있었던 경우, 토큰 요청에는 유효한 code_verifier가 있어야 한다.

이 외에도 PKCE 다운그레이드 공격을 방지하기 위해, 인가 서버는 인가 요청에 code_challenge가 없었다면, code_verifier를 포함하는 토큰 엔드포인트 요청을 거부하도록 보장해야 MUST 한다.

PKCE 사용을 (일반적으로 또는 특정 클라이언트에 대해) 의무화하는 인가 서버는 이 보안 조치를 암묵적으로 구현한다.

4.9. 리소스 서버에서의 액세스 토큰 유출

특정 상황에서 액세스 토큰은 리소스 서버로부터 유출될 수 있다.

4.9.1. 위조 리소스 서버에 의한 액세스 토큰 피싱

공격자는 자신만의 리소스 서버를 설정하고 클라이언트를 속여 다른 리소스 서버에 유효한 액세스 토큰을 그 서버로 보내게 할 수 있다 (Section 3의 공격자 (A1)(A5) 참조). 클라이언트가 유효한 액세스 토큰을 이 위조 리소스 서버로 보내면, 공격자는 그 토큰을 사용하여 리소스 소유자를 대신해 다른 서비스에 접근할 수 있다.

이 공격은 클라이언트가 개발 시점에 특정 리소스 서버 (및 그 URL) 하나에 바인딩되어 있지 않고, 클라이언트 인스턴스가 런타임에 리소스 서버 URL을 제공받는다고 가정한다. 이러한 종류의 지연 바인딩은 클라이언트가 표준화된 API를 구현하는 서비스(예: 이메일, 캘린더, eHealth 또는 오픈 뱅킹)를 사용하고, 클라이언트가 사용자 또는 관리자가 구성하는 상황에서 일반적이다.

4.9.2. 손상된 리소스 서버

공격자는 리소스 서버를 손상시켜 해당 배포의 리소스에 접근할 수 있다. 이러한 손상은 예를 들어 로그 파일에 대한 읽기 전용 접근과 같은 시스템에 대한 부분 접근부터 해당 서버에 대한 완전한 제어까지 다양할 수 있으며, 후자의 경우 모든 제어가 우회되고 모든 리소스에 접근할 수 있다. 공격자는 또한 손상된 시스템에 보관된 다른 액세스 토큰을 획득할 수 있으며, 그 토큰은 잠재적으로 다른 리소스 서버에 접근하는 데 유효할 수 있다.

서버 시스템을 강화하고 모니터링하여 서버 침해를 방지하는 것은 표준 운영 절차로 간주되므로 이 문서의 범위를 벗어난다. Section 4.9는 OAuth 관련 침해의 영향과 포착된 액세스 토큰의 리플레이에 초점을 둔다.

4.9.3. 대응책

악의적 행위자에 의한 액세스 토큰 리플레이에 대처하기 위해, 구현자는 다음 조치를 고려해야 한다.

  • Section 4.10.1에 설명된 발신자 제한 액세스 토큰을 사용해야 SHOULD 하며, 이는 공격자가 다른 리소스 서버에서 액세스 토큰을 리플레이하는 것을 방지한다. 공격자가 웹 서버 로그에 대한 읽기 전용 접근처럼 손상된 시스템에 부분적으로만 접근할 수 있는 경우, 발신자 제한 액세스 토큰은 손상된 시스템에서의 리플레이도 방지할 수 있다.
  • Section 4.10.2에 설명된 대상 제한을 사용해야 SHOULD 하며, 이는 포착된 액세스 토큰이 다른 리소스 서버에서 리플레이되는 것을 방지한다.
  • 리소스 서버는 액세스 토큰을 다른 민감한 비밀처럼 취급해야 MUST 하며, 이를 평문으로 저장하거나 전송해서는 안 된다.

첫 번째와 두 번째 권고사항은 액세스 토큰이 유출되는 다른 시나리오에도 적용된다(Section 3Attacker (A5) 참조).

4.10. 탈취된 액세스 토큰의 오용

액세스 토큰은 다양한 방식으로 공격자에게 탈취될 수 있다. 예를 들어 Sections 4.1, 4.2, 4.3, 4.44.9에 설명된 공격을 통해 탈취될 수 있다. 이러한 공격 중 일부는 각 절에 설명된 특정 보안 조치로 완화될 수 있다. 그러나 어떤 경우에는 이러한 조치가 충분하지 않거나 올바르게 구현되지 않는다. 따라서 인가 서버는 다음에 설명하는 것처럼 액세스 토큰이 발신자 제한되고 대상 제한되도록 보장해야 SHOULD 한다. 아키텍처와 성능상의 이유로 일부 배포에서는 이러한 조치를 사용하지 못할 수 있다.

4.10.1. 발신자 제한 액세스 토큰

이름이 시사하듯이, 발신자 제한 액세스 토큰은 액세스 토큰의 적용 범위를 특정 발신자로 한정한다. 이 발신자는 리소스 서버에서 해당 토큰이 수락되기 위한 전제조건으로 특정 비밀에 대한 지식을 입증해야 한다.

일반적인 흐름은 다음과 같다.

  1. 인가 서버는 이 특정 토큰을 특정 클라이언트에 바인딩하는 데이터를 액세스 토큰과 연결한다. 바인딩은 클라이언트의 신원을 활용할 수 있지만, 대부분의 경우 인가 서버는 클라이언트가 알고 있는 키 자료(또는 키 자료에서 파생된 데이터)를 활용한다.
  2. 이 키 자료는 어떻게든 배포되어야 한다. 키 자료가 인가 서버가 바인딩을 생성하기 전에 이미 존재하거나, 인가 서버가 임시 키를 생성할 수 있다. 기존 키 자료가 배포되는 방식은 서로 다른 접근 방식마다 다르다. 예를 들어 X.509 인증서를 사용할 수 있으며, 이 경우 배포는 등록 프로세스 중에 명시적으로 이루어진다. 또는 키 자료가 TLS 계층에서 생성되고 배포될 수 있으며, 이 경우 TLS 연결 설정 중에 자동으로 발생할 수 있다.
  3. 리소스 서버는 실제 proof-of-possession 검사를 구현해야 한다. 이는 일반적으로 애플리케이션 수준에서 수행되며, 종종 전송 계층(예: TLS)에서 제공되는 특정 자료와 연결된다. 리소스 서버는 또한 proof of possession의 리플레이가 불가능하도록 보장해야 한다.

proof of possession을 사용하는 발신자 제한 액세스 토큰의 두 가지 방법이 OAuth 워킹 그룹에 의해 정의되었으며 실제로 사용되고 있다.

  • "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens" [RFC8705]: 이 문서에 명시된 접근 방식은 클라이언트 인증과 발신자 제한 액세스 토큰 모두에 상호 TLS를 사용할 수 있게 한다. 발신자 제한 액세스 토큰의 목적에서 클라이언트는 자신의 공개 키 지문으로 리소스 서버에 식별된다. 액세스 토큰 요청을 처리하는 동안, 인가 서버는 TLS 스택에서 클라이언트의 공개 키를 얻고 그 지문을 해당 액세스 토큰과 연결한다. 리소스 서버도 같은 방식으로 TLS 스택에서 공개 키를 얻고, 그 지문을 액세스 토큰과 연결된 지문과 비교한다.
  • "OAuth 2.0 Demonstrating Proof of Possession (DPoP)" [RFC9449]: DPoP는 액세스 토큰과 갱신 토큰을 발신자 제한하기 위한 애플리케이션 수준 메커니즘을 제시한다. 이는 공개/개인 키 쌍과 애플리케이션 수준 서명에 기반한 proof-of-possession을 사용한다. DPoP는 공개 클라이언트와 함께 사용할 수 있으며, 기밀 클라이언트의 경우 어떤 클라이언트 인증 방법과도 결합될 수 있다.

공격자가 토큰과 키 자료 모두에 접근할 수 있게 되면 발신자 제한 토큰의 보안이 약화된다는 점에 유의한다. 이는 특히 손상된 클라이언트 소프트웨어와 cross-site scripting 공격 (클라이언트가 브라우저에서 실행되는 경우)에 해당한다. 키 자료가 하드웨어 또는 소프트웨어 보안 모듈에서 보호되거나 (TLS 스택처럼) 간접적으로만 접근 가능하다면, 발신자 제한 토큰은 적어도 클라이언트가 오프라인일 때, 즉 보안 모듈 또는 인터페이스를 공격자가 사용할 수 없을 때 토큰 사용을 방지한다. 이는 액세스 토큰뿐 아니라 갱신 토큰에도 적용된다 (Section 4.14 참조).

4.10.2. 대상 제한 액세스 토큰

대상 제한은 본질적으로 액세스 토큰을 특정 리소스 서버로 제한한다. 인가 서버는 액세스 토큰을 특정 리소스 서버와 연결하고, 리소스 서버는 의도된 대상을 검증해야 한다. 액세스 토큰이 의도된 대상 검증에 실패하면, 리소스 서버는 해당 요청의 처리를 거부한다.

일반적으로 대상 제한은 토큰 유출의 영향을 제한한다. 위조 리소스 서버의 경우, 아래에 설명된 것처럼 합법적인 리소스 서버에서 피싱된 액세스 토큰의 남용을 방지할 수도 있다.

대상은 논리적 이름 또는 물리적 주소(URL과 같은)로 표현될 수 있다. 피싱을 방지하려면 클라이언트가 요청을 보낼 실제 URL을 사용해야 한다. 피싱의 경우, 이 URL은 위조 리소스 서버를 가리킨다. 공격자가 합법적인 리소스 서버(다른 URL을 가짐)에서 액세스 토큰을 사용하려고 하면, 리소스 서버는 불일치(잘못된 대상)를 탐지하고 요청 처리를 거부한다.

인가 서버가 모든 리소스 서버의 URL을 알고 있는 배포에서는, 인가 서버가 알 수 없는 리소스 서버 URL에 대한 액세스 토큰 발급을 단순히 거부할 수 있다.

이것이 작동하려면 클라이언트가 의도한 리소스 서버를 인가 서버에 알려야 한다. 이를 위해 [RFC8707]의 메커니즘을 사용할 수 있거나, 정보를 scope 값(Section 3.3 of [RFC6749])에 인코딩할 수 있다.

URL 대신 리소스 서버의 X.509 인증서 지문을 대상 값으로 활용하는 것도 가능하다. 이 변형은 다른 CA에서 얻은 유효한 TLS 인증서를 사용해 합법적인 리소스 서버의 URL을 위조하려는 시도를 탐지할 수도 있다. 또한 인가 서버로부터 리소스 서버 URL을 숨기는 프라이버시 이점으로 간주될 수도 있다.

대상 제한은 클라이언트 측에서 암호화를 요구하지 않으므로 사용하기 더 쉬워 보일 수 있다. 하지만 모든 액세스 토큰이 특정 리소스 서버에 바인딩되므로, 클라이언트는 여러 리소스 서버에 접근할 때 리소스 서버별 액세스 토큰을 각각 하나씩 얻어야 한다. ([RFC8707]에 명시된 Resource indicators가 이를 달성하는 데 도움이 될 수 있다.) [TOKEN-BINDING]도 서로 다른 token-binding ID가 액세스 토큰과 연결되어야 했으므로 동일한 속성을 가졌다. 반면 OAuth 2.0을 위한 상호 TLS [RFC8705]를 사용하면 클라이언트가 여러 리소스 서버에서 액세스 토큰을 사용할 수 있다.

대상 제한 또는 일반적으로 말해 클라이언트가 액세스 토큰을 어디에서 사용하려는지를 인가 서버에 표시하는 것은 토큰 유출 방지의 범위를 넘어서는 추가 이점이 있다는 점에 유의해야 한다. 이를 통해 인가 서버는 해당 서버에 맞게 특별히 만들어진 형식과 내용을 가진 다른 액세스 토큰을 생성할 수 있다. 이는 구조화된 액세스 토큰을 사용하는 배포에서 큰 기능적 및 프라이버시 이점을 가진다.

4.10.3. 논의: 메타데이터를 통한 유출 방지

인가 서버는 액세스 토큰을 사용해도 안전한 위치에 관한 추가 정보를 클라이언트에 제공할 수 있다. 이 접근 방식과 그것이 권장되지 않는 이유를 다음에서 논의한다.

가장 단순한 형태에서는, 이는 인가 서버가 비표준 Authorization Server Metadata 매개변수 resource_servers를 사용한 다음 예시와 같이, 알려진 리소스 서버 목록을 공개해야 함을 의미한다.

HTTP/1.1 200 OK
Content-Type: application/json

{
  "issuer":"https://server.somesite.example",
  "authorization_endpoint":
    "https://server.somesite.example/authorize",
  "resource_servers":[
    "email.somesite.example",
    "storage.somesite.example",
    "video.somesite.example"
  ]
  ...
}

인가 서버는 토큰 응답에서 액세스 토큰이 유효한 URL(들)을 반환할 수도 있으며, 이는 예시와 비표준 반환 매개변수 access_token_resource_server로 설명된다.

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "access_token_resource_server":
    "https://hostedresource.somesite.example/path1",
...
}

이 완화 전략은 클라이언트가 보안 정책을 강제하고 액세스 토큰을 합법적인 대상으로만 보내도록 하는 데 의존한다. OAuth 관련 보안 연구 결과(예: [research.ubc][research.cmu] 참조)는 많은 클라이언트 구현이 state 검사와 같은 보안 제어를 구현하지 않거나 적절히 구현하지 못함을 나타낸다. 따라서 액세스 토큰 피싱을 방지하기 위해 클라이언트에 의존하는 것도 실패할 가능성이 높다. 또한 클라이언트와 인가/리소스 서버의 비율을 고려하면, 가능한 한 많은 보안 관련 로직을 이러한 서버로 이동하는 것이 더 실현 가능한 접근 방식으로 간주된다. 분명히 클라이언트는 전체 보안에 기여해야 한다. 그러나 Section 4.10.1Section 4.10.2에 설명된 것처럼, 관련 당사자 사이에서 더 나은 균형을 제공하는 대체 대응책이 있다.

4.11. 오픈 리디렉션

다음 공격은 인가 서버 또는 클라이언트에 오픈 리디렉터가 있을 때 발생할 수 있다. 이러한 엔드포인트는 예를 들어 사용자가 외부 웹사이트로 리디렉션되기 전에 메시지를 보여주거나, 로그인 프롬프트 등에 의해 중단되기 전에 사용자가 방문하려던 URL로 다시 리디렉션하기 위해 구현되는 경우가 있다.

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

클라이언트는 오픈 리디렉터를 노출해서는 MUST NOT 된다. 공격자는 오픈 리디렉터를 사용하여 클라이언트를 가리키는 URL을 만들고, 이를 활용하여 Section 4.1.2에 설명된 것처럼 인가 코드와 액세스 토큰을 유출시킬 수 있다. 또 다른 남용 사례는 클라이언트를 가리키는 것처럼 보이는 URL을 만드는 것이다. 이는 사용자가 URL을 신뢰하고 브라우저에서 따라가도록 속일 수 있다. 이는 피싱에 악용될 수 있다.

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

4.11.2. 오픈 리디렉터로서의 인가 서버

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

Section 4.1.2.1 of [RFC6749]은 이미 인가 서버가 client_idredirect_uri의 조합이 유효하지 않은 경우 사용자 에이전트를 자동으로 리디렉션해서는 MUST NOT 안 된다고 명시함으로써 오픈 리디렉션을 방지한다.

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

  1. 예를 들어 유효하지 않은 scope 값을 사용하여 의도적으로 오류가 있는 인가 요청을 보내고, 이로써 인가 서버가 사용자 에이전트를 자신의 피싱 사이트로 리디렉션하도록 지시한다.
  2. 공격자가 제어하는 client_idredirect_uri를 사용하여 의도적으로 유효한 인가 요청을 보낸다. 사용자가 인증한 후, 인가 서버는 사용자에게 요청에 대한 동의를 제공하라고 요청한다. 사용자가 요청의 문제를 알아차리고 요청을 거부하더라도, 인가 서버는 여전히 사용자 에이전트를 피싱 사이트로 리디렉션한다. 이 경우 사용자 에이전트는 사용자가 취한 동작과 관계없이 피싱 사이트로 리디렉션된다.
  3. 공격자가 제어하는 client_idredirect_uri를 사용하여 의도적으로 유효한 silent authentication 요청 (prompt=none)을 보낸다. 이 경우 인가 서버는 사용자 에이전트를 자동으로 피싱 사이트로 리디렉션한다.

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

인가 서버는 리디렉션 URI를 신뢰하는 경우에만 사용자 에이전트를 자동으로 리디렉션해야 SHOULD 한다. URI가 신뢰되지 않는 경우, 인가 서버는 사용자에게 알리고 올바른 결정을 사용자에게 맡길 수 MAY 있다.

4.12. 307 리디렉션

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

[RFC6749]에서는 이 목적을 위해 HTTP 상태 코드 302 (Found)가 사용되지만, "이 리디렉션을 수행하기 위해 user-agent를 통해 사용할 수 있는 다른 모든 방법도 허용된다". 대신 상태 코드 307이 리디렉션에 사용되면, 사용자 에이전트는 사용자의 자격 증명을 HTTP POST를 통해 클라이언트로 보낸다.

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

이 동작은 개발자에게 예상 밖일 수 있지만 Section 15.4.8 of [RFC9110]에 정의되어 있다. 이 상태 코드(307)는 사용자 에이전트가 POST 요청을 GET 요청으로 다시 작성하여 POST 요청 본문의 양식 데이터를 삭제할 것을 요구하지 않는다.

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

따라서 사용자의 자격 증명을 잠재적으로 포함하는 요청을 리디렉션하는 인가 서버는 리디렉션에 HTTP 307 상태 코드를 사용해서는 MUST NOT 된다. 이러한 요청에 대해 HTTP 리디렉션 (예: JavaScript가 아닌)을 사용하는 경우, 인가 서버는 HTTP 상태 코드 303 (See Other)을 사용해야 SHOULD 한다.

4.13. TLS 종료 리버스 프록시

HTTP 애플리케이션의 일반적인 배포 아키텍처는 TLS 연결을 종료하고 들어오는 요청을 해당 애플리케이션 서버 노드로 전달하는 리버스 프록시 뒤에 애플리케이션 서버를 숨기는 것이다.

이 절은 OAuth와 관련하여 이러한 배포 아키텍처의 일부 공격 각도를 강조하고 보안 제어에 대한 권고사항을 제공한다.

어떤 상황에서는 리버스 프록시가 추가 처리를 위해 보안 관련 데이터를 업스트림 애플리케이션 서버로 전달해야 한다. 예에는 요청 발신자의 IP 주소, token-binding ID 및 인증된 TLS 클라이언트 인증서가 포함된다. 이 데이터는 보통 업스트림 요청에 추가되는 HTTP 헤더로 전달된다. 헤더는 종종 사용자 정의 애플리케이션별 헤더이지만, 클라이언트 인증서와 클라이언트 인증서 체인을 위한 표준화된 헤더 필드는 [RFC9440]에 정의되어 있다.

리버스 프록시가 외부에서 전송된 헤더를 그대로 통과시키면, 공격자는 보안 제어를 우회하기 위해 위조된 헤더 값을 프록시를 통해 애플리케이션 서버로 직접 보내려고 시도할 수 있다. 예를 들어, 리버스 프록시는 X-Forwarded-For 헤더를 수락하고 인바운드 요청의 출처를 단순히 추가(목록으로 만듦)하는 것이 표준 관행이다. 애플리케이션 서버에서 수행되는 로직에 따라 공격자는 허용된 IP 주소를 헤더에 단순히 추가하여 보호를 무용지물로 만들 수 있다.

따라서 리버스 프록시는 애플리케이션 서버의 보안과 관련된 모든 헤더 값의 진정성과 무결성을 보장하기 위해 모든 인바운드 요청을 정화해야 MUST 한다.

공격자가 프록시와 애플리케이션 서버 사이의 내부 네트워크에 접근할 수 있다면, 기존 보안 제어를 우회하려고 시도할 수도 있다. 따라서 통신 엔티티의 진정성을 보장하는 것이 필수적이다. 또한 리버스 프록시와 애플리케이션 서버 사이의 통신 링크는 메시지 도청, 주입 및 리플레이로부터 보호되어야 MUST 한다.

4.14. 갱신 토큰 보호

갱신 토큰은 새 액세스 토큰을 얻는 편리하고 사용자 친화적인 방법이다. 또한 인가 서버가 수명이 짧고 범위가 축소된 액세스 토큰을 발급할 수 있게 하므로, 액세스 토큰 유출의 잠재적 영향을 줄여 OAuth의 보안에도 기여한다.

4.14.1. 논의

갱신 토큰은 특정 클라이언트에 부여된 전체 접근 범위를 나타내며, 특정 리소스에 추가로 제한되지 않기 때문에 공격자에게 매력적인 대상이다. 공격자가 갱신 토큰을 유출하고 성공적으로 리플레이할 수 있다면, 공격자는 액세스 토큰을 만들어 이를 사용해 리소스 소유자를 대신하여 리소스 서버에 접근할 수 있다.

[RFC6749]는 이미 다음을 요구함으로써 견고한 기본 보호를 제공한다.

  • 전송 및 저장 중 갱신 토큰의 기밀성,
  • 인가 서버와 클라이언트 사이의 TLS 보호 연결을 통한 갱신 토큰 전송,
  • 가능하다면 인가 서버가 갱신 토큰과 특정 클라이언트의 바인딩을 유지하고 검사하며, 토큰 갱신 중 이 클라이언트를 인증할 것, 그리고
  • 갱신 토큰이 생성, 수정 또는 추측될 수 없을 것.

[RFC6749]는 또한 해당 오류 코드와 응답 동작을 정의함으로써 갱신 토큰 만료와 취소, 그리고 갱신 토큰 회전과 같은 추가적인(구현별) 보안 조치의 기반도 마련한다.

이 명세는 [RFC6749]의 범위를 넘어서는 권고사항과 명확화를 제공한다.

4.14.2. 권고사항

인가 서버는 위험 평가에 근거하여 특정 클라이언트에 갱신 토큰을 발급할지 여부를 결정해야 MUST 한다. 인가 서버가 갱신 토큰을 발급하지 않기로 결정하면, 클라이언트는 인가 코드 그랜트 유형과 같은 다른 그랜트 유형을 활용하여 새 액세스 토큰을 얻을 수 MAY 있다. 이러한 경우 인가 서버는 사용자 경험을 최적화하기 위해 쿠키와 지속적 그랜트를 활용할 수 있다.

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

기밀 클라이언트의 경우, [RFC6749]는 이미 갱신 토큰이 해당 토큰이 발급된 클라이언트에 의해서만 사용될 수 있음을 요구한다.

인가 서버는 공개 클라이언트에 대해 악의적 행위자의 갱신 토큰 리플레이를 탐지하기 위해 다음 방법 중 하나를 활용해야 MUST 한다.

  • 발신자 제한 갱신 토큰: 인가 서버는 예를 들어 [RFC8705] 또는 [RFC9449]를 활용하여 갱신 토큰을 특정 클라이언트 인스턴스에 암호학적으로 바인딩한다.
  • 갱신 토큰 회전: 인가 서버는 모든 액세스 토큰 갱신 응답마다 새 갱신 토큰을 발급한다. 이전 갱신 토큰은 무효화되지만, 그 관계에 관한 정보는 인가 서버에 의해 유지된다. 갱신 토큰이 손상되어 이후 공격자와 합법적인 클라이언트가 모두 사용하게 되면, 둘 중 하나가 무효화된 갱신 토큰을 제시하게 되고, 이는 인가 서버에 침해 사실을 알린다. 인가 서버는 어느 당사자가 무효한 갱신 토큰을 제출했는지 결정할 수 없지만, 활성 갱신 토큰을 취소한다. 이는 합법적인 클라이언트가 새 인가 그랜트를 얻도록 강제하는 대가로 공격을 중단시킨다.

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

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

  • 비밀번호 변경 또는
  • 인가 서버에서의 로그아웃.

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

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

리소스 서버는 액세스 토큰이 발급된 리소스 소유자의 신원에 기반하거나, 클라이언트 자격 증명 그랜트에서의 클라이언트 신원에 기반하여 접근 제어 결정을 내릴 수 있다. 예를 들어, [RFC9068] (JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens)은 다음과 같이 정의된 sub 클레임을 포함하는 액세스 토큰용 데이터 구조를 설명한다.

In cases of access tokens obtained through grants where a resource owner is involved, such as the authorization code grant, the value of "sub" SHOULD correspond to the subject identifier of the resource owner. In cases of access tokens obtained through grants where no resource owner is involved, such as the client credentials grant, the value of "sub" SHOULD correspond to an identifier the authorization server uses to indicate the client application.

두 옵션이 모두 가능하면, 리소스 서버는 클라이언트의 신원을 리소스 소유자의 신원으로 오인할 수 있다. 예를 들어, 클라이언트가 인가 서버에 등록할 때 자신의 client_id를 선택할 수 있다면, 악의적인 클라이언트는 이를 리소스 소유자를 식별하는 값 (예: OpenID Connect가 사용되는 경우 sub 값)으로 설정할 수 있다. 리소스 서버가 리소스 소유자의 관여로 얻은 액세스 토큰과 그렇지 않은 액세스 토큰을 적절히 구분할 수 없다면, 클라이언트는 실수로 리소스 소유자에 속한 리소스에 접근할 수 있게 될 수 있다.

이 공격은 [RFC9068]를 사용하는 구현뿐 아니라 유사한 맞춤형 해결책에도 잠재적으로 영향을 미친다.

4.15.1. 대응책

인가 서버는 클라이언트 ID와 사용자 식별자에 대한 공통 네임스페이스가 존재하는 경우, 위의 Section 4.15에 표시된 [RFC9068]sub 클레임 예처럼, 클라이언트가 자신의 client_id 또는 진짜 리소스 소유자와 혼동을 일으킬 수 있는 다른 클레임에 영향을 미치도록 허용해서는 SHOULD NOT 된다. 이를 피할 수 없는 경우, 인가 서버는 리소스 서버가 두 종류의 액세스 토큰을 구분할 수 있는 다른 수단을 제공해야 MUST 한다.

4.16. 클릭재킹

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

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

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

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

CSP를 사용하면 인가 서버는 단일 응답 헤더 필드에 여러 출처를 지정하고 유연한 패턴을 사용해 이를 제한할 수 있다 (자세한 내용은 [W3C.CSP-2] 참조). CSP 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
...

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

4.17. 브라우저 내 통신 흐름에 대한 공격

인가 응답이 HTTP 리디렉션 대신 postMessage [WHATWG.postmessage_api]와 같은 브라우저 내 통신 기법으로 전송되는 경우, 메시지가 악의적인 출처로 부주의하게 전송되거나 악의적인 출처에서 주입될 수 있다.

4.17.1. 예시

브라우저 내 통신을 사용하는 공격의 다음 비규범적 의사코드 예시는 [research.rub]에 설명되어 있다.

4.17.1.1. 수신자 출처의 불충분한 제한

postMessage를 통해 인가 응답 또는 토큰 응답을 보낼 때, 인가 서버는 클라이언트의 출처 대신 와일드카드 출처 "*"로 응답을 보낸다. 응답이 전송되는 창이 공격자에 의해 제어되는 경우, 공격자는 응답을 읽을 수 있다.

window.opener.postMessage(
  {
    code: "ABC",
    state: "123"
  },
  "*" // any website in the opener window can receive the message
)
4.17.1.2. 불충분한 URI 검증

postMessage를 통해 인가 응답 또는 토큰 응답을 보낼 때, 인가 서버는 수신자 출처를 리디렉션 URI와 대조하여 검사하지 않고, 대신 예를 들어 공격자가 제공한 출처로 응답을 보낼 수 있다. 이는 Section 4.1에 설명된 공격과 유사하다.

window.opener.postMessage(
  {
    code: "ABC",
    state: "123"
  },
  "https://attacker.example" // attacker-provided value
)
4.17.1.3. 발신자 출처에 대한 불충분한 검증 이후 주입

postMessage를 통해 인가 응답 또는 토큰 응답을 기대하는 클라이언트가 메시지의 발신자 출처를 검증하지 않을 수 있다. 이는 공격자가 인가 응답 또는 토큰 응답을 클라이언트에 주입할 수 있게 할 수 있다.

악의적으로 주입된 인가 응답의 경우, 이 공격은 Section 4.7에 설명된 CSRF 공격의 변형이다. Section 4.7에 설명된 대응책은 이 공격에도 적용된다.

악의적으로 주입된 토큰 응답의 경우, Section 4.10.1에 설명된 발신자 제한 액세스 토큰이 일부 상황에서 공격을 방지할 수 있지만, 일반적으로는 Section 4.17.2에 설명된 추가 대응책이 필요하다.

4.17.2. 권고사항

클라이언트 수신자 출처를 사전 등록된 출처와 비교할 때, 인가 서버는 Section 4.1.3에 설명된 것처럼 정확한 문자열 일치를 사용해야 MUST 한다. 인가 서버는 다음 비규범적 예시처럼 신뢰할 수 있는 클라이언트 수신자 출처로 postMessage를 보내야 MUST 한다.

window.opener.postMessage(
  {
    code: "ABC",
    state: "123"
  },
  "https://client.example" // use explicit client origin
)

postMessage의 "*"와 같은 와일드카드 출처는 사용해서는 MUST NOT 된다. 공격자가 이를 사용하여 피해자의 브라우저 내 메시지를 악의적인 출처로 유출시킬 수 있기 때문이다. 두 조치 모두 인가 코드와 액세스 토큰의 유출 방지에 기여한다(Section 4.1 참조).

클라이언트는 클라이언트 수신자 엔드포인트에서 브라우저 내 메시지의 주입을 방지해야 MUST 한다. 클라이언트는 다음 비규범적 예시처럼 브라우저 내 메시지의 시작자 출처를 인가 서버 출처와 비교하기 위해 정확한 문자열 일치를 사용해야 MUST 한다.

window.addEventListener("message", (e) => {
  // validate exact authorization server origin
  if (e.origin === "https://honest.as.example") {
    // process e.data.code and e.data.state
  }
})

브라우저 내 통신 흐름은 다른 통신 기법 (즉, HTTP redirect 대신 postMessage)을 적용할 뿐이므로, Section 2.1에 나열된 인가 응답 보호 조치가 모두 동일하게 적용되어야 MUST 한다.

5. IANA 고려사항

이 문서에는 IANA 조치가 없다.

6. 보안 고려사항

보안 고려사항은 Sections 2, 34에 설명되어 있다.

7. 참고 문헌

7.1. 규범적 참고 문헌

[BCP195]
Best Current Practice 195, <https://www.rfc-editor.org/info/bcp195>.
작성 시점에 이 BCP는 다음을 포함한다.
Moriarty, K. and S. Farrell, "TLS 1.0 및 TLS 1.1 폐기", BCP 195, RFC 8996, DOI 10.17487/RFC8996, , <https://www.rfc-editor.org/info/rfc8996>.
Sheffer, Y., Saint-Andre, P., and T. Fossati, "Transport Layer Security (TLS) 및 Datagram Transport Layer Security (DTLS)의 안전한 사용을 위한 권고사항", BCP 195, RFC 9325, DOI 10.17487/RFC9325, , <https://www.rfc-editor.org/info/rfc9325>.
[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>.
[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 Token 사용", RFC 6750, DOI 10.17487/RFC6750, , <https://www.rfc-editor.org/info/rfc6750>.
[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>.
[RFC7521]
Campbell, B., Mortimore, C., Jones, M., and Y. Goland, "OAuth 2.0 클라이언트 인증 및 인가 그랜트를 위한 Assertion Framework", 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>.
[RFC8252]
Denniss, W. and J. Bradley, "네이티브 앱을 위한 OAuth 2.0", BCP 212, RFC 8252, DOI 10.17487/RFC8252, , <https://www.rfc-editor.org/info/rfc8252>.
[RFC8414]
Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 Authorization Server Metadata", RFC 8414, DOI 10.17487/RFC8414, , <https://www.rfc-editor.org/info/rfc8414>.
[RFC8705]
Campbell, B., Bradley, J., Sakimura, N., and T. Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", RFC 8705, DOI 10.17487/RFC8705, , <https://www.rfc-editor.org/info/rfc8705>.
[RFC9068]
Bertocci, V., "OAuth 2.0 액세스 토큰을 위한 JSON Web Token (JWT) 프로파일", RFC 9068, DOI 10.17487/RFC9068, , <https://www.rfc-editor.org/info/rfc9068>.

7.2. 정보성 참고 문헌

[arXiv.1508.04324v2]
Mladenov, V., Mainka, C., and J. Schwenk, "현대 Single Sign-On 프로토콜의 보안: OpenID Connect의 2차 취약점", arXiv:1508.04324v2, DOI 10.48550/arXiv.1508.04324, , <https://arxiv.org/abs/1508.04324v2/>.
[arXiv.1601.01229]
Fett, D., Küsters, R., and G. Schmitz, "OAuth 2.0의 포괄적인 형식 보안 분석", arXiv:1601.01229, DOI 10.48550/arXiv.1601.01229, , <https://arxiv.org/abs/1601.01229/>.
[arXiv.1704.08539]
Fett, D., Küsters, R., and G. Schmitz, "Web SSO 표준 OpenID Connect: 심층 형식 보안 분석 및 보안 지침", arXiv:1704.08539, DOI 10.48550/arXiv.1704.08539, , <https://arxiv.org/abs/1704.08539/>.
[arXiv.1901.11520]
Fett, D., Hosseyni, P., and R. Küsters, "OpenID Financial-grade API의 광범위한 형식 보안 분석", arXiv:1901.11520, DOI 10.48550/arXiv.1901.11520, , <https://arxiv.org/abs/1901.11520/>.
[bug.chromium]
"새 탭으로 링크를 열 때 Referer 헤더에 URL 프래그먼트가 포함됨", Chromium Issue Tracker, Issue ID: 40076763, <https://issues.chromium.org/issues/40076763>.
[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>.
[OAUTH-V2.1]
Hardt, D., Parecki, A., and T. Lodderstedt, "OAuth 2.1 인가 프레임워크", 진행 중인 작업, Internet-Draft, draft-ietf-oauth-v2-1-12, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12>.
[OAuth.Post]
Jones, M. and B. Campbell, "OAuth 2.0 Form Post Response Mode", The OpenID Foundation, , <https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html>.
[OAuth.Responses]
de Medeiros, B., Ed., Scurtescu, M., Tarjan, P., and M. Jones, "OAuth 2.0 Multiple Response Type Encoding Practices", The OpenID Foundation, , <https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html>.
[OpenID.Core]
Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and C. Mortimore, "OpenID Connect Core 1.0 incorporating errata set 2", The OpenID Foundation, , <https://openid.net/specs/openid-connect-core-1_0.html>.
[OpenID.Discovery]
Sakimura, N., Bradley, J., Jones, M., and E. Jay, "OpenID Connect Discovery 1.0 incorporating errata set 2", The OpenID Foundation, , <https://openid.net/specs/openid-connect-discovery-1_0.html>.
[OpenID.JARM]
Lodderstedt, T. and B. Campbell, "Financial-grade API: OAuth 2.0을 위한 JWT Secured Authorization Response Mode (JARM)", The OpenID Foundation, , <https://openid.net/specs/openid-financial-api-jarm.html>.
[owasp.redir]
OWASP Foundation, "검증되지 않은 리디렉션 및 포워드 치트 시트", OWASP Cheat Sheet Series, <https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html>.
[research.cmu]
Chen, E., Pei, Y., Chen, S., Tian, Y., Kotcher, R., and P. Tague, "모바일 애플리케이션 개발자를 위한 OAuth 해설", CCS '14: Proceedings of the 2014 ACM SIGSAC Conference on Computer and Communications Security, pp. 892-903, DOI 10.1145/2660267.2660323, , <https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/OAuthDemystified.pdf>.
[research.jcs_14]
Bansal, C., Bhargavan, K., Delignat-Lavaud, A., and S. Maffeis, "형식 분석을 통한 웹사이트 인가의 구체적 공격 발견", Journal of Computer Security, vol. 22, no. 4, pp. 601-657, DOI 10.3233/JCS-140503, , <https://www.doc.ic.ac.uk/~maffeis/papers/jcs14.pdf>.
[research.rub]
Jannett, L., Mladenov, V., Mainka, C., and J. Schwenk, "DISTINCT: 이중 창 Single Sign-On의 브라우저 내 통신을 사용한 신원 도용", CCS '22: Proceedings of the 2022 ACM SIGSAC Conference on Computer and Communications Security, DOI 10.1145/3548606.3560692, , <https://dl.acm.org/doi/pdf/10.1145/3548606.3560692>.
[research.rub2]
Fries, C., "실제 OpenID Connect 구현의 보안 분석", 석사 논문, Ruhr-Universität Bochum (RUB), , <https://www.nds.rub.de/media/ei/arbeiten/2021/05/03/masterthesis.pdf>.
[research.ubc]
Sun, S.-T. and K. Beznosov, "악마는 (구현) 세부사항에 있다: OAuth SSO 시스템의 경험적 분석", Proceedings of the 2012 ACM conference on Computer and communications security (CCS '12), pp. 378-390, DOI 10.1145/2382196.2382238, , <https://css.csail.mit.edu/6.858/2012/readings/oauth-sso.pdf>.
[research.udel]
Liu, D., Hao, S., and H. Wang, "당신의 모든 DNS 레코드는 우리를 가리킨다: Dangling DNS Records의 보안 위협 이해", CCS '16: Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security, pp. 1414-1425, DOI 10.1145/2976749.2978387, , <https://dl.acm.org/doi/pdf/10.1145/2976749.2978387>.
[RFC2119]
Bradner, S., "요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC7591]
Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and P. Hunt, "OAuth 2.0 동적 클라이언트 등록 프로토콜", RFC 7591, DOI 10.17487/RFC7591, , <https://www.rfc-editor.org/info/rfc7591>.
[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>.
[RFC8174]
Leiba, B., "RFC 2119 핵심 단어의 대문자와 소문자의 모호성", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8707]
Campbell, B., Bradley, J., and H. Tschofenig, "OAuth 2.0을 위한 Resource Indicators", RFC 8707, DOI 10.17487/RFC8707, , <https://www.rfc-editor.org/info/rfc8707>.
[RFC9101]
Sakimura, N., Bradley, J., and M. Jones, "OAuth 2.0 인가 프레임워크: JWT-Secured Authorization Request (JAR)", RFC 9101, DOI 10.17487/RFC9101, , <https://www.rfc-editor.org/info/rfc9101>.
[RFC9110]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/info/rfc9110>.
[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>.
[RFC9207]
Meyer zu Selhausen, K. and D. Fett, "OAuth 2.0 인가 서버 발급자 식별", RFC 9207, DOI 10.17487/RFC9207, , <https://www.rfc-editor.org/info/rfc9207>.
[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>.
[RFC9440]
Campbell, B. and M. Bishop, "Client-Cert HTTP 헤더 필드", RFC 9440, DOI 10.17487/RFC9440, , <https://www.rfc-editor.org/info/rfc9440>.
[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>.
[TOKEN-BINDING]
Jones, M., Campbell, B., Bradley, J., and W. Denniss, "OAuth 2.0 Token Binding", 진행 중인 작업, Internet-Draft, draft-ietf-oauth-token-binding-08, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-token-binding-08>.
[W3C.CSP-2]
West, M., Barth, A., and D. Veditz, "Content Security Policy Level 2", W3C Recommendation, , <https://www.w3.org/TR/2016/REC-CSP2-20161215/>. 최신 버전은 <https://www.w3.org/TR/CSP2/>에서 이용 가능하다.
[W3C.webappsec-referrer-policy]
Eisinger, J. and E. Stark, "Referrer Policy", , <https://www.w3.org/TR/2017/CR-referrer-policy-20170126/>. 최신 버전은 <https://www.w3.org/TR/referrer-policy/>에서 이용 가능하다.
[W3C.WebAuthn]
Hodges, J., Jones, J.C., Jones, M.B., Kumar, A., and E. Lundberg, "Web Authentication: Public Key Credentials Level 2에 접근하기 위한 API", W3C Recommendation, , <https://www.w3.org/TR/2021/REC-webauthn-2-20210408/>. 최신 버전은 <https://www.w3.org/TR/webauthn-2/>에서 이용 가능하다.
[W3C.WebCrypto]
Watson, M., Ed., "Web Cryptography API", W3C Recommendation, , <https://www.w3.org/TR/2017/REC-WebCryptoAPI-20170126/>. 최신 버전은 <https://www.w3.org/TR/WebCryptoAPI/>에서 이용 가능하다.
[WHATWG.CORS]
WHATWG, "CORS protocol", Fetch: Living Standard, Section 3.2, , <https://fetch.spec.whatwg.org/#http-cors-protocol>.
[WHATWG.postmessage_api]
WHATWG, "Cross-document messaging", HTML: Living Standard, Section 9.3, , <https://html.spec.whatwg.org/multipage/web-messaging.html#web-messaging>.

감사의 말

귀중한 피드백을 주신 Brock Allen, Annabelle Richard Backman, Dominick Baier, Vittorio Bertocci, Brian Campbell, Bruno Crispo, William Dennis, George Fletcher, Matteo Golinelli, Dick Hardt, Joseph Heenan, Pedram Hosseyni, Phil Hunt, Tommaso Innocenti, Louis Jannett, Jared Jennings, Michael B. Jones, Engin Kirda, Konstantin Lapine, Neil Madden, Christian Mainka, Jim Manico, Nov Matake, Doug McDorman, Karsten Meyer zu Selhausen, Ali Mirheidari, Vladislav Mladenov, Kaan Onarioglu, Aaron Parecki, Michael Peck, Johan Peeters, Nat Sakimura, Guido Schmitz, Jörg Schwenk, Rifaat Shekh-Yusef, Travis Spencer, Petteri Stenius, Tomek Stojecki, David Waite, Tim WürteleHans Zandbelt에게 감사드린다.

저자 주소

Torsten Lodderstedt
SPRIND
John Bradley
Yubico
Andrey Labunets
독립 연구자
Daniel Fett
Authlete