85 lines
4.9 KiB
Markdown
85 lines
4.9 KiB
Markdown
---
|
|
id: ede6b9ce-eeed-40c8-9175-9e8116029395
|
|
kind: REFERENCE
|
|
slug: public-confidential-client-boundary
|
|
title: Public Client와 Confidential Client 구분 기준
|
|
topic: OAuth/OIDC 인증 경계
|
|
project: KeyCloak Patterns
|
|
status: 게시 전
|
|
version: 12
|
|
studio: "https://hyeonworks.com/studio/documents/ede6b9ce-eeed-40c8-9175-9e8116029395/edit"
|
|
---
|
|
|
|
# Public Client와 Confidential Client 구분 기준
|
|
|
|
client 종류는 secret을 안전하게 보관할 수 있는지로 정한다. SPA는 보관할 곳이 없어 public client로 등록한다. 종류는 secret이 어디 있는지를 말할 뿐이고, 브라우저에 token이 가는지는 따로 정해진다.
|
|
|
|
## 관계
|
|
|
|
- **SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계**
|
|
SPA를 public client로 등록한 이유를 실제 구성에서 확인할 수 있다.
|
|
- **Mediator가 Refresh Token을 관리하고 Access Token을 Browser에 전달하는 구조**
|
|
confidential client를 사용해도 access token 전달 방식은 별도로 설계된다는 예다.
|
|
- **Authorization Code Flow의 Endpoint와 Credential 이동 기준**
|
|
client 종류에 따라 token endpoint의 client 인증 방식이 달라진다.
|
|
|
|
## 목적
|
|
|
|
client 종류를 무엇으로 정하는지부터 맞춰야 PKCE와 client 인증을 어디에 둘지 정할 수 있게 된다.
|
|
|
|
기준은 프레임워크나 언어가 아니라 값이 도달하는 범위다. 브라우저에서 실행되는 코드에 넣은 값은 개발자 도구를 열면 그대로 보이기 때문에 SPA는 secret을 가질 수 없고, server와 BFF는 그 값을 process 밖으로 내보내지 않을 수 있어서 secret을 들고 있게 된다.
|
|
|
|
여기서 자주 섞이는 것이 하나 있는데, 종류가 confidential이어도 브라우저에 token이 갈 수 있다. 서로 다른 결정이라서 따로 답해야 한다.
|
|
|
|
## 규칙
|
|
|
|
### 1. secret을 숨길 수 있는지로 종류를 정한다
|
|
|
|
배포물이나 실행 중 memory에서 사용자가 값을 꺼낼 수 있으면 public client가 되고, server 안에만 두고 응답으로 나가지 않게 할 수 있으면 confidential client다.
|
|
|
|
native app은 브라우저가 아니지만 배포물을 뜯으면 값이 나오기 때문에 여기서도 public client로 다루게 된다. 실행 환경의 이름이 아니라 값이 어디까지 가는지로 정한다.
|
|
|
|
### 2. public client에서도 Authorization Code Flow에 PKCE를 함께 쓴다
|
|
|
|
PKCE는 client secret을 대체하는 client 인증 방식이 아니다. authorization request에서 만든 verifier와 token request의 verifier를 연결해 탈취된 authorization code의 교환을 어렵게 만든다.
|
|
|
|
여기서 S256을 쓴다. plain은 challenge가 verifier 그대로라서 중간에서 본 사람이 그대로 쓸 수 있다.
|
|
|
|
### 3. confidential client에도 PKCE를 함께 쓸 수 있다
|
|
|
|
client 인증이 있어도 PKCE는 여전히 쓸모가 있다. 두 장치가 막는 구간이 서로 달라서 함께 두면 그만큼 좁아지게 된다.
|
|
|
|
다만 「Authorization Code를 쓴다」와 「PKCE S256까지 설정으로 고정했다」는 서로 다른 주장이다. 설정과 테스트에서 확인한 범위까지만 말할 수 있다.
|
|
|
|
### 4. public client에서는 implicit flow와 direct access grant를 끈다
|
|
|
|
implicit flow는 token을 redirect fragment로 받게 되어서 주소창과 히스토리에 token이 남고, direct access grant는 애플리케이션이 사용자의 아이디와 비밀번호를 직접 받게 되어서 IdP만 알면 되는 값을 애플리케이션이 만지게 된다.
|
|
|
|
현재 예제에서는 Authorization Code Flow를 사용하므로 implicit flow와 direct access grant를 비활성화했다.
|
|
|
|
### 5. 종류가 곧 브라우저 token 유무는 아니다
|
|
|
|
confidential client가 code를 교환해도 그 결과인 access token을 응답 본문으로 브라우저에 건넬 수 있고, 실제로 그렇게 도는 구조가 있다.
|
|
|
|
종류는 secret을 어디에 두는지를 말하고, token 노출은 어느 계층이 API를 부르는지에 따라 갈린다.
|
|
|
|
## 적용 조건
|
|
|
|
- 새 OAuth client를 등록할 때
|
|
- SPA와 server 중 어디가 code를 교환할지 정할 때
|
|
- PKCE와 client 인증을 어디에 둘지 정할 때
|
|
- 기존 client의 종류가 맞는지 다시 볼 때
|
|
|
|
## 예외
|
|
|
|
- 같은 서비스가 브라우저용 public client와 server용 confidential client를 따로 등록할 수 있다. 하나로 합치려고 secret을 브라우저로 내보내지는 않는다.
|
|
- backend가 사용자 없이 자기 자격으로 부르는 흐름은 Client Credentials를 쓰는 별도 client다.
|
|
|
|
## 예시
|
|
|
|
- SPA용 client : public, standard flow만 켜고 implicit flow와 direct grant는 끈다
|
|
- Mediator용 client : confidential, client_secret_basic으로 token endpoint에서 인증한다
|
|
- BFF용 client : confidential, PKCE S256을 함께 쓴다
|
|
- Proxy용 client : confidential, oauth2-proxy가 secret과 verifier로 code를 교환한다
|
|
- confidential client인 Mediator를 써도 access token은 브라우저 응답에 실릴 수 있다
|