100 lines
7.0 KiB
Markdown
100 lines
7.0 KiB
Markdown
---
|
|
id: ede6b9ce-eeed-40c8-9175-9e8116029395
|
|
kind: REFERENCE
|
|
slug: public-confidential-client-boundary
|
|
title: Public Client와 Confidential Client 구분 기준
|
|
topic: oauth-oidc-auth-boundary
|
|
topicName: OAuth/OIDC 인증 경계
|
|
project: KeyCloak Patterns
|
|
status: 게시 중
|
|
version: 27
|
|
verifiedOn: 2026-08-30
|
|
studio: "https://hyeonworks.com/studio/documents/ede6b9ce-eeed-40c8-9175-9e8116029395/edit"
|
|
public: "https://hyeonworks.com/references/public-confidential-client-boundary"
|
|
sourceRevision: keycloak-patterns-lab@2026-08
|
|
source:
|
|
- final/document.md#검토한-선택지와-막힌-지점-책임과-데이터
|
|
- final/document.md#선택의-이유와-지킨-경계-ap1
|
|
- final/document.md#선택의-이유와-지킨-경계-ap2
|
|
---
|
|
|
|
# Public Client와 Confidential Client 구분 기준
|
|
|
|
OAuth 클라이언트 종류는 인증 서버에 대해 장기 자격 증명의 기밀성을 유지하고 신뢰할 수 있는 클라이언트 인증을 수행할 수 있는지로 구분한다.
|
|
AP1의 SPA(Single Page Application)는 브라우저 실행 환경에서 이 조건을 충족하기 어려워 public client로 두었다. AP2~AP4는 서버 구성요소가 자격 증명을 보호할 수 있어 confidential client로 구성했고, 이 프로젝트에서는 `client_secret_basic`을 사용한다.
|
|
|
|
## 관계
|
|
|
|
- **SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계**
|
|
SPA를 public client로 등록한 이유를 실제 구성에서 확인할 수 있다.
|
|
- **Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출**
|
|
confidential client로 등록해도 액세스 토큰을 브라우저까지 보낼지는 따로 정한다.
|
|
- **Authorization Code Flow의 Endpoint와 Credential 이동 기준**
|
|
public client와 confidential client는 토큰 엔드포인트에서 사용하는 클라이언트 인증 방식이 다르다.
|
|
|
|
## 목적
|
|
|
|
클라이언트 종류가 정하는 범위는 자격 증명 보호와 클라이언트 인증이다. PKCE(Proof Key for Code Exchange)는 authorization code를 교환하는 쪽이 원래 verifier를 가진 주체인지 확인하는 별도 보호 장치라서 클라이언트 인증과 함께 사용할 수 있다.
|
|
|
|
AP1 SPA는 public client이고 브라우저가 code를 직접 교환한다. AP2~AP4는 서버 구성요소가 confidential client로 code를 교환하며 이 프로젝트에서는 `client_secret_basic`을 사용한다.
|
|
|
|
토큰 보관 위치와 API 호출 주체는 클라이언트 종류와 다른 축이다. 같은 confidential client라도 AP2는 액세스 토큰을 브라우저에 돌려주고, AP3 BFF(Backend for Frontend)와 AP4 프록시는 서버 쪽에서 다음 요청을 만든다.
|
|
|
|
## 규칙
|
|
|
|
### 1. 실행 환경에서 장기 자격 증명을 보호할 수 있는지 구분한다
|
|
|
|
브라우저 SPA나 사용자 기기에 설치되는 네이티브 앱처럼 배포물을 사용자가 직접 가진 환경에서는 애플리케이션 안에 넣은 장기 자격 증명을 비밀로 유지하기 어렵다. 이런 클라이언트는 public client로 다룬다.
|
|
|
|
서버 구성요소는 자격 증명을 사용자에게 배포하지 않고 인증 서버에 자신을 인증할 수 있다. 이 프로젝트는 공유 시크릿과 `client_secret_basic`을 사용한다. Confidential client의 인증 수단은 공유 시크릿 하나로 제한되지 않으며 private key나 mTLS 같은 방식도 가능하다.
|
|
|
|
### 2. public client에서 Authorization Code Flow에 PKCE를 함께 쓴다
|
|
|
|
PKCE는 authorization code가 중간에 탈취되더라도 다른 사람이 그 code를 토큰으로 바꾸기 어렵게 만드는 보호 장치다.
|
|
클라이언트 시크릿을 대신해 클라이언트를 인증하는 방식은 아니다.
|
|
|
|
로그인을 시작할 때 클라이언트는 임의의 code_verifier를 만들고, 이 값을 변환한 code_challenge를 authorization request에 함께 보낸다. 이후 authorization code를 토큰으로 교환할 때 원래의 code_verifier를 제출한다.
|
|
Authorization Server는 처음 받은 code_challenge와 맞춰 보고 같은 요청에서 시작된 교환인지 확인한다.
|
|
|
|
변환 방식은 S256을 쓴다. plain은 code_verifier 자체가 code_challenge로 전달되기 때문에 authorization request를 관찰한 사람이 그 값을 그대로 알 수 있다. S256은 code_verifier를 SHA-256으로 변환한 값을 보내므로 authorization request에 원래의 code_verifier가 실리지 않는다.
|
|
|
|
### 3. confidential client에도 PKCE를 함께 쓸 수 있다
|
|
|
|
클라이언트 인증과 PKCE는 보호하는 대상이 다르기 때문에 confidential client에서 둘을 같이 쓸 수 있다.
|
|
클라이언트 인증은 토큰 엔드포인트에 요청을 보낸 쪽이 등록된 클라이언트인지 확인한다. PKCE는 authorization code를 받은 쪽이 로그인을 시작할 때 만든 `code_verifier`를 가지고 있는지 확인한다.
|
|
|
|
### 4. public client에서는 implicit flow와 direct access grant를 끈다
|
|
|
|
implicit flow는 authorization code를 거치지 않고 액세스 토큰을 브라우저의 redirect URI로 바로 전달하기 때문에, 토큰이 지나가는 구간과 노출될 수 있는 범위가 넓어진다.
|
|
|
|
direct access grant는 애플리케이션이 사용자의 아이디와 비밀번호를 직접 받아 Authorization Server에 전달하는 방식이다.
|
|
사용자가 IdP에만 주면 되는 비밀번호를 애플리케이션도 함께 다룬다.
|
|
|
|
현재 구조는 Authorization Code Flow를 쓰므로 implicit flow와 direct access grant는 비활성화했다.
|
|
|
|
### 5. 클라이언트 종류만으로 브라우저가 토큰을 받는지가 정해지지는 않는다
|
|
|
|
confidential client가 authorization code를 교환해도 액세스 토큰을 브라우저에 다시 전달할 수 있다. AP2 mediator는 브라우저가 Resource Server를 직접 호출하기 때문에 액세스 토큰을 응답으로 내보낸다.
|
|
|
|
AP3 BFF와 AP4 프록시는 다음 API 요청을 서버 쪽에서 만들기 때문에 브라우저에 액세스 토큰을 줄 필요가 없다. 세 구조가 모두 confidential client라는 사실만으로 이 차이는 설명되지 않는다.
|
|
|
|
## 적용 조건
|
|
|
|
- 새 OAuth 클라이언트를 등록할 때
|
|
- SPA와 서버 중 어디가 code를 교환할지 정할 때
|
|
- PKCE와 클라이언트 인증을 어디에 걸지 정할 때
|
|
- 기존 클라이언트의 종류가 맞는지 다시 볼 때
|
|
|
|
## 예외
|
|
|
|
- 같은 서비스가 브라우저용 public client와 서버용 confidential client를 따로 등록할 수 있다.
|
|
- 백엔드가 사용자 없이 자기 자격으로 부르는 흐름은 Client Credentials를 쓰는 별도 클라이언트다.
|
|
|
|
## 예시
|
|
|
|
- SPA용 클라이언트 : public, standard flow만 켜고 implicit flow와 direct grant는 끈다
|
|
- mediator용 클라이언트 : confidential, client_secret_basic으로 token endpoint에서 인증한다
|
|
- BFF용 클라이언트 : confidential, PKCE S256을 함께 쓴다
|
|
- 프록시용 클라이언트 : confidential, oauth2-proxy가 클라이언트 시크릿과 verifier로 code를 교환한다
|
|
- confidential client인 mediator를 써도 액세스 토큰이 브라우저 응답에 실려 나갈 수 있다
|