테마
Public vs Confidential Client
logi는 OAuth 2.0 RFC 6749 §2.1 의 두 클라이언트 타입을 모두 지원합니다. RP 등록 시 어떤 타입을 선택할지가 보안 + 구현 복잡도를 결정합니다.
한 줄 요약
| 질문 | 답 |
|---|---|
| 백엔드 서버가 있고 client_secret 안전 보관 가능? | → Confidential |
| 순수 모바일 앱 / SPA / CLI 도구라 secret 보관 불가? | → Public |
| 둘 다 해당? (모바일 + 백엔드) | → Confidential + BFF (권장) |
결정 트리
mermaid
flowchart TD
A[RP 등록 시작] --> B{서버측 백엔드<br>존재?}
B -- 있음 --> C{모바일/SPA 클라이언트도<br>같이 운영?}
B -- 없음<br>(순수 클라이언트) --> D[Public client]
C -- 예 --> E[Confidential + BFF<br>권장]
C -- 아니오<br>(서버에서만 호출) --> F[Confidential]
D --> G[client_secret 발급 안 됨<br>PKCE S256 강제<br>refresh rotation 필수]
E --> H[모바일 → 백엔드 → logi<br>logi 토큰은 백엔드만<br>client_secret 백엔드 보관]
F --> I[server-to-server<br>HTTP Basic 또는 form body]보안 모델 차이
Confidential client
- ✅
client_secret으로 서버 신원 증명 (RFC 6749 §2.3) - ✅ HTTP Basic 또는 form body 인증
- ✅ logi 토큰을 백엔드 DB 에 저장해서 회전/취소/감사 가능
- ⚠️
client_secret유출 시 즉시 회전 필요 (logi/developer/applications/:id/rotate_secret)
Public client
- ✅ 클라이언트 신원 증명 없음 → PKCE S256 으로 code 가로채기 방어 (RFC 7636)
- ✅ refresh token rotation + family detection 자동 (재사용 감지 시 family 일괄 폐기)
- ⚠️ logi 토큰이 클라이언트 메모리/storage 에 노출 → DPoP / 키체인 권장
- ⚠️ HTTP Basic 또는 client_secret 파라미터 발견 시 요청 거절 (downgrade 방어)
- ⚠️
redirect_uri는 https / loopback / custom-scheme 만 허용 (RFC 8252 §8.5)
BFF (Backend-for-Frontend) 권장 시점
모바일 앱이 있고 자체 백엔드도 운영한다면 Confidential + BFF 가 거의 항상 더 안전합니다.
BFF 흐름:
[Mobile] PKCE 시작 → authorize URL 호출 → callback 에서 code 수령
│
▼
[Mobile] POST /api/auth/logi/exchange { code, code_verifier }
│
▼
[Backend] (client_secret 보유) POST {logi}/oauth/token
│ logi 토큰 수령 → id_token 검증 → User 매칭
│ → 자체 JWT 발급
▼
[Mobile] 자체 JWT 만 보관. logi 토큰은 절대 보지 않음.BFF 의 보안 이득:
- logi access_token / refresh_token 이 모바일에 절대 도달하지 않음 → 단말 침해 시에도 logi 자원에 접근 불가
- 백엔드가 자체 토큰의 TTL/회전/취소를 독립적으로 관리
- 토큰 만료 시 백엔드가 logi 와 silent refresh, 모바일은 자체 JWT 만 갱신
BFF 가 필요 없는 경우:
- 백엔드 자체가 없는 순수 SPA / 모바일 앱 (예: 클라이언트만으로 완결되는 위젯)
- 토큰을 받자마자 단말에서 일회성으로만 사용 (예: 일회성 페어링)
logi 가 Public client 에 강제하는 보안 정책
| 항목 | 강제 사항 |
|---|---|
| PKCE | S256 필수, plain 거절 |
code_challenge / code_verifier | 필수 |
| HTTP Basic 인증 | 거절 (invalid_client) |
client_secret 파라미터 | 거절 (invalid_client) |
redirect_uri 스킴 | https / 127.0.0.1 / localhost / custom-scheme |
redirect_uri 외부 평문 http | 거절 |
| Refresh token rotation | 모든 응답에 새 refresh 발급 |
| Refresh token 재사용 감지 | family 전체 폐기 |
선택 후 변경
한번 결정하면 변경 불가 — 새 RP 를 다시 등록해야 합니다. 이는 의도된 제약입니다. Public ↔ Confidential 토큰 정책이 달라 중간 변경 시 기존 발급된 토큰의 보안 모델이 깨질 수 있기 때문입니다.
관련 문서
- Public Clients 기술 가이드 — 등록 절차 + PKCE 다국어 예시
- Flutter Integration — Flutter 에서 public/BFF 양쪽 구현
- PKCE — RFC 7636 상세
- redirect_uri 보안 — 검증 규칙