--- 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" --- # Public Client와 Confidential Client 구분 기준 OAuth Client의 종류는 client secret을 안전하게 보관할 수 있는지를 기준으로 결정한다. SPA는 브라우저에서 실행되기 때문에 secret을 사용자에게 노출하지 않고 안전하게 보관할 수 없다. 따라서 SPA는 일반적으로 Public Client로 등록한다. ## 관계 - **SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계** SPA를 public client로 등록한 이유를 실제 구성에서 확인할 수 있다. - **Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출** confidential client를 사용해도 access token 전달 방식은 별도로 설계된다는 예다. - **Authorization Code Flow의 Endpoint와 Credential 이동 기준** client 종류에 따라 token endpoint의 client 인증 방식이 달라진다. ## 목적 먼저 OAuth Client가 Public Client인지 Confidential Client인지 결정해야 한다. 그래야 Authorization Code를 Token으로 교환할 때 PKCE를 사용할지, client secret을 이용한 Client 인증을 사용할지 결정할 수 있다. Client 종류를 나누는 기준은 client secret을 사용자에게 노출하지 않고 안전하게 보관할 수 있는지다. SPA는 브라우저에서 실행되기 때문에 코드에 secret을 넣어도 개발자 도구 등을 통해 사용자가 확인할 수 있다. 따라서 SPA는 secret을 안전하게 보관할 수 없는 Public Client로 구성한다. 반면 서버나 BFF는 secret을 서버 내부에 보관하고 브라우저에 전달하지 않을 수 있으므로 Confidential Client로 구성할 수 있다. 여기서 Client 종류와 Token을 누가 관리하는지는 구분해야 한다. Confidential Client라고 해서 반드시 Token이 서버에만 있어야 하는 것은 아니다. Client 종류는 secret을 안전하게 보관할 수 있는지로 정하고, Token을 브라우저와 서버 중 어디에서 관리할지는 애플리케이션의 인증 구조에 따라 별도로 정한다. ## 규칙 ### 1. secret을 숨길 수 있는지로 종류를 정한다 애플리케이션의 배포 파일이나 실행 중인 메모리에서 사용자가 client secret을 확인할 수 있다면 이를 안전하게 보관할 수 없으므로 Public Client로 본다. 반대로 client secret을 서버 내부에만 보관하고 사용자에게 전달되지 않도록 통제할 수 있다면 Confidential Client로 구성할 수 있다. Native App도 브라우저에서 실행되는 것은 아니지만 애플리케이션이 사용자 기기에 설치되기 때문에, 배포 파일을 분석하면 내부에 포함된 client secret을 확인할 수 있다. 따라서 Native App 역시 일반적으로 Public Client로 다룬다. ### 2. public client에서 Authorization Code Flow에 PKCE를 함께 쓴다 PKCE는 client secret을 대신해서 Client를 인증하는 방식이 아니다. Authorization Code가 중간에 탈취되더라도 다른 사람이 그 Code를 Token으로 교환하기 어렵게 만드는 보호 장치다. 로그인을 시작할 때 Client는 임의의 code_verifier를 만들고, 이를 변환한 code_challenge를 Authorization Request에 함께 보낸다. 이후 Authorization Code를 Token으로 교환할 때 원래의 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를 함께 쓸 수 있다 Client 인증을 사용하는 Confidential Client에서도 PKCE는 함께 사용할 수 있다. Client 인증과 PKCE는 보호하는 대상이 다르기 때문이다. Client 인증은 Token Endpoint에 요청한 Client가 올바른 Client인지 확인하고, PKCE는 Authorization Code를 받은 주체가 로그인 시작 시 생성한 code_verifier를 가지고 있는지 확인한다. 그래서 두 방식을 같이 사용하면 서로 다른 구간을 각각 보호할 수 있다. ### 4. public client에서는 implicit flow와 direct access grant를 끈다 Implicit Flow는 Authorization Code를 거치지 않고 Access Token을 브라우저의 Redirect URI로 직접 전달한다. 이 때문에 Token이 브라우저를 통과하고 노출될 수 있는 범위가 넓어진다. Direct Access Grant는 애플리케이션이 사용자의 아이디와 비밀번호를 직접 받아 Authorization Server에 전달하는 방식이다. 원래 사용자가 IdP에만 제공하면 되는 비밀번호를 애플리케이션도 다루게 된다는 문제가 있다. 현재 구조에서는 Authorization Code Flow를 사용하고 있으므로 Implicit Flow와 Direct Access Grant는 비활성화했다. ### 5. Client 종류만으로 브라우저가 Token을 받는지 여부가 결정되지는 않는다. Confidential Client가 Authorization Code를 Token으로 교환하더라도, 그 결과로 받은 Access Token을 다시 브라우저에 전달하는 구조를 만들 수 있다. 즉, Confidential Client라고 해서 Token이 반드시 서버 내부에만 있는 것은 아니다. Client 종류는 client secret을 어디에 안전하게 보관할 수 있는지를 나타낸다. 반면 Access Token이 브라우저까지 전달되는지는 어느 계층이 실제 API 호출을 담당하도록 설계했는지에 따라 별도로 결정된다. ## 적용 조건 - 새 OAuth client를 등록할 때 - SPA와 server 중 어디가 code를 교환할지 정할 때 - PKCE와 client 인증을 어디에 둘지 정할 때 - 기존 client의 종류가 맞는지 다시 볼 때 ## 예외 - 같은 서비스가 브라우저용 public client와 server용 confidential client를 따로 등록할 수 있다. - 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은 브라우저 응답에 반환될 수 있다