SSO 구축기 - Web 기반 Multi Cookie Domain SSO 구축

김동균·2022년 11월 7일
2

SSO 구축기

목록 보기
3/3

본 포스팅은 SSO 구축기 시리즈의 3편이다.

SSO Model을 설계하고 Authorization Sever를 구축하였으니, 이제 Keycloak과 OpenID Connect Protocol을 사용하여 기존 서비스들에 Signle Sign-On을 구축하는 일만 남았다.

1편에서 설명한 것처럼 사내 인프라를 고려하여 Web 기반 Multi Cookie Domain SSO을 구축할 것인데, 전체적인 설계도는 다음과 같다.

  1. 사용자가 1.A.com Web에서 로그인을 요청한다.
  2. A.com Root Domain을 사용하는 OAuth Client 서버로 요청을 넘긴다.
  3. OAuth Client가 로그인 요청을 해석하여 Keycloak 로그인 페이지로 Redirect 시킨다.
  4. 사용자가 로그인 페이지에서 로그인에 성공하면, Keycloak에 SSO Session이 생성된다.
  5. Keycloak이 Authorization Code와 함께 OAuth Client로 Callback 시킨다.
  6. OAuth Client가 Authorization Code를 가지고 Keycloak의 Token Endpoint로 Token Exchange를 요청한다.
  7. Keycloak은 Access Token, Refresh Token을 담아 응답한다.
  8. OAuth Client가 A.com Domain 속성으로 Access Token, Refresh Token Cookie를 생성한다.
    1편에서 설명하였듯이, A.com 도메인의 쿠키를 생성하기 위해서는 Origin Server 또한 A.com이어야 하기 때문에, OAuth Client 또한 A.com 도메인이어야 A.com 도메인의 쿠키를 생성할 수 있다. 자세한 내용은 RFC 6265 사양을 참고하자.
  9. 1.A.com Web에서는 Cookie에 담긴 Token을 사용하여 Resource Server를 호출한다.
  10. Resource Server는 토큰 검증을 Keycloak에 위임한다. Spring Boot Resource Server Sample은 Github 참고
  11. Token Validate가 완료 되었으면, Token에서 email 등 식별 가능한 키 값을 사용하여 Resource Server에서 권한을 검증한다. 사내에서는 Authentication(인증), Authorization(권한)을 구분하여 관리하기 위해 해당 방식을 사용하였지만, Keycloak의 Role Based 권한 관리를 사용하면 Keycloak에서 AuthN, AuthZ까지 모두 관리할 수 있다.
  12. Resource를 응답한다.

1.A.com 에서 로그인을 수행했다면, 같은 Root Domain을 사용하는 2.A.com 에서도 로그인이 유지된다.

그렇다면, Root Domain이 다른 브라우저에서는 어떤 방식으로 SSO가 가능한지 알아보자.

  1. 사용자가 1.B.com Web에서 로그인을 요청한다.
  2. B.com Root Domain을 사용하는 OAuth Client 서버로 요청을 넘긴다.
  3. OAuth Client가 로그인 요청을 해석하여 Keycloak 로그인 페이지로 Redirect 시킨다.
  4. Keycloak에 SSO Session이 존재하기 때문에, 로그인 프로세스가 생략된다.
    이후의 과정은, Cookie를 다른 도메인 속성으로 생성하는 것을 제외하고는 동일하다.

이제 Single Sign-On은 구현이 되었으니, Single Sign-Out을 구현해야 한다.
OpenID Connect Protocol에서는 기본적으로 Front-Channel Logout과 Back-Channel Logout을 지원한다.
간단히 말해서 Front-Channel Logout은 사용자 에이전트(브라우저)를 통해서 로그아웃 요청이 수행되고, Back-Channel Logout은 서버간의 네트워크 링크를 통해 로그아웃 요청이 수행되는 것을 말한다.
Back-Channel Logout 메커니즘은 End User의 브라우저 활동에 의존하기 않기 때문에 Front-Channel Logout보다 훨씬 덜 취약하고, Back-Channel Logout을 사용할 서버 또한 존재하기 때문에 해당 방식의 로그아웃을 구현했다.

Keycloak에서 제공하는 Back-Channel Logout Endpoint에 client_id, client_secret, refresh_token(Logout Token의 용도)를 담아 요청하면, Token Payload에 들어있는 iss, sub, sid 등의 클레임을 사용해 식별된 Session을 찾아 관련된 모든 상태를 지워버린다.

Session이 종료되면 발급된 Refresh Token은 사용할 수 없게 되지만, 발급된 Access Token은 Stateless하여 Session의 존속 여부와 무관하게 사용할 수 있어서 Access Token의 expire를 짧게 설정하는 것이 좋다.(Session Logout과 Access Token의 만료 시점을 동기화하려면 Redis 등을 두어 stateful하게 구현하는 방법도 있긴 하다.)

사내에서는 브라우저 애플리케이션 뿐만 아니라 AOS, IOS, 윈도우 앱 또한 존재하는데, Keycloak은 Browser 기반의 SSO만을 지원한다.
모바일은 Web View, 윈도우 앱은 Embedded Chrome을 사용하여 해당 문제를 해결하였다.

이렇게 SSO가 구축이 되었으면, 마지막으로 사내 서비스에서 Keycloak에서 발급한 Access Token을 사용할 수 있게 Resource Server를 적용해줘야 한다.
사내 서비스는 대부분 Spring Boot 기반인데, Spring에서는 dependency와 간단한 설정만으로 Resource Server를 구성할 수 있도록 하는 프레임워크를 제공해준다.
샘플 코드는 Github를 참고하기 바란다.

profile
백엔드 개발자

0개의 댓글