티스토리 뷰

WEB

Keycloak 시작하기 4

마시멜로co. 2025. 2. 10. 09:29

이번글에서는 다양한 유형의 애플리케이션을 보호하기 위한 보안 원리와 베스트 프랙티스에 대해 작성하겠습니다.

웹, 모바일 및 네이티브 애플리케이션을 보호하는 방법과 REST API, gRPC, Websocket 및 기타유형의 서비스를 포함한 다양한 유형의 서비스를 보호하기 위해 bearer 토큰을 이용하는 방법을 작성합니다.

 

1. 내부 및 외부 애플리케이션

애플리케이션을 보호할대 가장 먼저 고려해야할 사항은 애플리케이션이 내부 애플리케이션인지 혹은 외부 애플리케이션인지 확인하는 것입니다.

내부 애플리케이션은 기업이 보유한 애플리케이션입니다. 애플리케이션을 누가 개발했는지 또는 호스팅 방법은 중요하지 않습니다. 애플리케이션은 상용 애플리케이션, SaaS(Software as a Service)에서 호스팅되는 애플리케이션이 될 수도 있지만 해당 애플리케이션도 내부 애플리케이션으로 고려해야합니다.

내부 애플리케이션의 경우 해당 애플리케이션은 신뢰할 수 있고, Keycloak에 애플리케이션을 등록한 관리자가 사용자를 대신해 접근 권한을 사전 승인할 수 있으므로 사용를 인증할 때 사용자에게 애플리케이션에 대한 접근 권한을 부여하도록 요청할 필요가 없습니다.

 

관리자 창을 열어 keycloak 관리자 모드를 실행합니다. (keycloak 설정 방법은 Keycloak 시작하기 3 글 참고)

cd C:\keycloak-26.0.7\keycloak-26.0.7
bin\kc.bat start-dev

 

 

Consent required를 활성화면 사용자에게 접근 권한을 승인받아야 합니다.

 

외부 API를 호출하는 SPA(Single Page Application) 유형 애플리케이션인 경우 고려해야할 2가지 추가 옵션이 있습니다.

애플리케이션이 외부 REST API를 직접 호출하는지 , 아니면 애플리케이션과 함께 호스팅 되는 전용 REST API를 호출하는지 입니다. 위의 내용을 기반으로 다음 내용 중에서 보호하려는 애플리케이션의 아키텍처에 해당되는 내용을 결정해야합니다.

- Server side : 웹 애플리케이션이 웹 서버 내부 또는 애플리케이션 서버 내에서 실행 중인 경우

- SPA with dedicated REST API : 애플리케이션이 브라우저에서 실행되거나 동일 도메인에서 전용 REST API만 호출하는 경우

- SPA with intermediary API : 애플리케이션이 브라우저에서 실행되거나 애플리케이션과 동일한 도메인에서 호스팅되는 중개 API를 통해 외부 REST API를 호출하는 경우

- SPA with external API : 애플리케이션이 브라우저에서 실행되거나 다른 도메인에서 호스팅되는 API만 호출하는 경우

 

위와 같이 다양한 웹 애플리케이션 아키텍쳐에 대한 세부 사항을 살펴보기 전에 모든 아키텍처에서 공통되는 부분이 있습니다.

첫째, 가장 중요한 것은 PKCE(Proof Key for Code Exchange) 확장과 함께 인가 코드 흐름(Authorization Code flow)을 사용해 웹 애플리케이션을 보호해야 한다는 것입니다. PKCE 확장 기능은 인가 요청을 전송한 애플리케이션에 인가 코드를 바인딩하는 OAuth2.0 확장기능입니다.해당 확장 기능은 유출될 경우 인가코드가 남용되는 것을 방지합니다. 만약 라이브러리를 사용하지 않는 경우 OAuth2.0 및 OpenID Connect를 활용하기 위한 관련 사양을 직접 참조해야합니다.

Keycloak을 사용하기 위해 기존 애플리케이션을 포팅하는 경우, 기존 애플리케이션의 로그인 페이지를 유지한 다음 리소스 소유자 암호 자격증명 부여를 사용해 토큰의 사용자 이름과 패스워드를 교환하는게 효율적으로 보일 수 있습니다. 해당방법은 애플리케이션을 LDAP서버와 통합하는 것과 유사합니다.

하지만 해당 방법은 사용하면 안됩니다. 애플리케이션에서 사용자 자격증명을 수집하는 것은 단일 애플리케이션의 보안 이 손상된 경우 공격자는 사용자가 접근 할 수 있는 모든 애플리케이션에 접근할 수 있음을 의미합니다.

사용자들은 보통 패스워드를 재사용하기 때문에 Keycloak으로 보호되지 않는 애플리케이션이 포함됩니다. 또한 이중 인증과 같은 강력한 인증을 적용할 수 있는 기능도 없습니다. 결과적으로 해당 방법을 사용하면 SSO 및 소셜 로그인과 같은 Keycloak의 장점을 사용할 수 없게 됩니다. 

로그인 페이지를 기존 프로그램 내에 유지하는 대신 Keycloak 로그인 페이지를 iframe 방식으로 애플리케이션을 포함시키는 방법도 생각했을 수 있습니다. 하지만 이또한 반드시 피해야하는 설정입니다.

애플리케이션에 포함된 로그인 페이지를 사용하면 애플리케이션의 취약점의 영향을 받을 수 있고, 잠재적으로 공격자가 사용자 이름과 패스워드에 대한 접근 권한을 획득 할 수 있습니다. 로그인 페이지가 iframe내에서 렌더링되기 때문에 사용자는 로그인 페이지의 출처를 확인하기 어려우며 사용자는 애플리케이션에 패스워드를 직접 입력하는 것을 신뢰하지 않을 수 있습니다. 마지막으로 여러 사이트에서 서드파티 쿠키를 사용자 추적에 활용하면서 브라우저는 점점더 서브파티 쿠키를 차단하는 상황이며, 이로 인해 Keycloak 로그인 페이지에 작동하는데 필요한 쿠키에 접근하지 못 할 수 있습니다. 

요약하면, 애플리케이션이 인증을 위해 (특히 SSO환경에서) 사용자를 신뢰할 수 있는 ID 제공자로 리다이렉티해야한다는 것입니다. 또한 해당 환경은 최근 폭넓게 사용되는 패턴이기 때문에 대부분의 사용자가 이미 익숙할 것입니다. 

 

애플리케이션 자체에 내장돼 있지 않은 로그인 페이지 예시

 

2.  서버 사이드 웹 애플리케이션 보호

Keycloak을 사용해 서버 사이드 웹  애플리케이션을 보호하는 경우 Keycloak에 보안 클라이언트(Confidencial Client)를 등록해야합니다. 보안 클라이언트를 사용하면 공격자가 유출된 인가 코드를 악용할 수 없습니다.

PKCE확장은 여러가지 유형의 공격에 대한 보호를 제공하기 때문에 해당 확장을 활용하는 것이 좋습니다.

또한 클라이언트에 적절한 Redirect URIs를 설정해야합니다. 그렇지 않은 경우 오픈 리다이렉트 취약점이 생성됩니다.

예를 들어 스팸 공격의 경우, 오픈 리다이렉트를 사용해 사용자가 신뢰하는 사이트를 클릭하고 있는 것으로 속일 수 있습니다. 클라이언트에 대한 적절한 redirect URL를 설정하지 않으면 Keycloak은 사용자를 공격자가 제공한 사이트로 리다이렉트하게 될 수 있습니다.

서버 사이드 웹 애플리케이션의 HTTP 세션 수립에는 일반적으로 ID 토큰만 사용됩니다.

서버 사이드 웹 애플리케이션은 또한 사용자 컨텍스트 환경에서 외부 REST API를 호출하는 경우 접근 토큰을 활용합니다.

요약하면 애플리케이션은 Keycloak의 ID 토큰을 획득하기 위해 인가 코드흐름을 활용합니다. 해당 ID토큰은 인증된 HTTP 세션을 수립하기 위해 사용됩니다. 서버 사이드 애플리케이션인 경우 OpenID Connect를 사용하는 대신 SAML2.0을 사용할수도 있습니다. 일반적으로 OpenID Connect를 사용하는 것이 편하기 때문에 사용중인 애플리케이션이 이미 SAML2.0을 지원하는 것이 아니라면 OpenID Connect를 사용하는 것을 권장됩니다.

 

3. 전용 REST API가 포함된 SPA  보호

동일한 도메인에 전용 REST API가 포함된 SPA는 서버사이드 웹 애플리케이션과 동일한 방식으로 Keycloak을 사용해 보호됩니다. 애플리케이션은 REST API를 포함하기 때문에 최고 수준의 보안을 위해 보안 클라이언트의 인가 코드 흐름을 활용해야 하며, 클라이언트 사이드에서 전용 REST API로 전송되는 API 요청을 보호하기 위해 HTTP 세션을 사용해야합니다. 

SPA에서 전용 REST API로 전송되는 요청은 HTTP 세션 쿠키를 포함합니다. 요약하면 애플리케이션은 권한 부여 코드 흐름을 활용해 Keycloak에 ID 토큰 을 획득합니다. 해당 토큰은 인증된 HTTP 세션을 수립하기 위해 사용되며, 이를 통해 SPA는 웹 서버에서 제공되는 REST API를 안전하게 호출할 수 있습니다.

 

4. 중계 REST API를 사용하는 SPA 보호

SPA에서 외부 REST API를 호출하는 가장 안전한 방법은 SPA와 동일한 도메인에서 호스팅되는 중계 API 사용하는 것입니다. 중계 API를 사용하면 보안 클라이언트를 활용할 수 있고 브라우저에서 직접 토큰에 접근 할 수 없기 때문에 토큰이 유출될 위험이 줄어듭니다.

이러한 유형의 SPA를 보통 프론트엔드 패턴용 백엔드라고 합니다. 해당 SPA는 높은 보안 수준을 가졌으며, SPA의 호환성을 높이고 쉽게 개발 할 수 있습니다. 애플리케이션이 외부 API를 직접 처리할 필요가 없고 프론트엔드 SPA 서비스를 제공하기 위한 목적으로 구축한 전용 REST API가 있기 때문입니다.

또한 기본적으로 브라우저의 CORS(Cross-Origin Resource Sharing)가 활성화 되어 있기 떄문에 SPA가 다른 도메인에서 제공하는 REST API를 호출하는 것을 브라우저에서 허용되지 않습니다. CORS를 사용하면 REST API가 브라우저에서 다른 오리진의 요청을 허용하는 특정 HTTP 헤더를 응답 할 수 있습니다.해당 SPA는 동일한 도메인의 중계 REST API를 통해 요청을 생성하기 때문에 CORS를 처리할 필요가 없습니다. 

요약하면 애플리케이션은 인증 코드 흐름을 활용해 Keycloak에서 ID 토큰을 획득하며, 해당 ID 토큰은 인증된 HTTP 세션을 수립하기 위해 사용됩니다. 해당 HTTP 세션을 통해 SPA는 안전하게 웹 서버를 호출하고, 웹 서버는 해당 요청을 외부 REST API로 프록시합니다. 

 

5. 외부 REST API가 포함된 SPA 보호

Keycloak을 통해 SPA를 보호하는 가장 간단한 방법은 Keycloak에 등록된 공용 클라이언트를 사용해 SPA 자체에서 직접 인가 코드 흐름을 수행하는 것입니다. 해당 접근 방법은 토큰(리프레시 토큰 포함)이 브라우저에서 직접 노출되기 떄문에 약간 보안 수준이 낮은 방법입니다. 금융 애플리케이션과 같이 민감한 애플리케이션의 경우 해당 접근 방식을 사용하는 것을 권장하지 않습니다. 하지만 다음과 같이 해당 접근 방법에 적절한 수준의 보안을 제공하기 위해 활용할 수 있는 여러가지 기법이 있습니다.

- 리프레시 토큰의 만료 시간을 짧게 설정한다. 해당 설정은 Keycloak의 클라이언트 세션 타임아웃에서 설정할 수 있다.

설정을 수행하면 클라이언트에게 30분 동안 유효한 리프레시 토큰을 제공하고 반면 SSO 세션은 며칠동안 유효하다.

- 리프레시 토큰을 갱신한다. Keycloak에서 realm의 Revoke Refresh Token을 활성화해 이전에 사용한 리프레스 토큰을 폐기합니다. 폐기한 리프레시 토큰을 사용하는 경우 세션은 무효화된다.따라서 SPA와 공격자가 리프레시 토큰을 사용하려고 하면 유출된 리프레시 토큰이 즉시 폐기된다.

- PKCE 확장을 사용한다. 공용 클라이언트의 경우 PKCE 확장을 사용해야 한다. 그렇지 않으면 공격자는 유출된 인가 코드를 통해 토큰을 획득할 수 있다. 

- 토큰을 윈도우 상태 또는 HTTP5 스토리지 세션에 저장하고 window.sessionStorage.accessToken과 같이 쉽게 유추할 수 있는 키를 사용하지 않아야한다.

- OWASP(Open Web Application  Security Project)의 베스트 프랙티스를 활용해 XSS(Cross-site scripting) 및 여러가지 공격으로 부터 SPA를 보호한다.

- 애플리케이션에서 서드파티 스크립트를 사용하는 경우 주의를 기울여야 한다.

 

결국 적절한 수준의 보안을 설정하는 것은 사용자가 스스로 결정해야하는 사안입니다.

토큰이 유출될 위험이 없고 SPA의 보안이 적절하다고 생각된다면 위 접근 방식을 사용해 더욱 효율적으로 애플리케이션유지보수 비용도 절감 할 수 있습니다. 

웹 애플리케이션을 보호하는 베스트 프랙티스는 PKCE 확장을 포함하는 인가 코드흐름을 통해 Keycloak 로그인 페이지로 리다이렉트하는 것을 알 수 있습니다. 

 

6. 네이티브 및 모바일 애플리케이션 보호

Keycloak을 통해 웹 애플리케이션을 보호하는 것이 네이티브 또는 모바일 애플리케이션을 보호하는 것보다 더 간단합니다. Keycloak 로그인 페이지는 기본적으로 웹 애플리케이션이며 사용자가 이미 브라우저를 사용하는 경우 다른 웹 애플리케이션으로 리다이렉트하는 것이 더 적절합니다. 애플리케이션 자체에서 로그인 페이지를 구현해 사용자 이름과 패스워드를 수집한 다음 OAuth2.0 리소스 소유자 패스워드 자격증명 부여를 활용해 토큰을 획득하고자 할 수도 있습니다.

하지만 이 방법은 권장하지 않습니다. 애플리케이션은 사용자 자격증명에 직접 접근해서는 안되며 해당 접근 방법은 또한 Keycloak에서 제공하는 다양한 기능을 활용하지 않음을 의미합니다.

네이티브 및 모바일 애플리케이션을 보호하려면 PKCE 확장이 포함된 인가 코드 흐름을 사용해야합니다.

해당 접근 방법은 좀 더 높은 보안을 제공함과 동시에 Keycloak이 가진 장점을 최대한 활용할 수 있게 해줍니다.

사실상 네이티브 또는 모바일 프로그램이 Keycloak 인증을 위해 브라우저를 사용해야함을 의미합니다.

이와 관련해 애플리케이션 유형에 따라 다음 세가지 옵션을 사용할 수 있습니다.

- 임베디드 웹 뷰 사용

- 외부 사용자 에이전트 사용(사용자의 기본 브라우저)

- 안드로이드 및 IOS와 같은 일부 플랫폼에서 지원하는 애플리케이션이 필요 없는 인앱 브라우저 탭 사용

 

임베디드 웹 뷰를 사용하게 되면 애플리케이션 내에 로그인 페이지를 배치할 수 있기 때문에 편리해 보일 수 있습니다. 하지만 해당 옵션은 자격증명 탈취와 관련된 취약점이 있기 때문에 권장하지 않습니다. 또한 여러 애플리케이션 간의 공유 쿠키가 없기 때문에 SSO를 사용하지 않습니다.

애플리케이션의 로그인 페이지를 표시하면서 시스템 브라우저를 활성화하기 때문에 인앱 브라우저 탭을 사용하는 것은 적절한 방법입니다.하지만 악의적인 애플리케이션이 인앱 브라우저탭과 유사한 애플리케이션 로그인 페이지를 랜더링해 자격증명을 탈취하는게 가능합니다. 해당 취약점을 피하고 싶은 사용자는 외부 브라우저에서 로그인 페이지를 접속하면 됩니다.

 

인가 코드를 애플리케이션에 반환하는 경우, OAuth2.0에서 정의한 특수 리다이렉트 URI를 사용하는 4개의 서로 다른 접근 방법이 존재합니다.

- Claimed HTTPS scheme : 일부 플랫폼에서는 애플리케이션이 HTTPS 구조를 요청할 수 있으며, 시스템 브라우저를 사용하는 대신 애플리케이션에서 URI에 접근할 수 있습니다. 예를 들어 https://app.test01.org/oauth2callback/provider-name URI를  Test01 APP 애플리케이션이 요청할 수 있으며  브라우저가 아닌 Test01 APP 에서 콜백이 실행된다.

- Custom URI Scheme : 사용자 설정 URI 구조를 애플리케이션에 등록한다. Keycloak이 해당 사용자 URI 구조로 리다이렉트하면 애플리케이션에 요청이 전송된다. 사용자 지정 URI 구조는 애플리케이션 개발자가 소유한 도메인의 역순과 일치해야 한다. 예를들어 org.test01.app://oauth2/providename 리다이렉트 URI는 app.test01.org 도메인 네임과 일치해야한다.

- Loopback interface : 애플리케이션은 루프백 인터페이스에서 임시 웹 서버의 임의의 포트를 오픈한 다음, http://127.0.0.1/oauth2/provider-name 리다이렉트 URI를 등록해 애플리케이션 웹서버에 요청을 보낼 수 있다.

- A special redirect URI: 특수한 urn:left:wg:oauth2:2.0:oob 리다이렉트 URI를 사용하면 인가 코드가 Keycloak에서 표시되기 때문에 사용자는 수동으로 인가 코드를 복사해 애플리케이션에 붙여넣기할 수 있다.

 

HTTPS 구조를 사용할 수 있는 경우 HTTPS가 더 안전하기 때문에 해당 접근 방식 사용이 권장됩니다. CLI 환경과 같이 HTTPS 구조와 사용자 지정 구조를 사용할 수 없는 경우 루프백 인터페이스를 활용하는것을 권장합니다.

그래픽 인터페이스 환경을 제공하지 않는 서버에서 터미널을 실행하는 경우와 같이 브라우저를 사용할 수 없는 상황도 존재합니다. 이런 경우 디바이스 코드 승인 유형을 활용하는 것이 권장됩니다.

요약하면, 디바이스 코드 승인 유형은 서로 다른 디바이스 브라우저에서 사용자가 인증서버의 특정 엔드포인트에 제공하는 짧은 코드를 표시하는 애플리케이션 기반에서 동작합니다.

코드를 입력하면 사용자가 로그인돼 있지 않은 경우 로그인을 해야합니다. 로그인을 하게 되면 애플리케이션은 인가 서버에서 인가 코드를 확인 할 수 있습니다.

 

7. REST API 및 서비스 보호

애플리케이션이 Keycloak으로 보호되는 REST API를 호출하려는 경우, 먼저 Keycloak에서 접근 토큰을 얻은 다음 REST API로 보내는 요청에 권한 부여 헤더에 접근 토큰을 포함합니다.

Authorization : bearer eyJkcGciOiJsuZ1NilsInR55c__

 

그러면 REST API는 접근 토큰을 확인해 접근 권한 승인 여부를 결정할 수 있습니다.

해당 접근 방식을 사용하면 많은 애플리케이션에서 활용할 수 있는 REST API를 쉽게 제공할 수 있으며, 또한 REST API를 서드파티 애플리케이션이 사용할 수 있도록 인터넷에서 공용 API로 사용할 수 있습니다.

마이크로서비스에서 토큰을 사용해 서비스를 보호하는 것은 서비스가 다른 서비스를 호출할 때 인증 컨텍스트를 전파 할 수 있기 때문에 다음 다이어그램과 같이 전체적인 사용자 종단 (end-to-end)간 인증을 쉽게 제공할 수 있으므로 특히 유용합니다.

위 그림에서 애플리케이션은 서비스 A를 호출할 때 접근 토큰을 포함합니다. 그다음 서비스 A는 동일한 접근 토큰을 사용해 서비스 B와 서비스 C를 호출하며, 모든 서비스가 동일한 인증 컨텍스트를 사용하게 됩니다.

Keycloak은 또한 서비스 계정을 지원하므로 서비스가 클라이언트 자격증명 승인 유형을 사용해 자체적으로 접근 토큰을 획득할 수 있습니다.

 

REST API만 토큰을 활용하는 것은 아닙니다. 다양한 프로토콜 인증에 자주 사용되는 SASL(Simple Authentication and Security Layer)은 bearer 토큰 또한 지원합니다. gRPC 및 Websockets은 안전한 호출을 위해 bearer 토큰을 활용할 수 있습니다. 

요약하면 요청에 Bearer 토큰을 포함해 서비스에 전송하면 해당 서비스는 토큰을 직접 검증하거나 토큰 점검 엔드포인트를 사용해 해당 요청의 수락여부를 결정한다는 것입니다.

 

이글에서는 Keycloak을 활용해서 애플리케이션을 보호하는 원리와 베스트 프랙티스에 대해 작성하였습니다.

다음글에서는 전체 애플리케이션을 Keycloak과 통합하기 위해 사용할 수 있는 옵션에 대해 작성하겠습니다.

수고하셨습니다.~

 

'WEB' 카테고리의 다른 글

Keycloak 시작하기 6  (0) 2025.02.11
Keycloak 시작하기 5  (0) 2025.02.11
Keycloak 시작하기 3  (1) 2025.02.03
Keycloak 시작하기 2  (0) 2025.01.23
Keycloak 시작하기 1  (0) 2025.01.21
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크