본 포스팅은 SSO 구축기 시리즈의 3편이다.
SSO Model을 설계하고 Authorization Sever를 구축하였으니, 이제 Keycloak과 OpenID Connect Protocol을 사용하여 기존 서비스들에 Signle Sign-On을 구축하는 일만 남았다.
1편에서 설명한 것처럼 사내 인프라를 고려하여 Web 기반 Multi Cookie Domain SSO을 구축할 것인데, 전체적인 설계도는 다음과 같다.
1.A.com 에서 로그인을 수행했다면, 같은 Root Domain을 사용하는 2.A.com 에서도 로그인이 유지된다.
그렇다면, Root Domain이 다른 브라우저에서는 어떤 방식으로 SSO가 가능한지 알아보자.
이제 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를 참고하기 바란다.