LabHub
배우기 러닝패스 코스

Keycloakと企業認証

レルムは隔離の境界だ

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

렐름은 사용자, 클라이언트, 롤, 키를 담는 완전한 격리 단위다. 렐름이 다르면 서로의 사용자를 모른다.

概念マップ: 서명・발급자(iss)・대상(aud)・만료(exp)

왜 이게 필요했나

Keycloak 을 처음 열면 master 렐름이 있습니다. 여기에 애플리케이션 사용자를 만드는 것이 첫 번째 실수입니다. master 는 Keycloak 자체를 관리하는 렐름이고, 여기 사용자는 Keycloak 관리 권한과 엮입니다. 애플리케이션용 렐름은 따로 만들어야 합니다.

렐름이 격리 단위라는 말의 의미는 구체적입니다. 렐름마다 서명 키가 다르고, 사용자 저장소가 다르고, 토큰 발급자(iss)가 다릅니다. 그래서 렐름 A 의 토큰은 렐름 B 의 API 에서 검증에 실패합니다. 다중 테넌트 SaaS 에서 테넌트별 렐름을 두는 설계가 여기서 나옵니다 — 다만 렐름 수가 수백 개가 되면 관리와 메모리 부담이 커지므로, 대개는 하나의 렐름 안에서 그룹과 속성으로 테넌트를 구분합니다.

어떻게 동작하나

클라이언트는 렐름 안에서 토큰을 요청할 수 있는 애플리케이션입니다. 두 종류로 나뉩니다.

공개 클라이언트는 시크릿이 없습니다. SPA 와 모바일 앱이 여기 속하고, PKCE 를 반드시 켜야 합니다. 리다이렉트 URI 를 정확히 등록하는 것도 중요합니다 — 와일드카드를 넓게 쓰면 토큰 탈취 통로가 됩니다.

기밀 클라이언트는 시크릿이 있습니다. 백엔드 서버가 여기 속하고, 서비스 계정을 켜면 client credentials 흐름으로 자기 자신의 토큰을 받을 수 있습니다.

롤은 두 층위입니다. 렐름 롤은 렐름 전체에서 의미가 있고(예: admin), 클라이언트 롤은 특정 클라이언트 안에서만 의미가 있습니다(예: orders-apirefund). 서비스가 여럿이면 클라이언트 롤로 나누는 편이 이름 충돌을 막습니다.

그룹은 사용자의 묶음이고 롤을 매핑할 수 있습니다. 사용자 300명에게 개별로 롤을 주는 대신 그룹에 롤을 주고 사용자를 그룹에 넣습니다. 그룹은 계층을 가질 수 있고 하위 그룹이 상위의 롤을 상속합니다.

컴포지트 롤은 롤이 다른 롤을 포함하는 것입니다. order-adminorder-reader 를 포함하게 하면 관리자에게 두 롤을 각각 줄 필요가 없습니다.

현장에서 만나는 모습

토큰에 롤이 들어가는 위치가 헷갈리기 쉽습니다. 렐름 롤은 realm_access.roles 에, 클라이언트 롤은 resource_access.<클라이언트ID>.roles 에 들어갑니다. 그리고 클라이언트의 "full scope allowed" 를 끄면 그 클라이언트에 매핑되지 않은 롤은 토큰에서 빠집니다. 토큰 크기를 줄이고 최소 권한을 지키는 데 쓰이지만, 이걸 모르고 끄면 "롤을 줬는데 토큰에 안 보여요"가 됩니다.

관리 작업은 kcadm.sh 로 스크립트화하는 것이 좋습니다. 웹 콘솔에서 손으로 만든 설정은 재현되지 않고, 스테이징과 운영이 조용히 달라집니다.

토큰을 검증하는 쪽에서 봐야 할 것

발급 설정을 아무리 잘해도, 받는 쪽이 제대로 검증하지 않으면 아무 의미가 없다. API 서버가 토큰을 받았을 때 확인해야 하는 것은 정해져 있다.

여기서 절대 하지 말아야 할 것이 알고리즘을 토큰이 시키는 대로 고르는 것입니다. 검증하는 쪽이 헤더의 alg 를 그대로 믿으면, 공격자가 none 이나 대칭 알고리즘으로 바꿔 서명을 우회할 수 있습니다. 기대하는 알고리즘을 코드에 못 박아 두고 그것과 다르면 즉시 거절해야 합니다.

토큰 수명 설계도 함께 정한다. 액세스 토큰은 짧게(수 분), 리프레시 토큰은 길게 두는 이유는 액세스 토큰이 취소될 수 없기 때문이다. 서명이 유효하고 만료 전이면 Keycloak 에서 사용자를 지워도 그 토큰은 계속 통한다. 그래서 즉시 차단이 필요한 경우에는 짧은 수명에 기대거나, 요청마다 토큰 상태를 확인하는 방식으로 바꿔야 하는데 후자는 모든 요청이 Keycloak 을 거치므로 성능과 가용성을 함께 고려해야 한다. "로그아웃했는데 왜 아직 되나요" 라는 질문의 답이 대부분 이 대목에 있습니다.

마지막으로, 검증 실패를 어떻게 되돌려 줄지도 정해 두어야 한다. 서명이나 발급자가 틀린 것은 401 이고, 토큰은 유효한데 그 롤로는 못 하는 일이면 403 이다. 이 둘을 뭉뚱그리면 클라이언트가 다시 로그인해야 할 상황과 권한을 받아야 할 상황을 구분하지 못해, 무한히 재로그인을 시도하는 화면이 만들어진다.

다음 실습에서 할 것

렐름을 만들고 공개·기밀 클라이언트를 각각 만들고 사용자를 만듭니다. 그다음 별도 실습에서 롤과 그룹을 만들어 토큰에 어떻게 반영되는지 확인하고, 스코프로 롤을 제외해 보기까지 합니다.