OAuth 프로토콜을 사용하기 전에, 클라이언트는 먼저 인가 서버에 자신을 등록해야 한다. 이 등록 과정은 이 명세에서 구체적인 방법까지는 정의하지 않지만, 보통은 인가 서버가 제공하는 웹 화면(HTML 등록 폼)을 통해 개발자가 직접 정보를 입력하는 방식으로 이루어진다.
클라이언트 등록은 항상 클라이언트 프로그램과 인가 서버가 자동으로 직접 통신해야만 가능한 것은 아니다. 인가 서버가 이를 지원하는 경우에는, 신뢰를 형성하고 클라이언트의 필요한 정보를 얻기 위해 다른 방식들을 사용할 수도 있다. 예를 들어, 클라이언트가 자체적으로 발급한 정보나 제3자가 발급한 확인 정보(assertion)를 제출하여 등록할 수도 있고, 인가 서버가 신뢰된 경로를 통해 클라이언트를 찾아내는 방식(discovery)으로 등록을 완료할 수도 있다.
좀 더 풀어서 진행
- 등록 = API 자동 통신이라고 고정해서 생각하지 말고 사람이 직접 웹에서 등록하는 방식도 있고 자동 방식이 있을 수 있다.
- 인가 서버가 허용한다면 "이 클라이언트를 믿을 수 있는가?", "이 클라이언트의 정보는 무엇인가?"를 다른 방법으로 확인해도 된다.
- assertion는 나 이런 앱이야 라고 증명서를 제출하는 방식, discovery은 인가 서버가 이 클라이언트가 누구인지를 신뢰된 채널을 통해 직접 확인하는 방식
클라이언트를 등록할 때, 클라이언트 개발자는 반드시 다음을 수행해야 한다.
- 섹션 2.1에 설명된 대로 클라이언트 유형을 지정
- 섹션 3.1.2에 설명된 대로 클라이언트 리다이렉션 URI를 제공
- 인가 서버가 요구하는 기타 모든 정보를 포함해야한다(예 : 애플리케이션 이름, 웹사이트, 설명, 로고 이미지, 법적 약관에 대한 동의).
쉽게 말하면 OAuth를 쓰려면, 우리 앱(클라이언트)을 인가 서버에 미리 등록 해두는 과정이 필요하다는 말
2.1 클라이언트 유형(Client Types)
OAuth에서는 이 앱이 비밀정보를 안전하게 숨길 수 있느냐를 기준으로 클라이언트를 두 종류로 나눈다.
1. 기밀 클라이언트(confidential)
- 비밀을 숨길 수 있는 앱
- 백엔드 서버, 서버에서만 OAuth 토큰을 주고 받는 구조
2. 공개 클라이언트(public)
- 비밀을 숨길 수 없는 앱
- 사용자의 기기에서 실행되는 앱, 소스 코드나 설정이 사용자에게 보이는 앱
- 브라우저에서 실행되는 SPA, 모바일 앱
클라이언트 유형 지정은
- 인가 서버가 정의한 안전한 인증 기준
- 클라이언트 자격 증명이 노출될 수 있는 허용 수준
을 기준으로 한다. 인가 서버는 클라이언트 유형에 대해 임의로 가정해서는 안된다.
"이 앱이 기밀인지 공개인지"는 인가 서버 기준에 따라 판단된다. 인가 서버는 "이건 서버일 거야" 같은 추측을 하면 안된다. 즉, 클라이언트가 스스로 주장해도 최종 판단은 인가 서버가 함.
클라이언트는 각각 다른 클라이언트 유형과 보안 환경을 가진 여러 구성 요소로 분산되어 구현될 수도 있다.
하나의 서비스가 서버 부분 + 브라우저 부분처럼 나뉠 수도 있다는 말
예시로 백엔드는 서버 -> 기밀 클라이언트 프론트엔드는 브라우저 -> 공개 클라이언트
현대 웹 서비스 구조를 그대로 말한 것
인가 서버가 이러한 클라이언트를 지원하지 않거나 등록에 대한 지침을 제공하지 않는 경우 클라이언트는 각 구성 요소를 별도의 클라이언트로 등록해야한다.
인가 서버가 "복합 구조 클라이언트"를 이해 못하면 서버용, 브라우저용을 각각 다른 클라이언트로 등록해라 -> 실무에서 client_id가 여러 개 생기는 이유
이 명세는 현실에서 많이 쓰는 앱 유형 3가지를 기준으로 만들어졌다
1. 웹 애플리케이션(Web application)
- 웹 애플리케이션의 OAuth 처리 로직은 전부 서버에서 실행된다는 뜻 (OAuth 요청, access token 발급, client_secret 사용) 이런 건 전부 백엔드 서버가 담당 그래서 비밀 정보를 안전하게 숨길 수 있음 -> 기밀 클라이언트
- 사용자는 서버에 직접 OAuth 요청을 보내는 게 아니라 화면만 본다
- 사용자는 브라우저(사용자 에이전트)로 접속
- 서버가 만든 HTML 화면을 봄
- 버튼 클릭 -> 서버로 요청 전달
- client_secret, access_token 이런 게 서버에만 있기에 브라우저, JS, 사용자에게는 절대 안 보임 -> 비밀 정보는 절대 유출되지 않음
웹 애플리케이션은 OAuth 처리와 비밀 정보를 전부 서버에서 관리하고, 사용자는 단지 브라우저 화면을 통해 접근하기 때문에 안전한 기밀 클라이언트이다.
2. 사용자 에이전트 기반 애플리케이션(user-agent-based)
- 서버에서 내려준 클라이언트 프로그램 코드가 사요자의 기기 안에서 직접 실행되는 구조의 애플리케이션
- 사용자 에이전트란 보통 웹 브라우저를 의미하며 브라우저 내부에서 JavaScript 코드 형태로 동작
구조
애플리케이션의 코드와 실행 환경이 전부 사용자의 장치에 있기 때문에, OAuth 통신에 사용되는 프로토콜 데이터나 자격 증명 역시 사용자의 환경 안에 놓이게 된다. 따라서 사용자가 개발자 도구를 열거나 네트워크 요청을 확인하면, 이러한 값들이 비교적 쉽게 노출될 수 있다. 이 때문에 이런 애플리케이션은 비밀 정보를 안전하게 숨길 수 없는 공개 클라이언트로 분류된다.
이러한 단점에도 불구하고 애플리케이션이 브라우저 안에서 실행되기 떄문에 인가를 요청할 때 브라우저가 원래부터 제공하는 기능(ex : 페이지 이동, 주소 변경, 새 창 열기 같은 동작)을 별도의 복잡한 처리 없이 그대로 활용 가능 OAuth에서 자주 사용되는 리다이렉션 기반 인가 흐름은 이런 브라우저 환경과 매우 잘 맞는다.
사용자 에이전트 기반 애플리케이션은 보안상 불리하지만, 브라우저 환경에 최적화된 OAuth 클라이언트 구조를 설명한 것이다.
3. 네이티브 애플리케이션 (native application)
- 사용자의 스마트폰이나 컴퓨터 같은 개인 장치에 직접 설치되어 실행되는 애플리케이션 예를 들면 안드로이드 앱 or IOS 앱
- 이런 앱은 사용자 장치 안에서 실행되기 때문에 공개 클라이언트로 분류
구조
애플리케이션이 사용하는 프로토콜 데이터나 자격 증명에 사용자가 접근할 수 있다고 가정한다. 즉, 사용자가 앱 파일을 분석하거나 장치를 직접 다루면, 앱 안에 들어 있는 정보는 언제든지 들여다볼 수 있다고 보는 것이다. 그래서 애플리케이션 코드 안에 미리 넣어둔 클라이언트 인증 자격 증명(client_secret 같은 값)은, 결국 추출될 수 있다고 전제한다.
하지만 모든 자격 증명이 다 같은 수준으로 위험한 것은 아니다. 앱이 실행되는 동안 동적으로 발급되는 액세스 토큰이나 리프레시 토큰은, 앱의 실행 환경이나 운영체제의 보호 기능을 통해 어느 정도 안전하게 보호될 수 있다. 예를 들어, 이러한 토큰들은 네트워크를 통해 마음대로 유출되거나, 앱이 통신하는 서버 중 하나가 악의적인 서버라고 해도 쉽게 빼앗기지 않도록 보호될 수 있다.
최소한의 보안 수준으로, 이러한 토큰들은 애플리케이션이 통신하는 과정에서 만날 수 있는 악의적인 서버로부터는 보호된다고 가정한다. 그리고 플랫폼에 따라서는, 같은 장치 안에 설치된 다른 애플리케이션들로부터도 토큰이 보호될 수 있다고 본다. 예를 들어, 운영체제가 제공하는 보안 저장소를 사용하는 경우가 이에 해당한다.
2.2 클라이언트 식별자(Client Identifier)
인가 서버는 등록된 클라이언트에게 클라이언트 식별자(client identifier)를 발급한다.
- 이 식별자는 클라이언트가 제공한 등록 정보를 나타내는 고유한 문자열이다.
- 클라이언트 식별자는 비밀 값이 아니며 리소스 소유자에게 노출된다.
- 클라이언트 식별자는 이 값 하나만으로는 클라이언트 인증 x
- 이 식별자는 같은 인가 서버에서만 고유함
클라이언트 식별자 문자열 크기(길이)는 명세하지 않는다.
- 클라이언트는 -> 이 식별자에 대해 크기를 임의로 가정하는 것은 안 된다.
- 인가 서버는 자신이 발급하는 모든 식별자의 크기를 문서로 알려주는 것이 바람직
2.3 클라이언트 인증(Client Authentication)
기밀 클라이언트일 경우
- 인가 서버와 클라이언트는 서로 이 클라이언트가 맞는지 확인하기 위한 인증 방법을 하나 정해서 사용
- 인가 서버는 자기 기준에서 안전하다고 판단되기만 하면 어떤 방식의 클라이언트 인증이든 받아들일 수 있다.
기밀 클라이언트는 보통 인가 서버에 자신을 증명하기 위해 쓰는 고유한 자격 증명 세트를 발급하거나 설정(ex : 비밀번호, 공개키/개인키 쌍) 즉 서버에만 숨겨둘 수 있는 인증 수단을 가지고 있다는 말
인가 서버는 공개 클라이언트와도 클라이언트 인증을 설정할 수 있다.
but 인가 서버는 클라이언트를 식별하기 위한 목적으로 공개 클라이언트의 인증에 의존 X
클라이언트는 각 요청마다 하나를 촉화하는 인증 방법을 사용해서는 안된다.
2.3.1 클라이언트 비밀번호(Client Password)
클라이언트가 클라이언트 비밀번호를 가지고 있다면 인가 서버에 자신을 증명하기 위해 FRC 2617에 정의된 HTTP Basic 인증 방식을 사용할 수 있다.
이때 부록 B에 따라 application/x-www-form-urlencoded라는 정해진 인코딩 방식으로 변환해서 보낸다.
- 클라이언트 식별자(client_id)는 이 방식으로 인코딩한 뒤 HTTP Basic 인증에서 아이디(username) 자리에 넣고
- 클라이언트 비밀번호(client_secret)는 같은 방식으로 인코딩해서 비밀번호(password) 자리에 넣는다.
- 인가 서버는 클라이언트 비밀번호를 발급해 준 클라이언트라면 이런 HTTP Basic 인증 방식으로 들어오는 요청을 반드시 처리할 수 있어야한다.
예시
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
다른 방법으로는 client_id와 client_secret을 요청 본문(request-body)에 클라이언트 자격 증명을 포함하는 방식을 지원할 수도 있다.
- client_id
- 반드시 포함, 섹션 2.2에서 설명된 등록 과정 중 클라이언트에게 발급된 클라이언트 식별자
- client_secret
- 반드시 포함, 클라이언트 비밀 값, 클라이언트 비밀 값이 빈 무자열인 경우, 클라이언트는 이 파라미터를 생략할 수 있다.
이 두 파라미터를 사용하여 요청 본문에 클라이언트를 자격 증명을 포함하는 방식은 권장되지 않는다.
이 방식은
- HTTP Basic 인증을 쓸 수 없는 경우에만 어쩔 수 없이 사용해야 한다.
그리고 이 값들은
- 요청 본문(body)에만 있어야 하고
- URL 주소(query string)에 넣으면 안 된다.
예시: 액세스 토큰을 새로고침 하기 위해 (section 6) 아래와 같은 바디 파라미터를 사용하는 요청
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
1.6에서 명시한 것처럼, 인가 서버는 비밀번호 인증을 사용하는 요청에 대해 TLS 사용을 요구해야한다.
이 인증 방식은 비밀번호를 포함하기 떄문에 인가 서버는 이러한 방식을 사용하는 엔드 포인트를 무차별 공격으로 부터 보호해야한다.
2.3.2 기타 인증 방법(Other Authentication Methods)
인가 서버는 HTTP Basic 인증 말고도 자기 기준에서 안전하다고 판단되는 다른 어떤 HTTp 인증 방식이든 사용할 수 있다.
다만, 다른 인증 방식을 사용하는 경우 인가 서버는 이 클라이언트 식별자는 이 인증 방식을 사용한다라는 관계를 명확하게 정해두어야함. == 잘 관리해라
2.4 미등록 클라이언트(Unregistered Clients)
미리 등록하지 않은 클라이언트를 아예 금지하지는 않는다. 즉, 기술적으로는 등록되지 않은 클라이언트를 사용하는 것도 가능할 수 있다. 하지만 그런 방식은 이 문서에서 다루는 표준적인 사용 범위 포함되지 않는다. 그래서 만약 미등록 클라이언트를 사용하려면 보안상 문제가 없는지 다른 시스템들과 함께 잘 동작할 수 있는지에 대해 별도로 충분한 검토가 필요
미등록 클라이언트도 사용할 수는 있지만, OAuth 표준이 책임지거나 권장하는 방식은 아니며 보안과 호환성 문제를 스스로 해결해야 한다는 뜻이다.
'RFC > OAuth 2.0' 카테고리의 다른 글
| [OAuth 2.0] 5. Issuing an Access Token (0) | 2026.01.13 |
|---|---|
| [OAuth 2.0] 4. Obtaining Authorization(권한 획득) (0) | 2026.01.07 |
| [OAuth 2.0] 3. Protocol Endpoints (0) | 2025.12.31 |
| [OAuth 2.0] 1. Introduction (2) | 2025.12.20 |
| [OAuth 2.0] Abstract, Status of This Memo, Copyright Notice (1) | 2025.12.20 |