<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>진화하는공간</title>
    <link>https://marshmello.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 18 Jun 2026 06:07:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>마시멜로co.</managingEditor>
    <image>
      <title>진화하는공간</title>
      <url>https://tistory1.daumcdn.net/tistory/2823171/attach/4eeafffbca5748e784966f2022c5e9ab</url>
      <link>https://marshmello.tistory.com</link>
    </image>
    <item>
      <title>Keycloak 시작하기 10</title>
      <link>https://marshmello.tistory.com/105</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Keycloak 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번글에서는 Keycloak 서버 자체를 보호하는 몇가지 중요한 측면을 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1833&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dixiaM/btsMqJE0TLa/gGB61YzSgDa4MUuPtKqnZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dixiaM/btsMqJE0TLa/gGB61YzSgDa4MUuPtKqnZ1/img.png&quot; data-alt=&quot;[ 보안 배포 예시 ]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dixiaM/btsMqJE0TLa/gGB61YzSgDa4MUuPtKqnZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdixiaM%2FbtsMqJE0TLa%2FgGB61YzSgDa4MUuPtKqnZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1833&quot; height=&quot;662&quot; data-origin-width=&quot;1833&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[ 보안 배포 예시 ]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak과 해당 데이터베이스는 웹 애플리케이션 방화벽(WAF, Web Application Firewall)을 사용해 사용자 및 애플리케이션으로부터 격리되며 모든 네트워크 요청이 암호화되고 데이터베이스도 암호화됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에 송수신되는 트래픽에 TLS(Transport Layer Security)를 사용해야하는 이유를 먼저 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Keycloak에 대한 통신 암호화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak과의 통신에는 엔드 투 엔드 암호화 (end-to-end encryption) 사용을 권장합니다. 즉 HTTP가 아닌 HTTPS를 항상&amp;nbsp; 사용해야 합니다. 현재는 HTTPS의 가장 최근 보안 계층은 TLS 1.3이므로 가능하다면 해당 버전 사용을 권장합니다. 대부분의 HTTP 라이브러리는 최소 TLS 1.2를 지원합니다. TLS 1.2는 2008년부터 사용해왔기 떄문에 HTTPS 라이브러리가 TLS1.2를 지원하지 않는 경우 해당 라이브러리를 사용하지 않는 것을 고려해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;로드 밸런서 똔느 리버스 프록시를 Keycloak 앞단에 사용하고 있는 경우 가장안전한 접근 방식은 클라이언트와&amp;nbsp; Keycloak간에 엔드 투 엔드 암호화를 제공하는 TLS 패스스루(passthrough)를 활용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황에 따라 TLS 패스스루 사용이 어려울 수 있습니다. 이러한 경우 내부 인증서를 통해 프록시와 Keycloak간의 통신을 다시 암호화할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시와 Keycloak간에 암호화되지 않은 통신은 권장하지 않으며, 프록시와 Keycloak이 동일한 시스템에 있는 경우와 같이 프록시와 keycloak이 포함된 네트워크를 완전히 격리할 수 있는 경우에만 암호화되지 않은 통신을 고려할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Keycloak 호스트 이름 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 사용자에게 이메일을 전송하는 것과 같이 다양한 이유로 호스트 이름을 알아야 합니다. 일반적으로 Keycloak은 클라이언트가 전송한 Host HTTP 헤더를 통해 호스트이름을 확인합니다. 해당 설정은 공격자가 헤더에 다른 값을 사용해 Keycloak에 요청을 전송할 수 있기 떄문에 프로덕션 환경에서 사용하면 안됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 관련된 공격은 공격자가 Keycloak의 패스워드 복구 기능을 통해 호스트 헤더를 변경해 공격자가 제어할 수 있는 사이트에 대한 링크가 포함된 이메일을 사용자에게 전송하는 경우입니다. 사용자가 URL을 확인하지 않으면 공격자는 패스워드를 업데이트하기 위한 요청을 중간에서 가로챌 수 있습니다. 요청 가로채기를 통해 공격자는 업데이트된 암호를 획득하거나 다른 패스워들르 설정할 수 있습니다. 두 경우 모두 공격자는 사용자 계정에 대한 접근 권한을 얻습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 유형의 공격을 방어하려면 Keycloak에 대한 고정 호스트 이름을 설정하거나 Keycloak이 역뱡향 프록시를 사용하는 경우 역방향 프록시에서 호스트 헤더를 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에 고정 호스트네임을 설정하는 것이 가장 간단하고 안전한 접근 방법입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Keycloak에서 사용하는 서명키 순한&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 서명 및 패스워드 키를 주기적으로 순환하는 것을 권장합니다. 한단에 한번 정도 자주 수행하는 것이 좋습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 Keycloak은 중단없이 원활하게 키를 순환시킬 수 있도록 해줍니다. 신규 키를 활성화할 수 있으며 기존키는 여전히 토큰을 계속해서 검증할 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 순환은 다음과 같은 몇가지 이점을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 특정 키로 서명되거나 암호화된 컨텐츠의 양을 줄입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 키를 획득하려는 모든 사용자가 사용할 수 있는 시간을 줄입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 세션 제한 시간 설정에 관계없이 사용되지 않은 리프레시 토큰 또는 만료 시간이 긴 접근 토큰을 정리합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 공격자가 키에 접근할 수 있거나 최악의 상황에서 키가 유출된 경우 영향을 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 서명 키를 순환하려면 브라우저에서 관리자 콘솔에 접속해야합니다. 키를 순환하고자 하는 realm을 선택하고 Realm Settings로 이동한 다음 Keys를 클릭합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2518&quot; data-origin-height=&quot;1240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J8hGr/btsMr9CNe7J/cJKyUb1KnfkkkEpqkXMxvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J8hGr/btsMr9CNe7J/cJKyUb1KnfkkkEpqkXMxvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J8hGr/btsMr9CNe7J/cJKyUb1KnfkkkEpqkXMxvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ8hGr%2FbtsMr9CNe7J%2FcJKyUb1KnfkkkEpqkXMxvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2518&quot; height=&quot;1240&quot; data-origin-width=&quot;2518&quot; data-origin-height=&quot;1240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;realm에서 활성화된 서명 키 목록을 확인할 수 있습니다. Keycloak의 키는 3개의 다른 상태를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Active : 활성화 키는 신규 토큰에 서명하는데 사용되며, 우선 순위가 가장 높은 키는 특정 알고리즘에 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Passive : 수동키는 신규 토큰 서명에 사용되지 않지만 이전에 서명된 토큰을 검증하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Disabled : 비활성화된 키는 현재 사용하지 않는 키입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키를 순환하기 위한 첫번째 단계는 신규 활성화 키를 생성하는 것입니다. 신규 활성화 키를 생성한 후 이전 키가 비활성화되면 모든 활성 사용자 세션 및 토큰이 폐기됩니다. 이 방법은 키 유출이 의심되는 경우에만 사용해야 합니다. 그 외의 경우에는 기존키를 삭제하기 전에 모든 사용자 세션과 토큰이 신규 서명키로 업데이트되도록 일정 기간 동안 기존 키를 비활성화하는 것이 좋습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 키를 생성하려면 추가적인 키 제공자를 사용해야합니다. Add Providers 탭&amp;gt; Add provider 버튼&amp;nbsp;클릭합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJwArp/btsMq7FD4GX/0RLnoFznjfOyrwst3ehsxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJwArp/btsMq7FD4GX/0RLnoFznjfOyrwst3ehsxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJwArp/btsMq7FD4GX/0RLnoFznjfOyrwst3ehsxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJwArp%2FbtsMq7FD4GX%2F0RLnoFznjfOyrwst3ehsxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1584&quot; height=&quot;772&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하단의 rsa-generated를 선택합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1698&quot; data-origin-height=&quot;984&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uBSCP/btsMtei4cCr/nYTkfKz6sE6hC5UKy8HFak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uBSCP/btsMtei4cCr/nYTkfKz6sE6hC5UKy8HFak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uBSCP/btsMtei4cCr/nYTkfKz6sE6hC5UKy8HFak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuBSCP%2FbtsMtei4cCr%2FnYTkfKz6sE6hC5UKy8HFak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1698&quot; height=&quot;984&quot; data-origin-width=&quot;1698&quot; data-origin-height=&quot;984&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Save 버튼을 눌러 키를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1847&quot; data-origin-height=&quot;1108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZoG9p/btsMrlRgU3B/pPuQRsVe8dKFDuVnaIKglk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZoG9p/btsMrlRgU3B/pPuQRsVe8dKFDuVnaIKglk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZoG9p/btsMrlRgU3B/pPuQRsVe8dKFDuVnaIKglk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZoG9p%2FbtsMrlRgU3B%2FpPuQRsVe8dKFDuVnaIKglk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1847&quot; height=&quot;1108&quot; data-origin-width=&quot;1847&quot; data-origin-height=&quot;1108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key Active List를 보면 신규 생성된 키가 가장 높은 우선순위를 갖고 있기 때문에 신규 토큰을 서명하는데 사용됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2055&quot; data-origin-height=&quot;1118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ywv17/btsMtdqUz26/IRHyOLvhWFxK8kl7RMYxj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ywv17/btsMtdqUz26/IRHyOLvhWFxK8kl7RMYxj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ywv17/btsMtdqUz26/IRHyOLvhWFxK8kl7RMYxj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fywv17%2FbtsMtdqUz26%2FIRHyOLvhWFxK8kl7RMYxj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2055&quot; height=&quot;1118&quot; data-origin-width=&quot;2055&quot; data-origin-height=&quot;1118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 자동으로 쿠키와 토큰을 신규 키로 재서명하며 해당 작업은 사용자와 애플리케이션에 영향을 주지않습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 기본적으로 개인키를 데이터베이스에 저장합니다 적절한 데이터베이스 보안과 주기적인 키 순환을 사용하는 것이 가장 보편적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 보안기능으로 Keycloak은 외부 저장소에 키를 저장할 수 있습니다. Keycloak은 자바 키 저장소에서 키를 로드할 수 있습니다. 키에 대한 사용자 정의 소스를 구현할 수 있는 확장 메커니즘이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최고 수준의 보안을 위해 토큰 서명에 HSM(Hardware Security Module)과 같은 외부 서비스를 사용하는 것도 고려할 수 있습니다. 기본적으로 Keycloak은 현재 이러한 통합을 지원하지 않지만 사용자 정의 제공자를 직접 개발할 수 있는 확장 포인트를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 주기적인 Keycloak 업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠재적으로 공격자의 가장 좋은 동기 중 하나는 패치되지 않은 소프트웨어의 알려진 취약점에서 비롯됩니다. Keycloak 또는 운영체제를 주기적으로 업데이트하지 않으면 공격 가능한 패치되지 않은 알려진 취약점 리스트가 점점 더 늘어나게 됩니다. 신규 릴리스를 발견하고 신속하게 업데이트할 수 있는 프로세스를 갖추는 것이 특히 중요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의할 점은 Keycloak에는 장기간 지원되는 버전이 없다는 점입니다. 그 대신 지속적인 배포 모델, 또는 롤링 릴리스를 활용합니다. 이슈가 발생한 경우 Keycloak을 지속적으로 업데이트하면 변경 사항이 상당히 적기 떄문에 한번에 바이트 크기의 청크를 처리하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지속적인 릴리스를 사용하려면 대부분의 경우 업데이트 프로세스를 자동화하고 업그레이드가 프로덕션 시스템에 영향을 미치는지 여부를 신속하게 테스트할 수 있어야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장기간 지원되는 버전을 선호하는 경우 레드햇은 Keycloak의 장기 지원 버전인 Red Hat Single Sign-On을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 외부 저장소 시크릿을 Keycloak으로 다운로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이메일 서버에 접속하거나 디렉터리 서버에서 사용자를 연동하는 것과 같이 외부 시스템에 접근하기 위해 Keycloak에 자격증명을 제공해야 하는 몇가지 사용 사례가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 기본적으로 자격증명을 데이터베이스에 저장하지만 외부 저장소에서 자격증명을 가져올 수도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 외부 저장소와 통합할 수 있는 확장 메커니즘을 갖고 있습니다. 저장소 설정에 대한 자세한 정보는 Keycloak 서버 관리자 가이드를 참조하면 됩니다. &lt;a href=&quot;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740122846801&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Server Administration Guide&quot; data-og-description=&quot;Once you have an administrative account for the Admin Console, you can configure realms. A realm is a space where you manage objects, including users, applications, roles, and groups. A user belongs to and logs into a realm. One Keycloak deployment can def&quot; data-og-host=&quot;www.keycloak.org&quot; data-og-source-url=&quot;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&quot; data-og-url=&quot;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bRzTTh/hyYfCHeWqr/45JhQxg5fOuBkfAxaC9IT1/img.png?width=657&amp;amp;height=893&amp;amp;face=0_0_657_893,https://scrap.kakaocdn.net/dn/bF5odh/hyYfMJRCwp/9mEikQnHmHA0lBV1QKk7Q1/img.png?width=657&amp;amp;height=639&amp;amp;face=0_0_657_639,https://scrap.kakaocdn.net/dn/g5R5C/hyYjnuVft6/aNFJafrSj5MkgjpgdLiWkK/img.png?width=659&amp;amp;height=600&amp;amp;face=0_0_659_600&quot;&gt;&lt;a href=&quot;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.keycloak.org/docs/latest/server_admin/index.html#_vault-administration&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bRzTTh/hyYfCHeWqr/45JhQxg5fOuBkfAxaC9IT1/img.png?width=657&amp;amp;height=893&amp;amp;face=0_0_657_893,https://scrap.kakaocdn.net/dn/bF5odh/hyYfMJRCwp/9mEikQnHmHA0lBV1QKk7Q1/img.png?width=657&amp;amp;height=639&amp;amp;face=0_0_657_639,https://scrap.kakaocdn.net/dn/g5R5C/hyYjnuVft6/aNFJafrSj5MkgjpgdLiWkK/img.png?width=659&amp;amp;height=600&amp;amp;face=0_0_659_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Server Administration Guide&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Once you have an administrative account for the Admin Console, you can configure realms. A realm is a space where you manage objects, including users, applications, roles, and groups. A user belongs to and logs into a realm. One Keycloak deployment can def&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.keycloak.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 방화벽 및 침입 방지 시스템을 통한 Keycloak 보안&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소한 방화벽을 활용해 Keycloak에 송수신 트래픽을 제어하는 것을 권장합니다. 가능하면 Keycloak 및 데이터베이스를 내부 애플리케이션과 완전히 분리하는 것도 고려해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수신되는 트래픽의 경우 , HTTPS 트래픽만 허용하는 제한된 수신 트래픽 정책이 포함됩니다. 또한 Keycloak 관리자 콘솔 및 관리자 REST API 에 대한 접근을 내부 네트워크에서만 허용하는 것을 고려할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;송신 트래픽의 경우 , 사용자 환경에 따라 조금 더 까다로울 수 있습니다. 허용해야 하는 트래픽은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 로그아웃 요청과 같은 애플리케이션에 대한 HTTPS 백채널 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- LDAP과 같은 사용자 연동 제공자에 대한 연경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- OpenID 토큰 요청과 같은 외부 ID 제공자에 대한 백채널 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 사용해 내부 애플리케이션만 보호하는 경우 송신 트래픽을 보호하는 것이 더 간단할 수 있지만 네트워크 외부에 배포된 서드파티 애플리케이션도 보호해야&amp;nbsp; 하는 경우 작업이 더 어려울 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 침입 방지 시스템을 활용하는 것이 현명한 결정일 수 있습니다. 침입 방지 시스템은 서비스 거부 공격에 대응하는 데 도움을 주며 비정상적인 트래픽을 탐지하고 차단하는데 유용한 도구입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 보안을 고려하는 경우 , WAF(Web Application Firewall)를 활용하는 것도 좋은 방법이 될수 있습니다. WAF를 적절하게 설정하는 것은 상대적으로 복잡하고 주기적으로 업데이트를 수행해야 할 수도 있지만 해당 작업을 적절히 수행하는 경우 WAF는 공격에 대한 추가 보호 계층을 제공할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 데이터베이스 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 여러 가지 민감한 데이터를 자체 데이터베이스에 저장하기 떄문에 해당 데이터베이스는 안전하게 유지해야 하며, 공격자가 데이터베이스 접근하거나 수정하는 것을 방지해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak이 데이터베이스에 저장하는 데이터 예시는 다음과 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Realm 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 사용자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 클라이언트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에 보안 침해 사고가 발생해 공격자가 Keycloak 데이터에 접근할 수 있는 경우 발생할 수 있는 몇가지 상황은 다음과 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 공격자는 직원이나 고객에 대한 세부 정보에 접근할 수 있습니다. 해당 접근에 대한 영향은 저장된 개인 정보의 양에 따라 다르지만 공격자는 이메일 주소 리스트를 확보한 것만으로 충분할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 공격자는 사용자 자격증명에 접근할 수 있습니다. 패스워드는 데이터베이스에 단방향 해시로 저장되지만 공격자는 보안 수준이 낮은 패스워드 중 일부를 크랙할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 외부 및 키 저장소를 사용하는 경우 공격자는 데이터베이스에 저장된 시크릿(LDAP 연동 자격증명, SMTP 패스워드, Keycloak에서 사용되는 사설 서명키)에 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 내용은 몇가지 예시에 불과하지만 공격자는 일반적으로 매우 창의적이며 데이터를 악용할 모든 종류의 방법을 고안할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 강조해야할 중요한 점은 공격자가 데이터베이스에 직접 데이터를 가져오는 지 또는 데이터베이스 백업에서 데이터를 가져오는지 여부에 관계없이 데이터베이스 자체의 보안을 유지하는 것만큼이나 데이터베이스 백업을 보호하는것이 중요하다는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격자가 데이터베이스의 쓰기 접근 권한을 획득하면 Keycloak에 의해 보호되는 모든 애플리케이션에 접근할 수 있기 때문에 잠재적으로 상황이 더 악화될 수 있습니다. 즉 사용자의 자격증명을 도용하기 위해 realm 설정 또는 사용자 자격증명을 변경할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 방화벽을 사용한 데이터베이스 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스를 보호할 때 가장 먼저 해야할 일은 방화벽으로 데이터베이스를 보호하는 것입니다. 모든 트래픽은 기본적으로 차단해야하고, Keycloak 서버와 같은 필수적인 접근만 허용해야합니다. 또한 뚜렷한 이유가 없는한 아웃바운드 연결은 차단해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. 데이터베이스 인증 및 접근 제어 활성화&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 한 최소한의 사용자만 데이터베이스에 접근할 수 있어야 하며 , 작업을 수행하는데 필요한 최소한의 접근 권한만 가져야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 데이터베이스의 데이터와 스키마를 관리하기 떄문에 데이터베이스에 영구적인 접근 권한이 필요한 사람이 있는지 확인할 필요가 있씁니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak과 데이터베이스에 접근할 수 있는 모든 사용자는 강력한 암호를 사용해야 하며 로그인 시도가 실패하면 해당 계정을 중지시켜야합니다. 클라이언트 인증서와 같은 더 강력한 인증 메커니즘을 활용을 고려할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 접근 제어를 설정한 다음 암호화를 통해 전송 중인 데이터와 저장된 데이터를 보호해야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. 데이터베이스 암호화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 중인 데이터를 보호하려면 TLS를 사용해 데이터베이스에 대한 모든 연결을 암호화해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스가 실행 중인 서버에 불법적인 접근이 발생할 수 있기 떄문에 저장된 데이터를 보호하는 것이 중요하며 데이터베이스 백업 또한 암호화해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스를 적절하게 보호하기 위한 다양한 단계가 있으며 , Keycloak을 주기적으로 업데이트하는 것처럼 데이터베이스도 주기적으로 업데이트해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기업이 자체 데이터 센터를 소유한 경우 해당 작업을 수행할 수 있는 직원이 이미 있을 가능성이 높습니다. 그렇지 않은 경우 클라우드의 관계형 데이터베이스 서비스 활용을 고려할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12. 클러스터 통신 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에는 Keycloak 노드 클러스터를 생성할 때 활용되는 Infinispan이 포함돼 있습니다. 데이터베이스와 다르게 Keycloak은 대부분의 민감한 정보를 로컬 캐시에 저장하는 클러스터를 통해 민감한 정보를 전송하지 않으므로, 무효화를 위해서만 클러스터 통신을 활용합니다. Keycloak은 클러스터 전체에 분산된 클러스터의 사용자 세션에 대한 정보를 저장합니다. 세션 자체에는 세션 ID, 만료 날짜 및 연동된 클러이언트 세션과 같은 일부 정보가 포함됩니다. 공격자가 해당 정보에 대한 접근 권한을 획득해도 Keycloak을 통해 세션에 접근하려면 Keycloak에서 서명한 토큰이나 쿠키가 필요하기 때문에 공격 범위를 제한할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적어도 방화벽을 사용해 클러스터 통신을 보호하는 것이 권장됩니다. 그 밖의 추가적인 보안을 위해서 클러스터 통신에 대한 인증 및 암호화를 활성화할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터 인증을 활성화하면 인증되지 않은 노드가 클러스터에 포함되는 것을 방지 할 수 있습니다. 하지만 클러스터 멤버와 비멤버 간의 통신을 방지할 수는 없습니다 따라서 단순히 인증만 추가하는 것은 거의 이미가 없으며, 인증은 비대칭 암호화와 통합해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터 통신은 공유 키를 사용하는 대칭 암호화를 사용하거나 인증과 통합된 비대칭 암호화를 사용해 암호화할 수 있습니다. 가장 단순한 접근 방식은 대칭 암호화를 활성화하는 것이므로 해당 암호화를 활성화하는 방법에 대해 알아볼 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 단계는 공유 시크릿을 저장하는 자바 키 저장소를 생성하는 것입니다. 키 저장소를 생성하려면 터미널에서 다음 명령어를 실행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;13. 사용자 계정 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 계정 보안과 관련해 공격자가 사용자 계정에 접근하는 것을 보호해야하며 패스워드를 포함해 사용자에 관한 정보도 보호해야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격자로부터 사용자 계정을 보호하는 것은 단순히 패스워드를 인증 방법으로 사용하는 것이 아니라 강력한 인증을 통해서만 가능합니다. 사용자가 패스워드를 이중 인증 요소와 함께 사용중이더라도 패스워드를 보호하는 것이 중요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드는 강력한 패스워드 해싱 알고리즘 , 적절한 패스워드 정책 그리고 패스워드 무차별 대입 공격 보호 기능 활성화를 통해 보호돼야합니다. 또한 강력한 패스워드 정책과 다른곳에서 사용중인 패스워드를 재사용하지 않도록 사용자를 교육하는 것도 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드 정책을 설정하려면 Keycloak 관리자 콘솔을 열고 설정하고자 하는 realm을 선택합니다. 그다음 Authentication을 클릭한 다음 Policies 탭을 선택 &amp;gt;&amp;nbsp; Password Policy탭을 선택합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2504&quot; data-origin-height=&quot;1095&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFYkFs/btsMr7L1kGJ/s8HdVekDuEjbOBKi0ymcVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFYkFs/btsMr7L1kGJ/s8HdVekDuEjbOBKi0ymcVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFYkFs/btsMr7L1kGJ/s8HdVekDuEjbOBKi0ymcVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFYkFs%2FbtsMr7L1kGJ%2Fs8HdVekDuEjbOBKi0ymcVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2504&quot; height=&quot;1095&quot; data-origin-width=&quot;2504&quot; data-origin-height=&quot;1095&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Add policy 버튼을 클릭하여 사용할 정책을 선택하면 패스워드 정책을 선택할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;1345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnjL1H/btsMtn1le8i/KVgZ9dJD5ZbuDjOtCrkepk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnjL1H/btsMtn1le8i/KVgZ9dJD5ZbuDjOtCrkepk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnjL1H/btsMtn1le8i/KVgZ9dJD5ZbuDjOtCrkepk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnjL1H%2FbtsMtn1le8i%2FKVgZ9dJD5ZbuDjOtCrkepk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;535&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;1345&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 예시는 최소길이가 8자이고 하나 이상의 대문자 , 하나 이상의 소문자, 하나 이상의 특수문자 및 숫자를 포함하는 패스워드 정책 예시입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HBYzE/btsMq0GMOos/Vrq0M1EpzYldLyoySvSQFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HBYzE/btsMq0GMOos/Vrq0M1EpzYldLyoySvSQFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HBYzE/btsMq0GMOos/Vrq0M1EpzYldLyoySvSQFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHBYzE%2FbtsMq0GMOos%2FVrq0M1EpzYldLyoySvSQFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;726&quot; height=&quot;707&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1161&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 패스워드 무차별 대입 공격 보호 기능을 활성화하는 것을 권장합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Realm settings 좌측 메뉴 클릭 &amp;gt; Security defenses 탭 클릭 &amp;gt; Brute force detection 탭을 클릭합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1836&quot; data-origin-height=&quot;1177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/01kNY/btsMqKxvfEE/SSzrISRE7mFWiK8wiWs00K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/01kNY/btsMqKxvfEE/SSzrISRE7mFWiK8wiWs00K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/01kNY/btsMqKxvfEE/SSzrISRE7mFWiK8wiWs00K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F01kNY%2FbtsMqKxvfEE%2FSSzrISRE7mFWiK8wiWs00K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1836&quot; height=&quot;1177&quot; data-origin-width=&quot;1836&quot; data-origin-height=&quot;1177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Brute&amp;nbsp;Force&amp;nbsp;Protection의&amp;nbsp;Lockout&amp;nbsp;Mode&amp;nbsp;종류&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 88px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;Lockout Mode&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;Lockout permanently&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;로그인 실패 횟수를 초과하면 계정이 &lt;b&gt;영구적으로 차단&lt;/b&gt;됨&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;관리자가 직접 차단 해제해야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;Lockout temporarily&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;로그인 실패 횟수를 초과하면 계정이 &lt;b&gt;일정 시간 동안 차단&lt;/b&gt;됨&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;시간이 지나면 자동으로 차단 해제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 34px;&quot;&gt;Lockout permanently after temporary lockout&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 34px;&quot;&gt;일정 횟수까지는 &lt;b&gt;일시적 차단&lt;/b&gt;, 그러나 일정 횟수를 넘으면 &lt;b&gt;영구 차단&lt;/b&gt;됨&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 34px;&quot;&gt;공격 가능성을 점진적으로 줄임&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 환경에 따라 사용자와 관련된 다양한 수준의 데이터 또는 개인 식별 정보를 저장할 수 있습니다. 개인 정보 처리와 관련돼 취할 수 있는 몇가지 단계는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 반드시 필요한 사용자 정보만 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 애플리케이션에 노출되는 사용자 정보 제한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 데이터베이스 보안&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 비즈니스를 운영하는 지역의 개인 정보 관련 법률에 대한 이해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인정보취급을 가볍게 여겨서는 안됩니다. 개인 정보는 공격자에게 매우 중요하며 그자체로 판매될 수 있는 상품입니다. 이러한 정보가 유출되면 마갣한 벌금이 부과될 수 있으며 최악의 경우 비즈니스에 돌이킬수 없는 피해를 입힐 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;14. 애플리케이션 보안&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 애플리케이션이 인터넷에 노출되고 있기 때문에 공격 및 데이터 침해 사고 건수가 날로 증가하고 있습니다. 따라서 애프리케이션을 적절하게 보호해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근까지 공격에 대한 일반적인 대응 방법으로 방화벽과 VPS를 주요 보안 계층으로 활용해왔습니다. 이는 기업 환경의 경계 내에서 의심스러운 보안과 결함됐습니다. 더많은 직원이 재택 근무를 하고 개인 노트북이나 휴대폰을 사용함에 따라 이러한 상황은 점점 더 어려워지고 있습니다. 점점 더 많은 서비스가 파트너 또는 인터넷에 노출되고 있으며 기업 네트워크의 경계를 모호하게 만듭니다. 내부에 존재하는 것을 신뢰하고 외부에 있는 것은 신뢰하지 않는다는 아이디어는 공격자가 엔터프라이즈 네트워크 내부로 침투할 수 있는 다양한 방법이 있고, 내부 공격에 대한 보안 강도가 낮기 때문에 다소 신뢰성이 낮습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 방화벽보다 더 나은것이 필요합니다. Keycloak은 애플리케이션의 보안을 강화할 수 있는 훌륭한 툴이지만, 단순히 keycloak을 사용한다고 해서 애플리케이션이 안전해지진 않습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션 보안과 관련된 몇몇 단계는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 인증 : 사용자가 인증되고 세션이 생성되면 세션도 안전하게 보호돼야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 인가 : 최소 권한 접근은 준수할 필요가 있는 훌륭한 원칙이다.작업을 수행하기 위해 사용자에게 부여된 접근 권한을 제한해 위협에 노출된 계정이나 악의적인 직원의 영향을 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 범용적인 공격 이해 및 방어 : 인젝션 공격 및 XSS(Cross-Site Scriping)와 같은 범용적인 취약점을 활용한 공격으로부터 애플리케이션을 보호해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 주기적 업데이트 : 웹 애플리케이션 보안은 지속적인 노력이며, 애플리케이션의 보안을 향상시키기 위해 끊임없이 노력해야한다. 또한 프레임워크, 라이브러리 및 사용 중인 모든 도구를 주기적으로 업데이트해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 데이터 보안 : 민감한 데이터는 암호화해서 저장돼야 하며 전송 중인 데이터는 암호화돼야 한다. 백업 데이터 또한 암호화돼야 한다. 웹 애플리케이션과 마찬가지로 데이터 보안 또한 적절한 인증 및 인가 시스템을 갖고 있어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 로깅 및 모니터링 : 적절한 로깅 및 모니터링을 수행하지 않으면 보안 침해 발생을 식별할 수 없다. 로깅 및 모니터링은 진행 중인 공격으로 인한 더 큰 피해를 방지 할 수 있는 유용한 도구가 될수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 방화벽 : 방화벽과 웹 방화벽은 웹 애플리케이션에 추가적인 보안 계층을 형성한다. 보안을 웹 애플리케이션 방화벽에만 의존하는 것은 권장하지 않으며 애플리케이션 자체에 보안을 구축해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션 보안에 더 자세히 학습할 수 있는 자료는 OWASP(Open Web Application Security Project) Top 10입니다. OWASP Top 10은 웹 애플리케이션에 대한 가장 중요한 보안 위협리스트입니다. 각 위협에 대해 취약점에 관한 세부 설명과 애플리케이션을 보호하는 방법에 대한 팁을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 훌륭한 리소스는 애플리케이션 보안의 특정 영역에 대한 매우 간결한 정보가 포함된 여러 치트 시트(Cheat Sheet)를 제공하는 OWASP 치트 시트 시리즈입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;15. OAuth2.0 및 OpenID 커넥트 베스트 프랙티스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션에서 OAuth2.0과 OpenID 커넥트를 사용할 때 실수할 수 있는 부분이 많습니다. OAuth2.0 및 OpenID 커넥트 사용 방법에 대한 사양 자체는 매우 유연하며, 범용적인 취약점에 대응하기 위한 메커니즘은 옵션을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 인가 요청을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740127996875&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/auth?response_type=code&amp;amp;client_id=public-client&amp;amp;redirect_uri=https://example.com/myclient&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당요청에는 상태state 파라미터가 포함돼 있지 않습니다. PKCE도 사용되지 않습니다. 인가 서버에서 해당 파라미터들을 명시적으로 요청하지 않는 한 , 인가 요청은 아무런 문제가 없지만 일부 범용적인 취약점에 노출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT 사양에도 동일한 상황이 적용됩니다. 비교적 실수가 발생하기 쉽습니다. 한가지 예시는 사야에 포함된 none 알고리즘입니다. 해당 사양에는 유효한 토큰을 서명 알고리즘이 없이 사용할 수 있도록 명시하고 있으며 이러한 사실은 공격자가 악의적인 토큰을 쉽게 생성할 수 있음을 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안과 관련된 또 다른 중요한 작업이 FAPI(Financilal-Grade API) 워킹 그룹에서 진행되고 있습니다. 해당 워킹 그룹은 OIDC를 오픈 뱅킹에 활용하기 위해 OIDC의 매우 안전한 프로파일을 구축하는 것에서부터 시작됐습니다. 하지만 추가 보안이 필요한 OIDC의 모든 사용 사례에 해당 워킹 그룹이 생성한 프로파일을 적용할 수 있기 떄문에 이름에 지나치게 구애받을 필요가 없습니다. 해당 프로파일에 포함된 가장 중요한 내용은 베스트 프랙티스를 제공하는 2개의 OIDC 프로파일입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FAPI 1.0 - Part 1 : API 보안 프로파일 기준&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FAPI 1.0 - Part 2 : 개선된 보안 프로파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 프로파일들은 베스트 프렉티스 적용의 복잡성과 요구되는 보안 수준과의 균형을 유지할 수 있으며 필요한 사용 사례에 맞게 프로파일을 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak 팀은 또한 클라이언트 정책이라는 기능 생성을 통해 애플리케이션에서 OAuth2.0 및 OpenID Connect의 안전한 사용 방법을 좀 더 쉽게 적용할 수 있도록 큰 진전을 이루고 있습니다. 클라이언트 정책을 통해 필요한 보안 수준에 따라 다양한 애플리케이션에 대해 서로 다른 프로파일을 선택할 수 있으며, 애플리케이션에 대한 베스트 프랙티스를 쉽게 수행할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;16. Keycloak 클라이언트 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안에 영향을 줄 수 있는 Keycloak OIDC 클라이언트에서 사용할 수 있는 몇몇 설정 옵션에 대해 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2496&quot; data-origin-height=&quot;1265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGnGkz/btsMugBMbIH/o8z0r9fiLwhszkdiNcw8aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGnGkz/btsMugBMbIH/o8z0r9fiLwhszkdiNcw8aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGnGkz/btsMugBMbIH/o8z0r9fiLwhszkdiNcw8aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGnGkz%2FbtsMugBMbIH%2Fo8z0r9fiLwhszkdiNcw8aK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2496&quot; height=&quot;1265&quot; data-origin-width=&quot;2496&quot; data-origin-height=&quot;1265&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 설정을 검토하고 어떤 것이 보안과 더 관련됐는지 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;b&gt;Consent required :&lt;/b&gt; 해당 옵션은 클라이언트 애플리케이션이 사용자의 데이터를 요청할 때, 사용자가 사전에 이를 확인하고 승인할 수 있게 해주는 보안 및 개인정보 보호 기능입니다. 이 옵션을 활성화 하지 않으면 사용자는 애플리케이션에 설정된 접근 수준을 볼 수 없습니다. 서드파티 애플리케이션을 대상으로 해당 옵션을 활성화 해야합니다. 또한 CLI와 같은 네이티브 애플리케이션에도 이 옵션을 활성화 해야합니다. 즉 , 클라이언트(애플리케이션)가 사용자 정보를 요청할 때, 사용자가 그 정보 제공에 대해 명시적으로 동의하도록 요구하는 기능입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- C&lt;/span&gt;&lt;span&gt;lient authentication&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;b&gt; :&lt;/b&gt; 클라이언트 자격증명을 서버 측에서 안전하게 보관할 수 있는 경우 해당 설정을 활성화하는 것이 더 안전합니다. 해당 옵션은 OIDC 클라이언트의 유형을 정의합니다. 이 옵션을 활성화하면, OIDC 유형이 Confidential 접근 유형(비공개 접근 유형)으로 설정됩니다. 비활성화되면 Public 클라이언트 (공개 접근 유형)으로 설정됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;284&quot; data-start=&quot;148&quot;&gt;&lt;b&gt;Confidential 클라이언트:&lt;/b&gt;&lt;br /&gt;서버 사이드 애플리케이션과 같이 보안이 중요한 경우 사용됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;284&quot; data-start=&quot;218&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;281&quot; data-start=&quot;218&quot;&gt;클라이언트는 토큰 요청 시 반드시 &lt;b&gt;클라이언트 시크릿&lt;/b&gt;(또는 JWT 서명 등)을 사용하여 인증해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;416&quot; data-start=&quot;285&quot;&gt;&lt;b&gt;Public 클라이언트:&lt;/b&gt;&lt;br /&gt;브라우저나 모바일 애플리케이션처럼 클라이언트 시크릿을 안전하게 보관할 수 없는 경우 사용됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;416&quot; data-start=&quot;367&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;413&quot; data-start=&quot;367&quot;&gt;이 경우, 클라이언트 인증이 비활성화되어 별도의 인증 정보를 요구하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;- Standard Flow&amp;nbsp; :&lt;/b&gt;&amp;nbsp; 해당 옵션은 OAuth 2.0의 인가 코드 흐름(Authorization Code Flow)를 사용하도록 클라이언트를 구성하는 설정입니다. 인가 코드 흐름은 사용자가 Keycloak 로그인 페이지에서 인증을 완료한 후, 인가 코드를 클라이언트 애플리케이션으로 리다이렉트시켜줍니다. 클라이언트는 이 코드를 백엔드 서버에서 안전하게 액세스 토큰과 교환하게 됩니다. Standard flow 옵션은 액세스 토큰이 직접 브라우저에 노출되지 않고, 서버 측에서만 처리되기 때문에 보안성이 높습니다. 이는 민감한 정보 보호가 필요한 서버 기반 애플리케이션에 적합합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;관리 콘솔에서 클라이언트를 설정할 때, Standard flow 옵션을 활성화하면 해당 클라이언트는 인증 코드 기반의 표준 흐름을 사용하게 됩니다. 비활성화할 경우 다른 흐름(예: implicit flow 등)을 사용하도록 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;-&amp;nbsp; Implicit flow :&lt;/b&gt; 해당 옵션은 OpenID Connect의 Implicit Flow 인증 방식을 활성화하는 설정입니다. 이 옵션이 활성화되면, 사용자가 인증을 완료한 후 인가 코드 교환 절차 없이 바로 액세스 토큰과 ID 토큰이 클라이언트의 리다이렉트 URI로 전달됩니다. 사용자가 로그인하면 별도의 백엔드 코드 교환 과정 없이 클라이언트 애플리케이션으로 토큰이 직접 반환됩니다. Implicit&amp;nbsp;Flow는&amp;nbsp;서버&amp;nbsp;측&amp;nbsp;컴포넌트&amp;nbsp;없이&amp;nbsp;클라이언트에서&amp;nbsp;직접&amp;nbsp;토큰을&amp;nbsp;수신하는&amp;nbsp;웹&amp;nbsp;애플리케이션(예:&amp;nbsp;SPA)이나&amp;nbsp;모바일&amp;nbsp;애플리케이션에서&amp;nbsp;주로&amp;nbsp;사용됩니다.토큰이&amp;nbsp;브라우저에&amp;nbsp;직접&amp;nbsp;노출되기&amp;nbsp;때문에,&amp;nbsp;보안&amp;nbsp;위험이&amp;nbsp;상대적으로&amp;nbsp;클&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이러한&amp;nbsp;이유로&amp;nbsp;최신&amp;nbsp;권장&amp;nbsp;방식은&amp;nbsp;추가&amp;nbsp;보안&amp;nbsp;기능(PKCE)을&amp;nbsp;사용하는&amp;nbsp;Authorization&amp;nbsp;Code&amp;nbsp;Flow입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이, Implicit flow 옵션은 클라이언트 애플리케이션이 인증 후 토큰을 바로 받을 수 있도록 설정하지만, 보안 측면에서는 신중하게 사용해야 합니다. (비활성화 권장)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Direct access grants :&lt;/b&gt; &lt;span&gt;클라이언트가 사용자의 사용자 이름과 비밀번호에 접근하여 이를 Keycloak 서버와 직접 교환하여 액세스 토큰을 받는 방식입니다. OAuth2 사양에 따르면, 이는 이 클라이언트에 리소스 소유자 비밀번호 크레딧&amp;nbsp; 'Resource Owner Password Credentials Grant' 지원을 가능하게 합니다. 주로 신뢰할 수 있는 서버 측 애플리케이션이나 백엔드 서비스에서 사용됩니다. 사용자 자격 증명이 클라이언트에 직접 전달되므로, 보안에 취약할 수 있어 사용 시 주의가 필요합니다. (비활성화 권장)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Valid redirect URIs :&lt;/b&gt; 해당 옵션은 Keycloak 클라이언트 설정에서 인증 후 사용자를 리다이렉션할 수 있는 허용된 URI(엔드포인트)를 지정하는 기능입니다. 리다이렉트 URI와 정확히 일치하는 URI를 사용해야됩니다. 권장되는 URI 예시는 해당 링크와 같습니다. (https://your-app-domain.com/myclient/auth/callback) Keycloak은 모든 리다이렉트 URI에 와일드카드를 지원합니다.&amp;nbsp; 와일드 카드를 사용해야 하는 경우에는 다음 링크 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;/span&gt;https://your-app-domain.com/myclient/*)&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 와 같이 애플리케이션에서 사용할 수 있는 URI 요청으로 제한해야합니다.인증 및 토큰 발급 후, 민감한 정보(예: 인증 코드, 액세스 토큰)가 악의적인 사이트로 전송되는 것을 방지합니다.등록된 URI 외의 주소로 리다이렉션이 시도되면 요청이 거부되어 보안 위협을 줄입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Keycloak에서 지원하는 몇몇 서명 알고리즘을 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;- Reivset-Shamir-Adleman(RSA) 서명 :&lt;/b&gt; Keycloak에서 지원하는 기본 알고리즘입니다. 가장 안전한 옵션은 아니지만 가장 널리 사용되는 옵션이므로 기본값으로 사용됩니다. RSA 서명은 공개키 암호체계인 RSA 알고리즘을 기반으로 한 디지털 서명 방식입니다. 이 서명 방식은 데이터의 무결성과 인증, 부인방지(Non-repudiation)를 보장하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 데이터의 안전한 전송 및 인증을 위한 중요한 도구로 활용되며, 다양한 보안 애플리케이션 및 프로토콜에서 널리 사용되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- ECDSA(Elliptic Curve Digital Signature Algorithm) :&lt;/b&gt; &amp;nbsp;타원 곡선 암호학을 기반으로 한 디지털 서명 알고리즘입니다. 이는 RSA와 같은 전통적인 서명 방식보다 훨씬 짧은 키 길이로도 동일하거나 더 강력한 보안을 제공하여, 저장 공간 및 연산 자원이 제한된 환경에서도 효과적으로 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;- Hash-based Message Authentication Code(HMAC) :&lt;/b&gt; 대칭 키(Shared Secret)에 대한 접근 권한이 필요한 대칭 서명 알고리즘입니다. &amp;nbsp;데이터의 무결성과 인증을 보장하기 위한 메시지 인증 코드(MAC)를 생성하는 방식입니다. 이는 암호학적 해시 함수와 비밀 키를 결합하여, 전송되는 메시지가 변조되지 않았고, 올바른 발신자에 의해 생성되었음을 검증할 수 있도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RSA는 아직까지 안전한 알고리즘으로 고려되지만, 가능하면 RSA 대신 ECDSA를 사용해야합니다. 애플리케이션이 토큰 검사 엔드포인트를 사용해 토큰을 검증하도록 하려면 HMAC을 필수 시크릿으로 사용할 수 있습니다. 해당 설정은 Keycloak에서만 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 다양한 길이의 서명 해시를 선택할 수 있으며, 해시의 길이가 갈수록 더 높은 보안을 제공합니다. 리프레시 토큰 및 접근 토큰과 같이 상대적으로 토큰의 수명이 짧은 토큰의 경우 256비트 길이는 대부분의 사용 사례에서 충분히 안전한 것으로 간주됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또다른 중요한 옵션은 토큰 생명주기 설정입니다. Keycloak을 사용하면 개별 클라이언트의 접근 토큰 생명주기를 재정의할 수 있습니다. 또한 리프레시 토큰의 생명주기를 제어하는 클라이언트 세션 생명주기도 재정의할 수 있습니다. 해당 재정의를 통해 수명이 짧은 리프레시 토큰(1시간 미만)을 가진 수명이 긴 SSO 세션(하루 또는 1주)을 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수명이 짧은 리프레시 토큰은 리프레시 토큰이 유출된 경우 영향을 줄일 수 있으며 애플리케이션 HTTP 세션의 생명주기를 단축할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak 보안</category>
      <category>keycloak이란</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/105</guid>
      <comments>https://marshmello.tistory.com/105#entry105comment</comments>
      <pubDate>Fri, 21 Feb 2025 14:58:14 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 9</title>
      <link>https://marshmello.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글들에서 Keycloak이 IAM(Identity and Access Management) 솔루션으로서 제공하는 것에 대해 알아봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 확장해 기존 기능을 사용자 요구에 맞게 변경하거나 신규 기능을 추가해 제한된 설정 이외의 작업을 수행할 수 있습니다. 또한 Keycloak 디자인에 대한 개요와 IAM을 자신의 생태계에 신속하게 배치하는 것뿐만 아니라 IAM을 사용자의 요구에 맞게 빠르게 적용하는 것이 왜 완벽한 선택인지 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 서비스 공급자 인터페이스 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 언어에 이미 익숙하다면 서비스 제공자 인터페이스(SPI)를 알고 있을 것입니다. 그렇지 않은 경우 코드베이스를 변경하지 않고 확장 가능한 Java 애플리케이션의 기능을 추가하거나 변경하기 위한 플러그 가능한 매커니즘으로 생각할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 잘 정의된 인터페이스 집합을 통해 기능이 구현되는 확장성을 고려해 설계됐습니다. 다양한 인증 메커니즘을 통한 사용자 인증, 감사, ID 데이터를 가져오기 위해 레거시 시스템과의 통합, 클레임을 토큰과 매핑, 신규 사용자 등록 및 프로파일 업데이트 그리고 서드파티 ID 제공자 통합과 같은 기능들은 모두 서비스 인터페이스 집합 및 관련 서비스 제공자 인터페이스를 통해 수행됩니다. 캐싱, 스토리지 또는 Keycloak에서 지원하는 다양한 보안 프로토콜과 같은 핵심 기능 또한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 내용이 적용됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 기능은 3개의 주요 인터페이스를 기반으로 정의됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Spi&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- ProviderFactory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Provider&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 용어에 따르면 SPI는 기능의 다양한 구현을 로드하고 설명하기 위한 최상위 인터페이스입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ProviderFactory는 서비스 팩토리 인터페이스이며, 이름에서 알 수 있듯이 특정 구현의 라이프 사이클을 관리하고 Provider 인스턴스를 생성하기 위한 계약을 정의합니다. 팩토리는 또한 다른 제공자 구현과 총돌이 발생하지 않도록 SPI의 범위에서 고유한 식별자를 정의해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Provider는 기능을 구현하기 위해 실제 서비스 인터페이스입니다. 기존 기능을 사용자 정의하거나 신규 기능을 추가하기 위해 구현할 기본 인터페이스는 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2082&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6JWu1/btsMqOxYAz4/ko1tCwbU7zgy14Jb8UZqc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6JWu1/btsMqOxYAz4/ko1tCwbU7zgy14Jb8UZqc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6JWu1/btsMqOxYAz4/ko1tCwbU7zgy14Jb8UZqc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6JWu1%2FbtsMqOxYAz4%2Fko1tCwbU7zgy14Jb8UZqc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2082&quot; height=&quot;796&quot; data-origin-width=&quot;2082&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능 또는 Spi의 여러 구현을 허용함으로써, Keycloak은 신규 기능을 추가하거나 동작을 변경해 사용자 고유의 구현을 생성하고 개선할 수 있습니다. SPI 및 해당 제공자의 목록을 참조해 이 방법이 실제로 어떻게 적용되는지 알아보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 콘솔에 접속하고 우측 상단의 사용자 아이콘을 클릭합니다. 아이콘을 클릭하면 Realm Info 옵션이 포함된 서브 메뉴가 표시됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2544&quot; data-origin-height=&quot;1066&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kCy9H/btsMpJjXqYF/K62cFtuQXB1nxCNC2gry71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kCy9H/btsMpJjXqYF/K62cFtuQXB1nxCNC2gry71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kCy9H/btsMpJjXqYF/K62cFtuQXB1nxCNC2gry71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkCy9H%2FbtsMpJjXqYF%2FK62cFtuQXB1nxCNC2gry71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2544&quot; height=&quot;1066&quot; data-origin-width=&quot;2544&quot; data-origin-height=&quot;1066&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Realm Info 옵션을 클릭하면 서버런타임 정보와 Provider Info탭이 포함된 페이지가 표시됩니다. Provider Info 탭을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1869&quot; data-origin-height=&quot;1231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IU9MI/btsMoWj26Kz/KDu8ZguSku2KW7bSAxEjq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IU9MI/btsMoWj26Kz/KDu8ZguSku2KW7bSAxEjq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IU9MI/btsMoWj26Kz/KDu8ZguSku2KW7bSAxEjq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIU9MI%2FbtsMoWj26Kz%2FKDu8ZguSku2KW7bSAxEjq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1869&quot; height=&quot;1231&quot; data-origin-width=&quot;1869&quot; data-origin-height=&quot;1231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공자 리스트를 보면 위에서 제시한 다이어그램의 구현을 명확하게 확인 할 수 있습니다. 예를 들어 리스트 상단 입력 필드에 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;social을&lt;span&gt; 입력해 소셜 ID 제공자 통합과 관련된 결과만 필터링됩니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1ZeWH/btsMqahkHVE/UEzGQaKDbwKBXsXMkKjQl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1ZeWH/btsMqahkHVE/UEzGQaKDbwKBXsXMkKjQl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1ZeWH/btsMqahkHVE/UEzGQaKDbwKBXsXMkKjQl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1ZeWH%2FbtsMqahkHVE%2FUEzGQaKDbwKBXsXMkKjQl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;582&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;843&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 목록에서 볼 수 있듯이 social SPI에는 소셜 ID 제공자에 대해 서로 다른 제공자를 가집니다. required-action, protocol-mapper 등과 같은 다른 SPI에도 동일한 내용이 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 사용자 정의 제공자 패키징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 JAR(Java Archive)로 패키지된 사용자 정의 제공자를 사용합니다. 해당 클래스(ProviderFactory 및 Provider 구현) 외에도 Keycloak이 런타임에 사용자 정의 제공자를 검색하고 초기화할수 있도록 서비스 서술자(Service descriptor) 파일도 포함해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 서술자는 JAR파일 내의 META-INF/services 디렉터리에 있는 일반 파일이며 파일 이름은 구현중인 ProviderFactory 유형의 완전한 이름입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상의 com.acme.MyProvierFactory 팩토리를 예를 들면, 이전 절의 다이어그램 JAR파일은 다음과 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740034200667&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;: mycustomprovider.jar

META-INF/services/com.acme.MyProviderFactory

MyFirstProviderFactory.class

MyFirstProvider.class&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;META-INF/services/com.acme.MyProviderFactory 파일에는 com.acme.MyProviderFactory 구현에 대한 참조가 포함돼야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 사용자 정의 제공자 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 정의 제공자를 구현하는 경우 마지막 단계는 Keycloak에 사용자 제공자를 설치하는 것입니다. 해당 작업을 수행하기 위해 다양한 접근 방법을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- JAR 배포&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- WildFly 모듈 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- JEE(Java Enterprise Edition) EJB(Enterprise JavaBeans) JAR로 배포하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAR파일을 서버에 직접 배포하는 것이 사용자 정의 제공자를 설치하는 가장 일반적이고 간단한 방법입니다. JAR파일을 $KC_HOME/standalone/deployments 디렉터리에 복사하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 접근 방식을 사용하는 경우 Keycloak은 공급자를 적절하게 배포하는데 필요한 런타임 종속성을 자동으로 구성합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 모듈을 추가해 사용자 정의 제공자를 배포할 수도 있습니다. 모듈 개념을 잘 모르는 경우 Keycloak은 WildFly 애플리케이션 서버를 사용합니다. 해당 서버는 런타임 종속성을 정의하고, 로드하기 위해 JBoss 모듈을 기반으로 합니다. 해당 모듈은 $KC_HOME/modules 디렉터리에 포함돼 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 접근 방법을 적용하고자 하는 경우 고려사항은 다음과 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공통 종속성 집합을 공유하는 여러 제공자를 배포해야 할 때 매우 편리하다. 이 경우 각 종속성에 대한 모듈을 생성해 다른 모듈에서 참조할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로덕션 환경에서는 잠재적인 보안상의 이유로 배포 스캐너를 사용하지 않도록 설정해 런타임에 예기치 않은 변경을 방지할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 제공자 클래스 로더 및 해당 종속성에 대한 더 많은 격리 및 제어를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Keycloak에서 제공자를 EJB로 설치할 수 있습니다. 이 방법을 통해 WildFly 및 JEE에서 제공하는 몇몇 주요 기능들을 활용할 수 있습니다. 대부분 Keycloak API 및 SPI에만 사용하는 일반 Java 유형으로 구현되기 떄문에 일반적으로 제공자를 구현하거나 배포하기 위해 해당 방법을 사용하지 않습니다. 하지만 상황에 따라 JPA(Java Persistence API)를 사용해 기존 데이터베이스를 활용하거나 제공자의 JMS(Java Message Service)를 사용할 수 있는데, 이러한 상황이 Keycloak에서 해당 옵션을 지원하는 주요 이유 중 하나입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. KeycloakSessionFactory 및 KeycloakSession 컴포넌트 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 제공자를 관리하기 위해 KeycloakSessionFactory와 KeycloakSession을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KeycloakSessionFactory는 서버에 설치된 모든 제공자의 레지스트리 역할을 하며 생명 주기 관리를 담당합니다. Keycloak을 실행하면 KeycloakSessionFactory가 생성돼 서버에 설치된 제공자 팩토리를 초기화하고 등록합니다. 반대의 경우도 적용됩니다. Keycloak이 정상적으로 종료 절차를 진행하는 경우 KeycloakSessionFactory는 초기화 단계에서 생성된 리소스를 회수할 수 있는 마지막 기회를 팩토리에 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 Keycloak이 실행되고 요청을 처리하는 경우 Keycloak 세션이 생성돼 각 요청에 바인딩됩니다. KeycloakSession은 KeycloakSessionFactory를 기반으로 생성되며 realm,사용자 ,클라이언트, 세션을 관리하고 현재 realm 및 요청에 대한 컨텍스트 정보에 접근하고 제공자 인스턴스를 획득하기 위한 진입점 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션으로부터 획득한 제공자 인스턴스는 한번만 생성되며, KeycloakSesion의 생명주기 동안 캐시됩니다. KeycloakSession은 제공자 개발자가 제공자를 구현할 떄 가장많이 사용하는 구성요소입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 제공자의 생명주기 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공자는 초기화(initialization) 및 초기화 해제(Deinitialization)를 수행하기 위해 잘 정의된 생명주기를 갖습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공자를 설치하는 동안 Keycloak은 기화를 수행하기 위해 ProviderFactory구현의 특정 메서드를 호출합니다. 초기화 단계에서 생성된 리소스를 해제하기 위해 매서드 호출이 수행되는 서버가 정상적으로 종료될때도 마찬가지입니다. ProviderFactory의 생명 주기는 KeycloakSessionFactory가 초기화 또는 초기화 해제 수행될 때 초기화 및 초기화 해제가 한번만 수행되는 서버 생명주기에 바인딩됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 작업에 대한 유일한 예외는 런타임에 제공자를 재배포할때 입니다. 이 경우 초기화 및 초기화 해제가 여러번 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 단계는 제공자 초기화 단계에서 수행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) Keycloak은 각 SPI의 사용 가능한 모든 팩토리를 로드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) 각 팩토리에서 제공자 설정과 함께 init 메서드를 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3) 모든 팩토리가 초기화되고 등록되면각 팩토리에서 postinit 매서드가 호출돼 keycloakSessionFactory를 기반으로 추가 초기화 단계를 추행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;init 메서드는 $KC_HOME/standalone/configuration/standalone.xml파일의 특정 제공자로 설정된 구성을 기반으로 초기화하기 위해 팩토리 과정을 진행하는 과정 초기에 호출됩니다. 팩토리가 다른 팩토리나 KeycloakSession에 사용하지 않고 자체 초기화를 수행하는 경우 이 단계는 팩토리를 초기화 하기에 충분합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 postInit 메서드는 모든 팩토리가 등록된 후에만 호출되며, 초기화 중에 팩토리가 다른 제공자와 KeycloakSession 자체를 사용해 추가 단계를 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 제공자의 생명주기는 요청에 바인딩됩니다. 제공자는 해당 ProviderFactory에서 생성되며 요청 생명주기 동안 한 번만 발생합니다. 초기화 해제와 관련해 제공자의 close 메서드는 요청의 마지막에 호출됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 인터페이스 변경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자들이 가장 많이 사용하는 주요 사용자 정의 후크 중 하나는 Keycloak 기본 제공 테마를 브랜딩에 맞게 UI 및 UX 요구사항을 반영하기 위해 변경하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 테마를 변경할 수 있는 매우 간단한 환경을 제공하며, 사용자 페이지에서 관리 콘솔에 이르기까지 대부분의 UI를 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 테마 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak의 다른 기능과 마찬가지로 테마는 자체 SPI를 통해 지원됩니다. 하지만 테마를 변경하기 위해 자바 코드를 구현해야 하는 대신, Keycloak은 단순한 CSS 클래스, 자바스크립트 그리고 HTML 구조를 간단하고 우아한 방법을 제공합니다. 실제로 필요에 따라 테마를 변경하는 것은 새로운 CSS 스타일시트를 정의하는 것에 불과합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마의 또 다른 중요한 측면은 국제화(Internationalization입니다. 전 세계적인 프로젝트로서 Keycloak은 다양한 언어를 지원하는데 기여하고 있으며, 사용자의 추가 노력없이 해당 국가의 사용자가 이미 모국어로 된 Keycloak 을 사용하고 있을 가능성이 높습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 제공하는 기본 테마는 theme 디렉터리에 배포의 일부로 포함돼 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740098556786&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cd $KC_HOME\themes
$ ls
 base 
 keycloak
 keycloak-preview
 keycloak.v2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 내용은 &lt;a href=&quot;https://www.keycloak.org/docs/latest/server_development/index.html#_themes&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.keycloak.org/docs/latest/server_development/index.html#_themes&lt;/a&gt; 를 참고합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Base 테마는 테마가 아니라 페이지 템플릿, 국제화를 위한 메시지 번들 및 공동 리소스가 포함돼 다른 테마에서 사용될 수 있는 구조를 제공합니다. Keycloak 테마와 같은 다른 테마는 base 테마를 확장해 특정 CSS 스타일시트, 자바스크립트, 이미지 등을 사용해 레이아웃을 정의합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 theme 디렉터리에는 사용자가 정의가 가능한 Keycloak의 다양한 UI 집합에 대한 하위 디렉터리가 존재합니다. 해당 하위 디렉터리는 테마유형을 나타냅니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740113258351&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;themes/mytheme
├── account
├── admin
├── common
├── email
├── login
├── welcome&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- account : 계정 콘솔에 대한 UI 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- admin : 관리자 콘솔에 대한 UI 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- common : 테마 유형에서 사용되는 공통 리소스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- email : 이메일에 대한 UI 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- login : 프로파일 업데이트, 패스워드 리셋 등을 포함한 로그인 관련 페이지에 대한 UI 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- welcome : 웰컴 페이지에 대한 UI 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테마 유형에는 theme.properties 라는 필수 파일이 존재하며 해당 파일에 테마 유형의 설정을 정의합니다. 예시는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 다른 테마에서 설정 상속&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 다른 테마에서 리소스 가져오기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- CSS 스타일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 자바스크립트 리소스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- CSS 스타일을 Keycloak 컴포넌트(입력 상자 및 버튼)에 매핑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마 설정의 한가지 중요한 측면은 테마 유형을 사용자 정의하는 경우 처음부터 모든걸 설정하지 않고 다른 테마의 구성을 활용해 필요한 부분만 변경할 수 있다는 점입니다.&amp;nbsp; 기존 테마를 적절하게 변경하고 싶을 때 매우 편리합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;realm에 테마 설정하는 방법에 대해 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak 테마를 만들려면 themes 디렉터리 안에 원하는 테마 이름으로 새 폴더를 생성합니다. 예를 들어 mytheme이라는 테마를 만들고 싶다면 아래의 코드를 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740113844306&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;mkdir -p themes/mytheme&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마에 지원할 유형별로 하위 디렉터리를 생성합니다. 예를 들어 로그인 테마를 추가하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740113929947&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir -p themes/mytheme/login&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테마 유형 폴더안에 theme.properties 파일을 생성하고 테마 설정을 지정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740114009761&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ vi themes/mytheme/login/theme.propertie
parent=base
import=common/keycloak&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;936&quot; data-start=&quot;897&quot;&gt;parent=base : 기본 테마(base)를 확장합니다.&lt;/li&gt;
&lt;li data-end=&quot;999&quot; data-start=&quot;937&quot;&gt;import=common/keycloak : common/keycloak의 공통 리소스를 가져옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디렉터리에 CSS 스타일 시트, 자바스크립트 라이브러리 및 메시지 번들과 같은 필요한 정적 리소스를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115128323&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;├── theme/mytheme/
│   ├── login/
│   │   ├── theme.properties
│   │   ├── login.ftl
│   │   ├── resources/
│   │   │   ├── css/styles.css
│   │   │   ├── img/image.png
│   │   ├── messages/
│   │   │   ├── messages_en.properties&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마 유형을 정의하는 경우. 다음과 같은 표준 디렉터리 구조를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- resources 디렉터리는 Keycloak이 테마에서 사용하는 정적 리소스가 위치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- message 디렉터리는 메시지 번들을 가져오는 디렉터리입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 로그인 페이지 테마가 생성되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 실행하여 Keycloak Admin Console에 로그인합니다. 테마를 적용할 Realm을 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측 메뉴에서 Realm Settings 클릭 &amp;gt; Themes 탭을 선택합니다. Login theme에서 mytheme을 선택한 후 Save 버튼을 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2480&quot; data-origin-height=&quot;1081&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2sXyL/btsMqv00B5A/KjWPNkqwGllRjBXZSO70A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2sXyL/btsMqv00B5A/KjWPNkqwGllRjBXZSO70A0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2sXyL/btsMqv00B5A/KjWPNkqwGllRjBXZSO70A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2sXyL%2FbtsMqv00B5A%2FKjWPNkqwGllRjBXZSO70A0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2480&quot; height=&quot;1081&quot; data-origin-width=&quot;2480&quot; data-origin-height=&quot;1081&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 로그인 관련 페이지를 개별 클라이언트 기반으로 정의할 수 있습니다. 해당 설정을 통해 인증 대상 클라이언트에 따라 사용자 정의된 최종 사용자 환경을 제공할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트의 login 테마를 정의하려면 클라이언트를 선택하고 클라이언트 상세 페이지의 Login Theme 설정에서 테마를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2482&quot; data-origin-height=&quot;936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cC2dY2/btsMr9Ct0FN/MHrAmJjQxH71lbZgLZ6Jgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cC2dY2/btsMr9Ct0FN/MHrAmJjQxH71lbZgLZ6Jgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cC2dY2/btsMr9Ct0FN/MHrAmJjQxH71lbZgLZ6Jgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcC2dY2%2FbtsMr9Ct0FN%2FMHrAmJjQxH71lbZgLZ6Jgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2482&quot; height=&quot;936&quot; data-origin-width=&quot;2482&quot; data-origin-height=&quot;936&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 테마를 아카이브(JAR) 형태로 배포하기&lt;/h3&gt;
&lt;p data-end=&quot;211&quot; data-start=&quot;122&quot; data-ke-size=&quot;size16&quot;&gt;테마를 배포할 때, META-INF/keycloak-themes.json 파일을 추가하여 사용할 수 있는 테마 목록과 제공하는 테마 유형을 정의해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;281&quot; data-start=&quot;213&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어, mytheme이라는 테마를 배포하려면 mytheme.jar 파일을 다음과 같은 구조로 생성해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115361727&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mytheme.jar
├── META-INF/
│   ├── keycloak-themes.json
├── theme/mytheme/
│   ├── login/
│   │   ├── theme.properties
│   │   ├── login.ftl
│   │   ├── resources/
│   │   │   ├── css/styles.css
│   │   │   ├── img/image.png
│   │   ├── messages/
│   │   │   ├── messages_en.properties
│   ├── email/
│   │   ├── messages/
│   │   │   ├── messages_en.properties&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아카이브에는 META-INF/keycloak-themes.json 파일이 포함되어야 합니다. 이 파일에는 테마 정보가 JSON 형식으로 정의됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115392145&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;themes&quot;: [
    {
      &quot;name&quot;: &quot;mytheme&quot;,
      &quot;types&quot;: [&quot;login&quot;, &quot;email&quot;]
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1025&quot; data-start=&quot;928&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;958&quot; data-start=&quot;928&quot;&gt;&quot;name&quot;: &quot;mytheme&quot; &amp;rarr; 테마의 이름&lt;/li&gt;
&lt;li data-end=&quot;1025&quot; data-start=&quot;959&quot;&gt;&quot;types&quot;: [&quot;login&quot;, &quot;email&quot;] &amp;rarr; 이 테마가 지원하는 유형(로그인 페이지 및 이메일 템플릿)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1156&quot; data-start=&quot;1085&quot; data-ke-size=&quot;size16&quot;&gt;테마의 동작을 설정하는 파일로, theme/mytheme/login/theme.properties에 다음 내용을 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115463961&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;parent=base
import=common/keycloak&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1409&quot; data-start=&quot;1341&quot; data-ke-size=&quot;size16&quot;&gt;theme/mytheme/login/login.ftl 파일을 만들어 사용자 정의 로그인 페이지를 디자인할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;1409&quot; data-start=&quot;1341&quot; data-ke-size=&quot;size16&quot;&gt;(참고 : &lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://freemarker.apache.org/&quot;&gt;&amp;nbsp;&lt;/a&gt;&lt;a href=&quot;https://freemarker.apache.org/&quot;&gt;https://freemarker.apache.org/)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740115546641&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;What is Apache FreeMarker&amp;trade;?&quot; data-og-description=&quot;Apache FreeMarker&amp;trade; is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates and changing data. Templates are written in the FreeMarker Template Language (FTL), which&quot; data-og-host=&quot;freemarker.apache.org&quot; data-og-source-url=&quot;https://freemarker.apache.org/&quot; data-og-url=&quot;https://freemarker.apache.org/index.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://freemarker.apache.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://freemarker.apache.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;What is Apache FreeMarker&amp;trade;?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Apache FreeMarker&amp;trade; is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates and changing data. Templates are written in the FreeMarker Template Language (FTL), which&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;freemarker.apache.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740115495649&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;#import &quot;template.ftl&quot; as layout&amp;gt;
&amp;lt;@layout.registrationLayout displayMessage=true&amp;gt;
  &amp;lt;h1&amp;gt;Welcome to My Custom Theme!&amp;lt;/h1&amp;gt;
&amp;lt;/@layout.registrationLayout&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마의 CSS 및 이미지 파일을 resources 폴더에 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1690&quot; data-start=&quot;1642&quot;&gt;theme/mytheme/login/resources/css/styles.css&lt;/li&gt;
&lt;li data-end=&quot;1738&quot; data-start=&quot;1691&quot;&gt;theme/mytheme/login/resources/img/image.png&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다국어 메시지 파일을 messages 폴더에 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1871&quot; data-start=&quot;1807&quot;&gt;로그인 메시지: theme/mytheme/login/messages/messages_en.properties&lt;/li&gt;
&lt;li data-end=&quot;1936&quot; data-start=&quot;1872&quot;&gt;이메일 메시지: theme/mytheme/email/messages/messages_en.properties&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 JAR 파일을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115628191&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jar cf mytheme.jar -C theme/mytheme/ . -C META-INF/ .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 zip을 사용하여 생성할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115645423&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;zip -r mytheme.jar META-INF theme&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 mytheme.jar 파일을 Keycloak의 providers 디렉터리에 복사합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115663236&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cp mytheme.jar $KEYCLOAK_HOME/providers/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런 다음 Keycloak을 다시 시작하면 테마가 적용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740115678670&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bin/kc.sh build
bin/kc.sh start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Keycloak을 실행하여 Keycloak Admin Console에 로그인합니다. 테마를 적용할 Realm을 선택합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;좌측 메뉴에서 Realm Settings 클릭 &amp;gt; Themes 탭을 선택합니다. Login theme에서 mytheme을 선택한 후 Save 버튼을 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. 템플릿 확장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때때로 CSS 스타일만 사용해 테마를 확장하는 것만으로 충분하지 않고 base 테마의 페이지 템플릿 컴포넌트 처리를 변경해야 하는 경우도 있습니다.&amp;nbsp; Keycloak은 잘 알려져 있고 널리 사용되는 템플릿 엔진인 아파치 프리마커를 사용해 템플릿을 기반으로 페이지를 렌더링합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서 base 테마의 테마 유형 중 하나에서 템플릿을 복사해 사용자 정의 테마 유형에 포함시키면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이러한 유연성은 Keycloak이 릴리스될 때마다 기본 제공 템플릿에 대한 변경사항을 사용자 정의 템플릿에 수동으로 적용해야 하는 번거로움이 발생합니다. 테마에 사용자 정의를 적용하는 방법은 매우 편리하지만 Kecloak이 해당 템플릿을 정의하는 방법에 대한 추가적인 지식이 요구됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak css</category>
      <category>keycloak themes</category>
      <category>keycloak 테마</category>
      <category>keycloak 테마 설정</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/104</guid>
      <comments>https://marshmello.tistory.com/104#entry104comment</comments>
      <pubDate>Thu, 20 Feb 2025 15:56:41 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 8</title>
      <link>https://marshmello.tistory.com/103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 통합 인증 및 인가 서비스 역할 외에도 세션 및 토큰 관리 시스템 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 프로세스의 일환으로 Keycloak은 서버 사이드 세션을 생성하고 토큰과 연동할 수 있습니다. 해당 세션을 통해 Keycloak은 세션이 시작된 인증 컨텍스트의 상태를 유지하고 사용자 및 클라이언트의 활동을 추적하며, 토큰의 유효성을 확인해 사용자와 클라이언트가 언제 재인증을 수행해야하는지 결정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 통한 토큰 및 토큰 기반 세션 관리 방법과 이러한 작업을 수행할때 주의해야 할 다양한 부분에 대해 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 세션 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 관리는 사용자 경험, 보안 그리고 성능과 같은 중요한 지표에 직접적인 영향을 미칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 경험 관점에서 Keycloak은 세션에 활용해 사용자와 클라이언트의 인증 여부, 인증 기간, 재인증 시기 등을 결정합니다. 세션의 이러한 특성은 기본적으로 동일한 영역 내의 서로 다른 클라이언트를 인증하는 경우 사용자에게 싱글 사인온 환경을 제공하고 통합 인증 경험을 실현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안 관점에서 세션은 사용자 활동을 추적 및 제어하고 클라이언트에게 발급된 토큰이 사용자를 대신해 작동할 수 있는 유효한 토큰인지 확인하기 위한 보안 계층을 제공합니다. 세션 또는 토큰이 유출되거나 탈취됐을 경우 공격 표면을 제한할 수 있기 떄문에 사용자의 realm 및 해당 클라이언트와의 세션유지시간을 제한하고 제어하는 것 또한 중요합니다. 세션은 악의적인 행위자의 비인가 접근 차단 또는 대응을 하기 위해 관리자, 사용자 및 클라이언트가 조기에 무효화 시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 측면에서 세션은 메모리에 저장되며 Keycloak의 전반적인 성능에 직접적인 영향을 미칩니다. Keycloak은 세션을 공유 캐시에 저장합니다. 여기서 활성 세션의 개수와 활성 세션 유지 시간은 메모리와 CPU 리소스를 최적화하기 위해 균형을 유지해야하는 주요 요소입니다. 이러한 점들을 고려할 때 Keycloak은 여기에 언급된 세가지 측면의 균형을 유지하는 유연한 세션 및 토큰 관리를 제공합니다. 관리자는 사용자 및 클라이언트의 활성 세션을 추적하고, 사용자가 인증한 클라이언트를 확인하며 세션 무효화를 위해 단일 또는 전역 로그아웃을 수행하고 토큰을 폐기하고 세션 및 토큰 생명주기의 다양한 측면을 제어할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 세션 생명주기 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 프로덕션 환경에 적용하기 전에 결정해야하는 첫번째 질문 중 하나는 얼마나 자주 사용자와 클라이언트가 재인증을 수행해야하는지 정하는 것입니다. 이 질문에 적절한 해답을 찾기 위해서는 Keycloak이 세션을 생성하는 방법과 세션의 생명주기를 정의하는 방법을 알고 있어야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 생명주기는 세션이 만료되고 삭제되는 시기를 결정합니다. 세션이 만료되면 해당 세션과 관련된 사용자 및 클라이언트는 인증된 상태를 유지할 수 없고 신규 세션을 생성하기 위해 재인증을 수행해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 백그라운드 작업을 사용해 세션을 만료하고 만료된 세션을 확인합니다. 기본적으로 작업은 15분마다 실행됩니다. 필요한 경우 해당 값을 수정할 수 있지만 기본설정을 사용하는 것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 사용자를 인증하는 경우 다양한 레벨에서 세션을 생성합니다. 첫번째 레벨에서 클라이언트에 관계없이 사용자 활동을 추적하기 위해 사용자 세션이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 레벨은 SSO(Single Sign-On) 세션이라고 하며 사용자 세션이라고도 합니다. 두번째 레벨에서 Keycloak은 사용자가 인증된 사용자 세션에서 각 클라이언트의 사용자 활동을 추적하기 위해 클라이언트 세션을 생성합니다. 클라이언트 세션은 토큰의 유효성 및 애플리케이션에서 토큰을 사용하는 방식과 밀접하게 관련돼 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최상위 세션인 SSO 세션 생명주기는 사용자와 클라이언트가 재인증을 수행해야하는 빈도를 설정하기 위해 사용하는 전역 설정입니다. Keycloak을 사용하면 SSO세션이 활성 상태로 유지하는 최대 시간과 세션이 조기에 만료되는 유휴 시간을 설정할 수 있습니다. SSO 세션이 만료되면 해당 SSO 세션과 연동된 모든 클라이언트 세션 또한 만료됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSO 세션은 HTTP 세션과 유사합니다. 두 세션 모두 동일한 에이전트가 전송하는 여러 개의 요청에서 상태를 추적하고 유지하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 생명주기를 설정하려면 좌측 패널의 Realm Setting &amp;gt; Sessions 탭을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwRP64/btsMmKcOx17/FdYPBicKh2n9w7nkz7tvY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwRP64/btsMmKcOx17/FdYPBicKh2n9w7nkz7tvY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwRP64/btsMmKcOx17/FdYPBicKh2n9w7nkz7tvY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwRP64%2FbtsMmKcOx17%2FFdYPBicKh2n9w7nkz7tvY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2490&quot; height=&quot;1260&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;SSO Session Idle&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;및 &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;SSO Session Max 설정을 통해 SSO 세션의 유휴 시간과 최대 시간을 각각 설정할 수 있습니다. 설정이 적용되면 세션ㅇㄴ 일정시간 동안 활성화상태로 유지돼야 하고, 최대 시간보다 길지 않아야 합니다. 그리고 동시에 Keycloak은 세션 조기 만료 여부를 결정하기 위해 특정시간(유휴 시간)동안 사용자 활동을 확인합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;기본적으로 Keycloak은 SSO 세션의 생명주기를 10시간으로 정의합니다. 해당 시간은 세션이 최대 10시간동안 지속될수 있고 그 이후에는 만료된다는 것을 의미합니다. 하지만 유휴 시간의 타임아웃은 기본 30분으로 설정되고 있고 이는&amp;nbsp;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak이 30분 이내에 사용자 활동을 확인하지 못하면 설정된 최대 시간에 관계없이 세션이 만료됨을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;사용자가 인가 포인트를 통해 직접 통신하거나 토큰이 클라이언트에 의해 간접적으로 갱신되는 것과 같이 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak과 상호작용하는 유휴 시간 타임아웃은 갱신됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;사용자가 인증을 수행한 후 자리를 비우고 토큰을 갱신하지 않으면 사용자 세션은 30분 후에 만료됩니다. 하지만 사용자가 브라우저를 통해 지속적으로 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak과 통신하거나 클라이언트가 지속적으로 토큰을 갱신하면 사용자 세션은 최대 10시간까지 유지할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;SSO&lt;span&gt; 세션과 마찬가지로 관리자는 클라이언트 세션의 유휴 및 최대 시간을 설정하기 위해 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Client Session Idle 및&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;Client Session Max&lt;/span&gt;&lt;span&gt; 을 각각 설정할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p2dzV/btsMohmLoo1/eZxc8vKBrQfaWmzA8b2KeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p2dzV/btsMohmLoo1/eZxc8vKBrQfaWmzA8b2KeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p2dzV/btsMohmLoo1/eZxc8vKBrQfaWmzA8b2KeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp2dzV%2FbtsMohmLoo1%2FeZxc8vKBrQfaWmzA8b2KeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;891&quot; height=&quot;397&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;397&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;위의 두가지 설정은 토큰의 유효 기간에 대한 최댓값을 정의하고 클라이언트가 토큰을 재인증을 수행하도록 함으로써 관리자에게 클라이언트 세션 생명주기에 대한 세밀한 제어를 제공해줍니다.즉, realm 클라이언트에 발급된 토큰은 설정한 최대 시간까지만 유효하며 클라이언트가 유후 기간내에 토큰을 갱신하지 않으면 클라이언트 세션이 조기에 만료되고 토큰이 폐기됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;하지만 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;SSO&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;세션과 다르게 클라이언트 세션이 만료되고, &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;SSO&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;세션이 만료되지 않은 경우 사용자는 재인증을 반드시 수행할 필요는 없지만 신규 토큰을 생성하기 위해 클라이언트는 재인증을 수행해야 합니다. 클라이언트 세션이 만료된 경우 클라이언트 재인증을 수행하기 위해 사용자는 Keycloak으로 리다이렉트 되고, 브라우저를 사용하는 경우 사용자 경험에 영향을 미칠 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;기본적으로 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 클라이언트 세션의 생명 주기를 제어하기 위한 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;SSO&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;세션과 동일한 설정 집합을 정의합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Client Session Idle 및 &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Client Session Max&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; 설정값을 0이 아닌 값으로 변경해 클라이언트 세션의 다양한 생명주기를 정의할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;경험에 비춰볼때 보안, 퍼포먼스 및 사용자 경험 측면을 고려해 세션의 생명주기를 가능한 한 짧게 설정해야합니다. 이러한 짧은 생명주기를 통해 세션 하이재킹 공격 또는 토큰 유출이나 도난에 대한 영향을 최소화할 수 있습니다. 또한 사용자의 활동을 보여주지 않는 세션에 의해서 서버에 과부하가 걸리는 것을 회피하고 메모리나 CPU 등의 서버 리소스 낭비를 막을 수 있습니다. 하지만 짧은 세션 생명주기는 사용자 경험과 사용자 재인증 횟수에 직접적인 영향을 미칩니다. 사용자 우선 접근법에서는 사용자에게 최적인 것부터 시작해 보안 요구 사항 및 메모리와 CPU와 같은 리소스 제약에 따라 세션 생명주기를 조정합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;span&gt;3. 활성 세션 관리&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 관리자에게 다양한 수준의 뛰어난 세션 추적성과 가시성을 제공합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- realm 별&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- 클라이언트별&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- 사용자별&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;관리자는 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;realm 레벨에서 클라이언트별로 활성 세션 개수에 대한 통계를 볼 수 있습니다. 해당 통계를 확인하려면 좌측 패널의 Settings 링크를 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;1093&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn2Z6U/btsMmYhEdzp/RHKNemzGtz13vF6y1uXxj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn2Z6U/btsMmYhEdzp/RHKNemzGtz13vF6y1uXxj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn2Z6U/btsMmYhEdzp/RHKNemzGtz13vF6y1uXxj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn2Z6U%2FbtsMmYhEdzp%2FRHKNemzGtz13vF6y1uXxj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2508&quot; height=&quot;1093&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;1093&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;해당 페이지에서 임의의 클라이언트를 클릭하면 활성 세션에 대한 자세한 내용을 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTmt37/btsMnZmnHqH/9kqK8hVrH2u3O0CMUhP6vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTmt37/btsMnZmnHqH/9kqK8hVrH2u3O0CMUhP6vK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTmt37/btsMnZmnHqH/9kqK8hVrH2u3O0CMUhP6vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTmt37%2FbtsMnZmnHqH%2F9kqK8hVrH2u3O0CMUhP6vK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1357&quot; height=&quot;247&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트를 선택하면 클라이언트 상세 페이지의 Sessions 탭으로 리다이렉트됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ITRKW/btsMmo2iP2f/tyrgStGsaFopLwNX8cLp7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ITRKW/btsMmo2iP2f/tyrgStGsaFopLwNX8cLp7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ITRKW/btsMmo2iP2f/tyrgStGsaFopLwNX8cLp7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FITRKW%2FbtsMmo2iP2f%2FtyrgStGsaFopLwNX8cLp7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2508&quot; height=&quot;675&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 페이지에서 사용자 IP주소 및 세션 시작 시간 등과 같은 세션에 대한 몇가지 세부 정보에 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 페이지에서 임의의 사용자를 클릭하면 활성 세션의 세번째 및 마지막 표시 수준인 사용자 상세 페이지로 리다이렉트됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LOozz/btsMmpmsc0D/S7LYdjfFnO9KZby5IdPOW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LOozz/btsMmpmsc0D/S7LYdjfFnO9KZby5IdPOW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LOozz/btsMmpmsc0D/S7LYdjfFnO9KZby5IdPOW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLOozz%2FbtsMmpmsc0D%2FS7LYdjfFnO9KZby5IdPOW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1672&quot; height=&quot;423&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 탭에서 세션이 시작된 시간, &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak이 사용자와 여러 클라이언트 및 클라이언트 세션에 대한 자세한 정보가 제공됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2512&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPex9t/btsMowxepbr/BE4vJEr0fyStkKdodbfZI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPex9t/btsMowxepbr/BE4vJEr0fyStkKdodbfZI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPex9t/btsMowxepbr/BE4vJEr0fyStkKdodbfZI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPex9t%2FbtsMowxepbr%2FBE4vJEr0fyStkKdodbfZI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2512&quot; height=&quot;738&quot; data-origin-width=&quot;2512&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 경우 단일 세션을 가진 사용자와 여러 클라이언트가 표시됩니다. 이는 사용자가 브라우저를 사용해 인증하는 일반적인 SSO에 적합하며 동일 세션이 서로 다른 클라이언트를 인증하기 위해 재사용됩니다. 하지만 사용자가 브라우저를 닫거나 쿠키를 지우거나 다른 기기를 사용해 인증할 수 있습니다. 이런 경우 단일 사용자는 여러개의 사용자 세션을 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 사용자 세션 조기 종료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 통계 정보를 제공하는 것 외에도 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 각기 다른 레벨에서 세션을 조기에 만료되는 메커니즘을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;realm 레벨에서 활성 세션을 확인하는 경우 Action &amp;gt; Sign out all active sessions 버튼을 클릭해 realm 의 전체 활성 세션을 만료할 수 있습니다.&amp;nbsp; Revocation(폐기, 무효화)란, 발급된 인증 정보(예: 토큰, 인증서, 권한)를 더 이상 사용할 수 없도록 무효화하는 과정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2500&quot; data-origin-height=&quot;733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rsrVD/btsMnn9nxD7/tfKlf8Tsf25Xuf9qJ5QaVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rsrVD/btsMnn9nxD7/tfKlf8Tsf25Xuf9qJ5QaVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rsrVD/btsMnn9nxD7/tfKlf8Tsf25Xuf9qJ5QaVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrsrVD%2FbtsMnn9nxD7%2FtfKlf8Tsf25Xuf9qJ5QaVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2500&quot; height=&quot;733&quot; data-origin-width=&quot;2500&quot; data-origin-height=&quot;733&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;realm 또는 사용자 레벨에서 모든 세션을 로그아웃하기 위해 위의 방법 중 하나를 사용하는 경우 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 전체 세션을 순회하며 하나씩 만료시킵니다. 사용자 레벨에서 활성 사용자 세션이 많진 않지만 사용자가 인증된 클라이언트 개수에 따라 클라이언트 세션이 많을 수 있습니다. 하지만 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;realm에 인증된 전체 사용자의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;realm&lt;span&gt; 세션을 만료시키는 작업은 많은 자원이 필요할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;5. 쿠키 및 세션과의 관련성 이해&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;HTTP는 무상태(stateless) 프로토콜이며 브라우저와 서버 사이의 상태를 공유하기 위해 쿠키를 사용합니다. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 사용자가 브라우저를 통해 통신하는 경우 사용자의 세션을 추적하기 위해 &lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;HTTP 쿠키를 활용합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;사용자를 성공적으로 인증한 다음 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 KEYCLOAK_IDENTITY 쿠키를 통해 브라우저 세션을 서버의 사용자 세션과 연동합니다. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;KEYCLOAK_IDENTITY 쿠키가 유출되거나 탈취된 경우 사용자 세션의 보안이 위협을 받을 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;KEYCLOAK_IDENTITY 쿠키는 XSS(cross-site scripting) 및 세션 하이재킹 session hijacking 공격을 방지하기 위해 HttpOnly 쿠키로 설정됩니다. 해당 쿠키의 만료는 사용자 세션에 설정된 최대 시간 값을 기반으로 하며 이 값은 추측 공격을 방지하기에 충분한 엔트로피를 가집니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;realm의 remember me 설정을 활성화하고 사용자가 로그인을 할 때 해당 옵션을 사용하는 경우 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;KEYCLOAK_IDENTITY 쿠키의 만료 기간이 1년으로 설정됩니다. 이런 경우 사용자 세션에 설정된 최대 시간은 고려되지 않습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;쿠키에 더 많은 보안 설정을 추가할 수 있으며 가장 중요한 것은 HTTPS(HTTP over TLS)를 사용하는 보안 채널을 통해서만 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak에 접근할 수 있도록 하는 것입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;HTTPS를 사용하는 경우 secure 속성은 쿠키가 평문으로 전송되지 않도록 하기 위해 설정되며, SameSite=none 속성은 보안 연결을 사용하는 사이트 간 요청에서만 쿠키가 전송되도록합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;세션 만료와 관련해 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;KEYCLOAK_IDENTITY 쿠키는 위에서 살펴본 방법을 사용하는 경우 자동으로 만료되지 않습니다.따라서 브라우저는 여전히 해당 쿠키를 전송할 수 있지만 더이상 활성 세션을 참조하지 않습니다. 유효하지 않은 쿠키가 수신되면 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Keycloak은 쿠키를 폐기하고 사용자가 재인증을 수행하도록 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;6. 토큰 관리&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;토큰은 세션과 연동됩니다. 따라서 토큰 유효성(생명주기를 의미하지 않음) 세션에 따라 달라집니다. 토큰은 세션과 연동됩니다. 따라서 토큰 유효성 세션에 따라 달라집니다. 토큰은 각각 생명주기를 가지며 토큰이 유효한것으로 간주되는 기간은 토큰이 인증된 방식에 따라 달라집니다. JWT(Json Web Token)를 토큰 형식으로 사용하는 경우 Keycloak은 애플리케이션이 서버에 대한 추가적인 통신없이 로컬에서 토큰을 검증하고 검사할 수 있도록 지원합니다. 하지만 JWT토큰을 사용하는 경우 토큰이 유효한 생명주기를 갖고 있더라도 세션이 만료되면 토큰이 무효화됩니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이를 고려하지 않으면 토큰은 무효화됐지만 유효한 생명주기 기간 내에 있기 때문에 애플리케이션에서 여전히 허용되므로 토큰이 유출될 경우 공격 표면이 증가할 수 있습니다. 토큰 만료 및 폐기에 대한 명확한 전략을 항상 고려해야합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;애플리케이션이 Keycloak으로부터 토큰을 획득하는 경우 다음과 같은 토큰 데이터를 포함합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- ID 토큰&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- 접근 토큰&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- 리프레시토큰&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트의 권한 부여에 따라 Keycloak은 위의 토큰을 모두 발행하거나 일부 토큰만 발행할 수 있습니다. 각 토큰은 자체 생명주기를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리프레시 토큰을 제외하고, ID 토큰과 접근 토큰은 동일한 생명주기를 가집니다. 두 토큰 모두 수명이 짧고 토큰 스토리지가 가장 안전하지 않은 공용클라이언트(예를들어 단일 페이지 애플리케이션)에 서 일반적으로 사용됩니다. 접근 토큰의 경우, 일반적으로 사용됩니다. 접근 토큰의 경우, 일반적으로 케이블을 통해 전송되며 토큰 정보가 통신 중에 유출될 가능성이 있습니다. 접근 토큰의 생명주기와 유효성은 토큰 유출 또는 폐기시 영향을 줄이는 핵심 요소입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 리프레시 토큰은 수명이 더 길고, 유효성은 사용자 및 클라이언트 세션에 설정된 생명주기에 따라 달라집니다. 이러한 특성으로 인해 ID 토큰과 접근 토큰은 짧은 생명주기를 가지며 리프레시 토큰은 해당 토큰들이 만료되는 경우 갱신할 수 있습니다. 리프레시 토큰은 수명이 길기 떄문에 공격자에게 완벽한 타깃이 되며, 만료와 폐기를 위한 명확한 전략도 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. ID 토큰 및 접근 토큰 생명 주기 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 세션과 마찬가지로 토큰 생명주기를 설정할 수 있습니다. 해당 설정을 하려면 Realm Settings페이지에서 Tokens 탭을 클릭합니다. Tokens 탭에서 리프레시 토큰에 대한 특정 설정 정의를 포함해 ID토큰, 접근토큰,리프레시 토큰의 생명주기를 설정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2527&quot; data-origin-height=&quot;1418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DJjGF/btsMoRJsEoc/DgJG9I1rUn2puvwbelK7wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DJjGF/btsMoRJsEoc/DgJG9I1rUn2puvwbelK7wK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DJjGF/btsMoRJsEoc/DgJG9I1rUn2puvwbelK7wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDJjGF%2FbtsMoRJsEoc%2FDgJG9I1rUn2puvwbelK7wK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2527&quot; height=&quot;1418&quot; data-origin-width=&quot;2527&quot; data-origin-height=&quot;1418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ID 토큰 및 접근 토큰의 경우 Access Token Lifespan 설정을 통해 생명주기를 설정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M1Ps0/btsMoFCmXLY/2CoR6vw62Rg7WpMdkkLFL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M1Ps0/btsMoFCmXLY/2CoR6vw62Rg7WpMdkkLFL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M1Ps0/btsMoFCmXLY/2CoR6vw62Rg7WpMdkkLFL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM1Ps0%2FbtsMoFCmXLY%2F2CoR6vw62Rg7WpMdkkLFL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1347&quot; height=&quot;788&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 또한 Access Token Lifespan을 클라이언트 별로 설정할 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 설정을 하려면 클라이언트 상세 페이지로 이동한 다음 Advanced&amp;nbsp;&amp;nbsp;탭을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;802&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NYfIo/btsMqkjmEgG/hEBpkVQbZYiW212FlCoWJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NYfIo/btsMqkjmEgG/hEBpkVQbZYiW212FlCoWJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NYfIo/btsMqkjmEgG/hEBpkVQbZYiW212FlCoWJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNYfIo%2FbtsMqkjmEgG%2FhEBpkVQbZYiW212FlCoWJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1498&quot; height=&quot;802&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;802&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크롤을 내려 Advanced settings 섹션으로 이동합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2499&quot; data-origin-height=&quot;1331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZgfvP/btsMpAmJkWL/Er0UUaQaWloGBPV6IYu4uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZgfvP/btsMpAmJkWL/Er0UUaQaWloGBPV6IYu4uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZgfvP/btsMpAmJkWL/Er0UUaQaWloGBPV6IYu4uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZgfvP%2FbtsMpAmJkWL%2FEr0UUaQaWloGBPV6IYu4uK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2499&quot; height=&quot;1331&quot; data-origin-width=&quot;2499&quot; data-origin-height=&quot;1331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Advanced Settings에서 특정 클라이언트 ID 토큰 및 접근 토큰 생명주기를 재설정하기 위해 Access Token Lifespan을 설정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1331&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ENCkY/btsMoHG0xC2/PxjJHH0GBdKFWtyzr8emO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ENCkY/btsMoHG0xC2/PxjJHH0GBdKFWtyzr8emO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ENCkY/btsMoHG0xC2/PxjJHH0GBdKFWtyzr8emO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FENCkY%2FbtsMoHG0xC2%2FPxjJHH0GBdKFWtyzr8emO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1331&quot; height=&quot;582&quot; data-origin-width=&quot;1331&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰이 유출될 경우 피해를 줄이기 위해 토큰 생명주기 값은 최대한 짧게 해 클라이언트가 해당 토큰을 갱신하도록 해야합니다. 하지만 토큰 생명주기 값이 너무 짧으면 토큰 리프레시 요청이 더 자주 발생하므로 애플리케이션 및 Keycloak자체의 성능에 영향을 줄 수 있습니다. 토큰 생명주기의 기본값은 대부분의 사용 사례에 적합해야 하지만 필요에 따라 값을 조정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정은 RFC 6750 - Bearer Token Useage에 따라 애플리케이션에 접근하기 위해 베어러(Bearer) 토큰으로 자주 전송되기 떄문에 접근 토큰에 특히 중요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 Keycloak에서 발행한 토큰은 JWT 포맷이며 애플리케이션이 Keycloak의 토큰 검사 엔드포인트를 사용해 토큰을 검사하기 위한 추가적인 통신 없이 토큰 시그니처 및 생명주기와 관련된 일부 표준 클레임의 유효성을 검증합니다. 또한 보안 요구 사항에 따라 토큰이 수명 내에 있지만 리프레시 토큰은 더 이상 Keycloak의 활성 세션에서 사용되지 않는 상황을 허용하지 않을 수 있습니다. 이러한 상황에서 보안을 위해 토큰 검사 엔드포인트를 사용할 때 추가 오버헤드가 필요할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생명주기는 사용자 경험과 클라이언트의 복잡성에도 직접적인 영향을 미칩니다. 일반적으로 수명이 짧은 토큰은 수명이 긴 리프레시 토큰과 함께 사용돼 토큰이 만료될 때마다 사용자가 재인증하는 것을 방지합니다. 리프레시 토큰을 사용하는 클라이언트는 리프래시 토큰을 처리하는 추가 논리로 인해 구현이 더 복잡합니다. 반면 빈번한 토큰 갱신 필요성이 없는 수명이 긴 토큰은 토큰이 유출될 경우 추가적인 위험을 갖고 있지만 클라이언트의 복잡성을 제거합니다. 환경에 맞는 적절한 균형을 찾을 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 리프레시 토큰 생명 주기 관라&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리프레시 토큰 생명주기는 사용자 세션과 클라이언트 세션의 생명주기를 각각 설정하기 위해 SSO Session Max 및 Client Session Max 설정을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 리프레시 토큰의 생명주기는 클라이언트 세션에 설정된 시간을 기반으로 계산되며 realm 수준의 Client Session Max를 설정하거나 동일한 설정을 클라이언트 기반으로 재설정합니다. 클라이언트 세션에 대한 생명주기나 명시적으로 설정되지 않은 경우, Keycloak은 SSO Session Max 설정에서 사용자 세션으로 설정한 값이 사용됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 기반의 리프레시 토큰 생명주기를 재설정하려면 클라이언트의 상세 페이지로 이동한 다음 Advanced탭 &amp;gt; Advanced settings 섹션으로 이동합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;953&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTig5/btsMox5LeIR/zkFC2CtEaBbTK3qOuCPQEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTig5/btsMox5LeIR/zkFC2CtEaBbTK3qOuCPQEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTig5/btsMox5LeIR/zkFC2CtEaBbTK3qOuCPQEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTig5%2FbtsMox5LeIR%2FzkFC2CtEaBbTK3qOuCPQEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2430&quot; height=&quot;953&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;953&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Advanced Settings에서 Client Session Max 및 Client Session Idle 설정을 통해 리프레시 토큰 생명주기를 재설정할 수 있습니다. Keycloak은 기본적으로 클라이언트 수준에서 해당 설정에 대한 명시적 값을 정의하지 않으므로 realm 수준에서 설정된 값이 암시적으로 설정됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리프레시 토큰과 관련해 다음과 같은 내용을 고려해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리프레시 토큰은 인증 코드와 같은 특정 권한 부여를 사용해 Keycloak에서 사용자를 인증한 후 항상 클라이언트 세션과 연동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리프레시 토큰은 연동된 사용자 및 클라이언트 세션이 만료되지 않은 경우 유효한 것으로 간주된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라이언트는 클라이언트 세션이 활성 상태인 경우에만 리프레시 토큰을 사용해 신규 토큰을 획득할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 세가지 고려 사항을 고려하면 수명이 짧은 ID 토큰 및 접근 토큰을 사용하는데 있어서 리프레시 토큰의 역할이 얼마나 중요한지알게 될 것입니다.&amp;nbsp; 또한 클라이언트 기반의 토큰 생명주기를 통해 보다 엄격한 정책을 정의해 애플리케이션의 전반적인 보안에도 큰 영향을 미칠 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰 생명 주기 갱신은 얼마나 많은 클라이언트가 토큰을 안전하게 유지할 것인지에 따라 조정됩니다. 예를 들어 보안성이 높은 클라이언트는 수명이 더 긴 리프레시 토큰을 사용할 수 있지만 공용 클라이언트의 경우 수명이 짧은 리프레시 토큰을 사용해야 할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 리프레시 토큰이 만료되면 사용자는 클라이언트에 대한 재인증을 수행해야 하기 때문에 브라우절르 사용하는 경우 사용자 경험에 영향을 줄 수 있음을 고려해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발생할 수 있는 최악의 상황 중 하나는 리프레시 토큰이 유출되는 경우입니다. 이를 통해 공격자는 Keycloak에서 토큰을 획득하고 토큰이 발급된 클라이언트로 위장해 애플리케이션에 접근할 수 있습니다. 이러한 상황이 발생한 경우 영향을 피하거나 줄이기 위해 사용할 수 있는 여러 대응책이 있습니다. 그중 하나는 리프레시 토큰 로테이션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 리프레시 토큰 로테이션 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리프레시 토큰이 유출된 경우에 대한 보안 대응책으로 Keycloak에서 리프레시 토큰 로테이션을 활성화할 수 있습니다. 리프레시 토큰 로테이션은 합법적인 클라이언트가 리프레시 토큰 요청을 하는 경우에 영향을 줄이기 위한 전략입니다. 해당 기능을 활성화하면 로테이션은 리프레시 토큰이 언제 유출됐는지 신속하게 신별하고 신규 및 유효한 리프래시 토큰이 포함된 토큰 갱신 집합을 획득하기 위해 공격자와 합법적인 클라이언트 모두를 재인증합니다. 합법적인 클라이언트만 토큰 엔드포인트에 대해 인증할 수 있다는 점을 고려할때 클라이언트만 신규 리프래시 토큰을 성공적으로 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리프래시 토큰 로테이션을 활성화하려면 Realm Settings 메뉴에서 Tokens 탭으로 이동한 다음 Revoke Refresh Token 설정을 활성화합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2526&quot; data-origin-height=&quot;1339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XtT8S/btsMoRiEVfW/6SF8l4h6okC8ipBF2fIlCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XtT8S/btsMoRiEVfW/6SF8l4h6okC8ipBF2fIlCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XtT8S/btsMoRiEVfW/6SF8l4h6okC8ipBF2fIlCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXtT8S%2FbtsMoRiEVfW%2F6SF8l4h6okC8ipBF2fIlCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2526&quot; height=&quot;1339&quot; data-origin-width=&quot;2526&quot; data-origin-height=&quot;1339&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 설정을 활성화하면 신규 리프래시 토큰을 재발급하지 않고, 클라이언트가 리프레시 토큰을 재사용할 수 있는 횟수를 정의한 Refresh Token Max Reuse 설정이 추가로 제공되며 해당 횟수가 초과되면 기존 리프레시 토큰은 폐기됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Refresh Token Max Reuse 설정은 기본적으로 0으로 설정되며, 리프레시 토큰의 재사용은 한번만 가능합니다. 클라이언트가 동일한 리프래시 토큰을 재사용하려고 시도하면 Keycloak은 해당 요청을 차단하고 클라이언트가 사용자를 재인증하도록 합니다. 예를들어 값을 1로 증가시키면 클라이언트가 동일한 리프래시 토큰을 두번사용 할 수있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 리프레시 토큰 로테이션은 일반적으로 해당 토큰이 유출된 경우 공격 표면을 줄이는 좋은 방법입니다. 또한 유출을 신속하게 식별할 수 있으며 발생 가능한 공격에 대응할 수 있습니다. 하지만 공용 클라이언트의 경우 리프래시 토큰 로테이션이 고려할 수 있는 유일한 보안 조치는 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공용클라이언트는 토큰 앤드포인트에 인증하기 위해 자격증명을 제공할 필요가 없으므로 본질적으로 안전하지 않습니다. 따라서 클라이언트 인증서가 토큰을 발급받는 클라이언트에 바인딩하는데 사용되는 발신자 제한 토큰 사용을 수행하기 위해 상호 TLS 클라이언트 인증 사용을 고려해야하며, 이를 통해 리프래시 토큰을 토큰 엔드포인트에 제공할 때 공격자가 유출된 리프레시 토큰을 사용할 수 없게 할수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. 토큰 폐기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 여러가지 방법을 통해 토큰을 폐기할 수 있습니다. 토큰은 세션과 연동되며 만료된 세션의 토큰은 Keycloak에서 더이상 유효하지 않은 것으로 간주됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자와 클라이언트에 관계없이 토큰을 전체적으로 비활성화하는 가장 쉬운 방법 가운데 하나는 not-before-revocation 정책을 사용해 토큰이 시간에 따라 만료되도록 하는것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Realm Settings로 이동한 후 Tokens 탭을 선택해 realm의 활성 세션을 관리할 수 있습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2488&quot; data-origin-height=&quot;1281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1xbFd/btsMqPpUO9x/N5sGPDEQllcPnKFEZWN89k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1xbFd/btsMqPpUO9x/N5sGPDEQllcPnKFEZWN89k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1xbFd/btsMqPpUO9x/N5sGPDEQllcPnKFEZWN89k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1xbFd%2FbtsMqPpUO9x%2FN5sGPDEQllcPnKFEZWN89k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2488&quot; height=&quot;1281&quot; data-origin-width=&quot;2488&quot; data-origin-height=&quot;1281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 사용하면 기본 세션을 만료하거나 RFC 7009에 정의된 폐기 엔드포인드를 사용해 토큰을 폐기할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션만료를 통해 토큰을 폐기하면 관리자는 세션과 연동된 모든 토큰을 자동으로 폐기할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 Keycloak은 RFC7009 기반의 토큰 폐기(token revocation) 엔드포인트와 같은 특정 엔드포인트를 통해 클라이언트가 토큰을 폐기할 수 있도록해 줍니다.해당 접근 방식을 사용해 클라이언트는 Keycloak이 사용하지 않는 토큰을 추적하도록 돕고, 토큰이 유출되기 쉬운 시간을 줄이며 메모리와 CPU 리소스를 절약하기 위해 관련된 데이터를 정리할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 언급된 모든 방법은 토큰 유출에 대응하거나 토큰이 더이상 사용되지 않는 즉시 토큰을 폐기하는데 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Not-before-revocation 정책을 제외하고 다른 모든 방법은 토큰 폐기 엔드포인트를 사용할 때 realm의 모든 활성 세션을 만료하거나 클라이언트 세션만 만료해 사용자 및 클라이언트 세션을 만료함을 의미합니다. Not-Before 정책은 토큰의 유효성을 검사하는 방법에만 영향을 주며 관련 세션은 여전히 활성 상태로 유지됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번글에서는 토큰 및 세션관리에 대한 몇가지 주요 측면을 살펴봤습니다. 다음글에서는 Keycloak 확장성에 대해 작성하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak 세션</category>
      <category>keycloak 세션관리</category>
      <category>keycloak 토큰</category>
      <category>keycloak 토큰관리</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/103</guid>
      <comments>https://marshmello.tistory.com/103#entry103comment</comments>
      <pubDate>Wed, 19 Feb 2025 11:15:00 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 7</title>
      <link>https://marshmello.tistory.com/102</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 인증 흐름 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak에서 인증은 인증 흐름에 따라 ID 인증 방법을 정의하기 위해 그룹화된 일련의 순차적 단계 또는 실행으로 구성됩니다. 흐름에 따라 인증 요구 사항 및 realm에 인증을 수행하는 주체의&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID 검증 단계도 달라집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak은 최종 사용자 및 클라이언트가 realm에 인증하는 방법을 보여주는 정교한 흐름 집합을 갖고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종 사용자의 경우, 인증 흐름은 일반적으로 브라우저를 중개자로 사용합니다. 클라이언트 단계는 엔드포인트에 대한 백채널 요청을 기반으로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak은 흐름을 정의하는 것과 관련해서 매우 유연함을 갖고 있습니다. 기본적으로 realm은 최종 사용자 및 클라이언트를 인증하기 위한 가장 일반적인 요구사항을 처리하는 빌트인 정의로 생성되며,사용자 고유의 인증 요구 사항을 수행하기 위해 언제든지 변경하거나 확장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀더 정확하게 이해하기 위해 myrealm의 인증흐름 정의를 살펴보겠습니다. 해당 작업을 수행하려면 관리자 콘솔에 접근하여 좌측 사이드 메뉴의 Authentication를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2514&quot; data-origin-height=&quot;1303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yCG6e/btsMlogKTS2/lGtzhyAvBYu5ktKuZRlo6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yCG6e/btsMlogKTS2/lGtzhyAvBYu5ktKuZRlo6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yCG6e/btsMlogKTS2/lGtzhyAvBYu5ktKuZRlo6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyCG6e%2FbtsMlogKTS2%2FlGtzhyAvBYu5ktKuZRlo6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2514&quot; height=&quot;1303&quot; data-origin-width=&quot;2514&quot; data-origin-height=&quot;1303&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 페이지에서 사전 정의된 인증 흐름을 선택 및 확인 할 수 있으며 realm의 모든 흐름 정의 리스트를 확인 할 수 있습니다. 현재 페이지에 있는 내용들을 모두 알고 있을 필요는 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2232&quot; data-origin-height=&quot;1339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pX63m/btsMlhovikl/FE4ERAibnNDWfK2hqnzuF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pX63m/btsMlhovikl/FE4ERAibnNDWfK2hqnzuF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pX63m/btsMlhovikl/FE4ERAibnNDWfK2hqnzuF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpX63m%2FbtsMlhovikl%2FFE4ERAibnNDWfK2hqnzuF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2232&quot; height=&quot;1339&quot; data-origin-width=&quot;2232&quot; data-origin-height=&quot;1339&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flow name을 클릭하면 해당 인증과 관련된 인증 흐름에 대한 관계를 보여줍니다 그중 브라우저 흐름은 최종 사용자가 브라우저를 사용해 인증을 수행하는 것과 관련돼 있습니다. 다이렉트 권한 부여 흐름 및 클라이언트 인증에도 동일한 동작 방식을 가집니다. 하지만 해당 흐름들은 클라이언트가 realm에 인증하거나 클라이언트가 토큰 엔드포인트를 사용해 토큰을 획득하기 위해 백채널 요청을 통해 사용자를 인증하는 것과 관련돼 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 인증 흐름 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 흐름과 관련된 인증 흐름 정의 설정을 변경하거나 기존의 인증 흐름 정의 설정을 템플릿으로 생성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흐름을 생성하는 가장 쉽고 권장되는 방법은 Flows 탭에서 정의를 선택해 기존 정의를 템플릿으로 사용하고 Duplicatie 버튼을 클릭하는 것입니다. 기존 정의를 템플릿으로 사용하는 이유는 변경사항을 쉽게 롤백할 수 있고, 변경사항으로 인해 흐름에 장애가 발생하더라도 기존 템플릿으로 돌아 갈 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Browser Flow를 사용자 정의하는 방법에 대해 알아보고 브라우저를 사용해 realm에서 인증을 수행하는 최종 사용자에게 미치는 영향을 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 작업을 수행하려면 , Flows 탭의 선택박스에서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Duplicatie&lt;span&gt; 버튼을 클릭합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2067&quot; data-origin-height=&quot;931&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cys68l/btsMlmiVHLH/FIALVSXRaUYQVIzhhDk1UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cys68l/btsMlmiVHLH/FIALVSXRaUYQVIzhhDk1UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cys68l/btsMlmiVHLH/FIALVSXRaUYQVIzhhDk1UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcys68l%2FbtsMlmiVHLH%2FFIALVSXRaUYQVIzhhDk1UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2067&quot; height=&quot;931&quot; data-origin-width=&quot;2067&quot; data-origin-height=&quot;931&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 생성된 흐름의 이름을 입력하라는 메시지가 표시됩니다. 이름을 My Browser로 입력하고 Duplicatie&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;버튼을 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2079&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkGwiB/btsMmkYS5dv/tlUkvTVzkgbST3LsH2Ylp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkGwiB/btsMmkYS5dv/tlUkvTVzkgbST3LsH2Ylp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkGwiB/btsMmkYS5dv/tlUkvTVzkgbST3LsH2Ylp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkGwiB%2FbtsMmkYS5dv%2FtlUkvTVzkgbST3LsH2Ylp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2079&quot; height=&quot;856&quot; data-origin-width=&quot;2079&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증흐름은 다양한 인증 실행 및 다른 인증 흐름을 포함하는 계층 트리입니다. 인증 실행은 사용자를 인증할 때 몇가지 작업을 수행하는 실제 단계입니다.해당 작업들은 최종 사용자가 브라우저를 사용하는 경우 사용자 이름을 요청하는 것과 같이 사용자로부터 몇몇 정보를 획득하거나 서로 다른 유형의 자격증명을 통해 클라이언트를 인증하는 경우 특정 인증 메커니즘을 통해 사용자를 인증합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;1230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1FYe9/btsMnm2KZlx/9ssINIeHMpDCkTAe29qM1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1FYe9/btsMnm2KZlx/9ssINIeHMpDCkTAe29qM1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1FYe9/btsMnm2KZlx/9ssINIeHMpDCkTAe29qM1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1FYe9%2FbtsMnm2KZlx%2F9ssINIeHMpDCkTAe29qM1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1915&quot; height=&quot;1230&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;1230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;769&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/txA7K/btsMnDJVOFe/pGGKzZbQCIqnKJ9b11Ks30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/txA7K/btsMnDJVOFe/pGGKzZbQCIqnKJ9b11Ks30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/txA7K/btsMnDJVOFe/pGGKzZbQCIqnKJ9b11Ks30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtxA7K%2FbtsMnDJVOFe%2FpGGKzZbQCIqnKJ9b11Ks30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1912&quot; height=&quot;769&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;769&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 흐름의 요소는 위에서 아래로 순차적으로 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;흐름의 단계를 실행할지 여부에 대한 결정은 현재 단계 및 해당 설정의 결과에 따라 달라집니다. 단계가 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Required&lt;span&gt; &lt;/span&gt;&lt;/span&gt;로 설정된 경우 다음 단계로 이동하기 전에 해당 단계를 성공적으로 수행해야합니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Required&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 단계가 성공적으로 완료되면 흐름에 다른 Required 단계가 없는 경우 흐름이 중지됩니다. Alternative 단계의 경우 단계가 정상적으로 완료 되지 않더라도 흐름은 진행됩니다. 따라서 다른 단계는 정상적으로 작업을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 흐름 및 하위 흐름의 경우 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Required&lt;span&gt; 및&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Alternative&lt;span&gt; 설정은 필수적인 전체 실행 또는 흐름 내의 실행이 성공적으로 완료되는 것과 관련돼 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My Browser 흐름 정의를 예시로 보면 인증은 다음과 같이 정의됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 먼저 쿠키 실행은 유효한 사용자 세션에 매핑되는 요청에 쿠키가 있는 경우 사용자를 원활하게 재인증합니다. 즉, 사용자가 이미 realm에 인증된 경우 인증을 수행하지 않습니다. 해당 단계는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Alternative&lt;span&gt; 이며 사용자를 인증할 수 없는 경우 흐름은 계속 진행됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;2) Kerberos 실행이 활성화 된 경우, &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Kerberos&lt;span&gt; 자격 증명을 통해 사용자를 인증합니다. 기본적으로 비활성화돼 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;3) Identity Provider Redirect은 realm이 사용자를 사전 정의된 ID 제공자로 자동 리다이렉트하는 설정이 있는지 확인합니다. Alternative&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 단계이며 단계가 완료되지 않아도 흐름은 계속 수행됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;4) My Browser Forms는 특정 단계를 그룹화하는 하위 흐름이며 패스워드 기반 및 OTP(one-time Password)dhk rkxdms 2FA를 통해 사용자를 인증합니다. 해당 단계는 Alternative&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 이며 따라서 위 단계 중 하나라도 정상적으로 완료되면 해당 단계는 실행되지 않습니다. 그렇지 않은 경우 사용자가 이미 인증됐더라도 자격증명을 다시 제공해야합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;5) 하위 흐름의 첫 단계는 Username Password Form을 사용하는 단일 단계에서 사용자 이름과 패스워드를 통해 사용자를 인증하는 것입니다. 이것은 realm에 인증을 수행할 때 확인했던 로그인 페이지입니다. 이 단계는 Required&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 단계이기 때문에 반드시 정상 수행돼야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;6) 5단계가 정상적으로 수행되면 사용자의 초기인증 OTP를 사용하는 2FA가 활성화돼 있는지 확인하기 위해 My Browser Browser - Conditional OTP라는 하위 흐름이 수행됩니다. 해당 하위 흐름에서 Condition - User Configured는 사용자가&amp;nbsp; OTP 자격증명 설정을 사용하고 있는지 확인하고, 해당 설정이 활성화된 경우 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OTP를 토해 사용자를 인증하기 위해 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OTP&lt;span&gt; Form 단계를 수행합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;이제 단일 로그인 페이지에서 자격증명을 요청하는 대신 사용자 이름과 패스워드를 서로 다른 단계 및 페이지에서 수집해 사용자를 realm에서 인증하는 방법을 변경해보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;해당 작업을 수행하려면 Username Password Form 실행의 우측에 있는 삭제 아이콘을 클릭합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNsW0u/btsMnLOB7t0/w7zfOoqpQyw2nHWjzj5yM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNsW0u/btsMnLOB7t0/w7zfOoqpQyw2nHWjzj5yM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNsW0u/btsMnLOB7t0/w7zfOoqpQyw2nHWjzj5yM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNsW0u%2FbtsMnLOB7t0%2Fw7zfOoqpQyw2nHWjzj5yM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1243&quot; height=&quot;75&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My Browser Forms 우측에 있는 추가 아이콘을 클릭 Add step 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0Qn10/btsMlG2GJJq/mxaYX5i8DvH67TFJFOgJLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0Qn10/btsMlG2GJJq/mxaYX5i8DvH67TFJFOgJLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0Qn10/btsMlG2GJJq/mxaYX5i8DvH67TFJFOgJLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0Qn10%2FbtsMlG2GJJq%2FmxaYX5i8DvH67TFJFOgJLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1135&quot; height=&quot;207&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Username Form을 선택하고 Add 버튼 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1501&quot; data-origin-height=&quot;1354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OwlxX/btsMnpFfE4O/ZdH6DvRakOjfX06bkdlXqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OwlxX/btsMnpFfE4O/ZdH6DvRakOjfX06bkdlXqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OwlxX/btsMnpFfE4O/ZdH6DvRakOjfX06bkdlXqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOwlxX%2FbtsMnpFfE4O%2FZdH6DvRakOjfX06bkdlXqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1501&quot; height=&quot;1354&quot; data-origin-width=&quot;1501&quot; data-origin-height=&quot;1354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가한 Username Form이 하위 흐름의 첫번째 실행이 될 수 있도록 아래 박스쳐진 아이콘에 마우스를 클릭하여 드래그합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/me14g/btsMnnncfNY/ipK3VBPAppKEx2bx9jcQCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/me14g/btsMnnncfNY/ipK3VBPAppKEx2bx9jcQCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/me14g/btsMnnncfNY/ipK3VBPAppKEx2bx9jcQCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fme14g%2FbtsMnnncfNY%2FipK3VBPAppKEx2bx9jcQCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1744&quot; height=&quot;688&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1795&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGJAMz/btsMm5mIGYz/PUYbzpe2rPAqhXVhubK2zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGJAMz/btsMm5mIGYz/PUYbzpe2rPAqhXVhubK2zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGJAMz/btsMm5mIGYz/PUYbzpe2rPAqhXVhubK2zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGJAMz%2FbtsMm5mIGYz%2FPUYbzpe2rPAqhXVhubK2zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1795&quot; height=&quot;708&quot; data-origin-width=&quot;1795&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Username Form에서 했던 동일한 작업을 Password Form 인증 실행에도 동일하게 적용합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0C82/btsMmm3GQaD/ZjZoz3Y4k3thoH7ZdzpPvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0C82/btsMmm3GQaD/ZjZoz3Y4k3thoH7ZdzpPvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0C82/btsMmm3GQaD/ZjZoz3Y4k3thoH7ZdzpPvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0C82%2FbtsMmm3GQaD%2FZjZoz3Y4k3thoH7ZdzpPvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1432&quot; height=&quot;964&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Password Form 인증 실행은 하위 흐름에서 패스워드를 획득하고 사용자를 인증합니다. Password Form을 하위흐름에서 두번째로 실행되게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Username Form 및 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Password Form&lt;span&gt; 실행을 Required&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 로 설정합니다. 해당 작업을 수행하려면 각 인증 실행의 Required&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 설정을 클릭합니다. Required&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp; 설정을 통해 최종 사용자가 realm에 로그인하는 경우 사용자 이름과 패스워드를 인증할 수 있기 때문에 해당 설정은 중요한 단계입니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1911&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctvsi5/btsMnlCUWHJ/sgp2dkZ5sQqJeQf5KdHyx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctvsi5/btsMnlCUWHJ/sgp2dkZ5sQqJeQf5KdHyx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctvsi5/btsMnlCUWHJ/sgp2dkZ5sQqJeQf5KdHyx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fctvsi5%2FbtsMnlCUWHJ%2Fsgp2dkZ5sQqJeQf5KdHyx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1911&quot; height=&quot;880&quot; data-origin-width=&quot;1911&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 My Browser 인증 흐름 정의와 연동하기 위해 Action &amp;gt;&amp;nbsp; Bind flow 버튼을 눌러 Browser Flow를 변경합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXooNh/btsMmJqKrdF/EeR5VZiCfdloooVBItWyc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXooNh/btsMmJqKrdF/EeR5VZiCfdloooVBItWyc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXooNh/btsMmJqKrdF/EeR5VZiCfdloooVBItWyc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXooNh%2FbtsMmJqKrdF%2FEeR5VZiCfdloooVBItWyc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1377&quot; height=&quot;538&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2052&quot; data-origin-height=&quot;1048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFByI9/btsMnnOk5Tp/WLqj33LIdAuw1jjm1pHfEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFByI9/btsMnnOk5Tp/WLqj33LIdAuw1jjm1pHfEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFByI9/btsMnnOk5Tp/WLqj33LIdAuw1jjm1pHfEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFByI9%2FbtsMnnOk5Tp%2FWLqj33LIdAuw1jjm1pHfEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2052&quot; height=&quot;1048&quot; data-origin-width=&quot;2052&quot; data-origin-height=&quot;1048&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://localhost:9090/realms/myrealm/account 브라우저에 접속하여 사용자 자격증명을 통해 로그인을 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;871&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtHl5p/btsMlXpH9mv/02NXIVpkrOmk9JJQTi6JZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtHl5p/btsMlXpH9mv/02NXIVpkrOmk9JJQTi6JZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtHl5p/btsMlXpH9mv/02NXIVpkrOmk9JJQTi6JZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtHl5p%2FbtsMlXpH9mv%2F02NXIVpkrOmk9JJQTi6JZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1744&quot; height=&quot;871&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;871&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 이름과 패스워드가 여러 단계에 걸쳐 활용되고 검증된다는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwsDG9/btsMm1xYBJ7/LcORfjUlOJCoqdlGgXFuEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwsDG9/btsMm1xYBJ7/LcORfjUlOJCoqdlGgXFuEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwsDG9/btsMm1xYBJ7/LcORfjUlOJCoqdlGgXFuEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwsDG9%2FbtsMm1xYBJ7%2FLcORfjUlOJCoqdlGgXFuEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1116&quot; height=&quot;976&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 패스워드 사용&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 기본적으로 사용자를 인증하기 위해 패스워드를 사용했습니다. 또한 사용자 관리 작업을 수행하는 경우 패스워드를 설정하는 방법을 간단하게 소개했습니다. 패스워드 기반 인증의 동작 방식과 패스워드 관리 방법을 자세히 알아 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드 기반 인증은 사용자를 인증하는 가장 널리 사용되는 방법 중 하나 일 것입니다. 패스워드 기반 인증은 구현하기 쉽고 대부분의 최종 사용자가 시스템에 인증하는 경우에 사용하는 방법입니다. 하지만 패스워드 기반 인증의 단순함은 몇몇 단점과 약점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드 기반 인증의 몇몇 단점을 극복하기 위해 Keycloak은 일반적으로 베스트 프랙티스를 활용해 전송 중이나 보관중인 패스워드가 안전한지 확인합니다. 또한 Keycloak에서 만료, 패스워드 포맷 및 이전 암호 재사용과 같은 패스워드 관리의 몇가지 주요 부분을 제어할 수 있도록 정책을 정의할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드는 사용자의 자격증명 유형 중 가장 단순한 형태의 자격증명이며 Keycloak에서 기본적으로 사용자를 인증할 때 사용하는 방법입니다 패스워드는 사용자별로 관리됩니다. User details 페이지의 Credentials 탭에서 사용자의 패스워드를 리셋하거나 삭제할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;883&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/luAid/btsMm1Y7cNb/UXcW1TNW8Qo4wrtoLOB7Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/luAid/btsMm1Y7cNb/UXcW1TNW8Qo4wrtoLOB7Rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/luAid/btsMm1Y7cNb/UXcW1TNW8Qo4wrtoLOB7Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FluAid%2FbtsMm1Y7cNb%2FUXcW1TNW8Qo4wrtoLOB7Rk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2479&quot; height=&quot;883&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;883&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 강력한 패스워드 해싱 알고리즘을 사용해 브루트-포스(brute-force) 공격을 방지하며, 패스워드를 안전하게 저장합니다. Keycloak에서 사용하는 기본 해싱 알고리즘은 PBKDF2이며, 해당 알고리즘 잘 알려지고 널리 사용되는 알고리즘으로 패스워드를 안전하게 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 패스워드를 설정하는 경우, 해당 패스워드는 salt라고 알려진 보안 랜덤 숫자와 결합하고 해킹하기 어려운 파생키를 생성하기 위해 여러번의 해시를 수행합니다. 패스워드를 저장하는 경우 절대 평문으로 저장되지 않습니다. 그 대신 파생된 키가 추후 패스워드를 확인하기 위해 필요한 메타데이터와 함께 저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 HMAC-SHA-256을 사용해 패스워드에 대한 해시수행을하고 27,500번의 반복 횟수가 설정돼 있습니다. HMAC-SHA-256와 같은 더 강력한 해싱 알고리즘을 사용하거나 패스워드 정책을 설정할 때 반복 횟수를 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드 기반 인증은 여러 약점을 갖고 있기 때문에 사용자를 인증하는데 가장 강력한 방법은 아닙니다. 몇가지 예를 들면 패스워드는 일반적으로 도난을 당하거나 유출되며 피싱 공격에 취약합니다. 그리고 일부 사용자는 강력한 패스워드를 사용하지 않으며 시스템은 사용자가 패스워드를 정의, 유지 및 사용하는 수준만큼의 보안 수준을 가집니다. 사용자는 보통 여러 시스템에서 동일한 패스워드를 사용하기 때문에 가장 취약한 시스템만큼의 보안 수준을 갖게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용성 측면에서 정책을 사용해 사용자에게 강력한 패스워드를 사용하도록 강제할 경우 패스워드가 길어지고 복잡해져서 사용자가 시스템에 인증할 경우, 패스워드를 기억하지 못하거나 입력하기 어려워집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 패스워드 기반인증의 전반적인 보안을 개선할 수 있지만 모든문제를 해결하지 못합니다. 패스워드는 단독으로 사용될 경우 사용자를 인증하기 위한 단일요소이므로 시스템의 전반적인 보안을 향상시키기 위해 추가 요소를 사용하는 것을 고려해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드 기반 인증은 Keycloak에서 사용자를 인증하는데 필요한 유일한 옵션은 아니며, 다른 형식의 인증을 결합하거나 패스워드를 완전히 제거해 시스템에 강력한 인증을 적용할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 패스워드 정책 변경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 패스워드와 관련된 유형이 정책을 정의할 수 있습니다. 해당 정책은 좌측 사이드메뉴에 있는 Authentication을 클릭한 다음 Password Policy 탭을 클릭하여 생성할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2125&quot; data-origin-height=&quot;1066&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JAYqi/btsMnqxxO1p/DIygDd4jGckd6E80DcE6TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JAYqi/btsMnqxxO1p/DIygDd4jGckd6E80DcE6TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JAYqi/btsMnqxxO1p/DIygDd4jGckd6E80DcE6TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJAYqi%2FbtsMnqxxO1p%2FDIygDd4jGckd6E80DcE6TK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2125&quot; height=&quot;1066&quot; data-origin-width=&quot;2125&quot; data-origin-height=&quot;1066&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 탭에서 다양한 정책을 선택하고 다음과 같이 특정 패스워드 관리 설정을 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패스워드에 특수문자, 숫자, 소문자 또는 대문자의 개수를 적용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패스워드의 최소 길이를 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패스워드의 만료 시간을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패스워드에 사용자 이름이 포함되는 것을 방지합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 블랙리스트 사전을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이미 사용중인 패스워드를 재사용하지 않도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Add policy 선택박스를 클릭하여 위와 같은 패스워드 정책을 설정할 수 있습니다. 패스워드 정책을 활용해 더 강력한 패스워드 및 패스워드 갱신 주기를 설정해 패스워드 기반 인증의 몇몇 약점을 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 사용자 패스워드 리셋&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 여러가지 방법으로 사용자 패스워드를 리셋할수 있습니다. 관리자는 관리자 콘솔을 사용해 사용자의 패스워드를 선택하거나 사용자가 로그인할 때 패스워드를 업데이트하도록 설정할 수 있습니다. 또한 사용자는 로그인 페이지에서 패스워드를 리셋하거나 Keycloak 계정 콘솔을 통해 계정을 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 콘솔을 통해 사용자의 패스워드를 변경하는 경우, Keycloak은 기본적으로 신규 패스워드를 임시로 발급합니다. 임시 패스워드는 사용자가 추후 realm에 로그인하는 경우 신규 패스워드를 입력해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User datils 페이지의 Credentials 탭에서 임시 스위치를 활성화해 관리자가 설정한 패스워드의 임시 패스워드 여부를 제어할 수 있습니다. 임시 스위치를 비활성화하면 사용자가 로그인할때 패스워드 변경요청을 받지 않습니다. 임시패스워드는 사용자가 패스워드 업데이트 수행하도록 하기 위한 간단한 설정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Update Password의 required action은 관리자가 언제든지 특정 사용자가 패스워드를 업데이트하도록 설정할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1597&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vHxXx/btsMnO5Kow0/f3flO1NrD69HT297JZZcSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vHxXx/btsMnO5Kow0/f3flO1NrD69HT297JZZcSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vHxXx/btsMnO5Kow0/f3flO1NrD69HT297JZZcSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvHxXx%2FbtsMnO5Kow0%2Ff3flO1NrD69HT297JZZcSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1597&quot; height=&quot;709&quot; data-origin-width=&quot;1597&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 입장에서 Keycloak 계정 콘솔을 사용하거나 로그인 페이지에서 특정 흐름을 시작함으로써 패스워드를 업데이트할 수 있습니다. 사용자는 계정 콘솔에서 Signing in 페이지의 Update 버튼을 클릭하여 패스워드를 변경할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2527&quot; data-origin-height=&quot;1087&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuAX3P/btsMm6lL1Pz/1YPkikSbqZXyg7tN1ulVUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuAX3P/btsMm6lL1Pz/1YPkikSbqZXyg7tN1ulVUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuAX3P/btsMm6lL1Pz/1YPkikSbqZXyg7tN1ulVUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuAX3P%2FbtsMm6lL1Pz%2F1YPkikSbqZXyg7tN1ulVUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2527&quot; height=&quot;1087&quot; data-origin-width=&quot;2527&quot; data-origin-height=&quot;1087&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 패스워드를 잊어버리거나 분실했을 경우 패스워드를 리셋하기 위해 로그인 페이지에서 특정 흐름을 사용할 수 있습니다. 해당 흐름은 기본적으로 비활성화되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;활성화하려면 관리자 페이지에서 Realm settings &amp;gt; Login 탭 &amp;gt; Forgot password 를 활성화합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1309&quot; data-origin-height=&quot;1279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6nQRH/btsMmnhlcyT/cSvJbKogCCyu6Ml2P3d6T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6nQRH/btsMmnhlcyT/cSvJbKogCCyu6Ml2P3d6T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6nQRH/btsMmnhlcyT/cSvJbKogCCyu6Ml2P3d6T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6nQRH%2FbtsMmnhlcyT%2FcSvJbKogCCyu6Ml2P3d6T1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1309&quot; height=&quot;1279&quot; data-origin-width=&quot;1309&quot; data-origin-height=&quot;1279&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 패스워드를 리셋하기 위해 클릭할 수 있는 링크가 로그인 페이지에 표시됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;1051&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhImdp/btsMnBeDEhz/8TAVzHojpsrElFhHlxm1j1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhImdp/btsMnBeDEhz/8TAVzHojpsrElFhHlxm1j1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhImdp/btsMnBeDEhz/8TAVzHojpsrElFhHlxm1j1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhImdp%2FbtsMnBeDEhz%2F8TAVzHojpsrElFhHlxm1j1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1305&quot; height=&quot;1051&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;1051&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Forgot password? 링크를 클릭하면 사용자 패스워드를 리셋하기 위한 링크를 이메일로 수신할 수 있도록 사용자 이름 또는 이메일을 제공하라는 메시지가 표시됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;889&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHo946/btsMmd0enfn/ansnkk3BJkuWWiyXJbEpM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHo946/btsMmd0enfn/ansnkk3BJkuWWiyXJbEpM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHo946/btsMmd0enfn/ansnkk3BJkuWWiyXJbEpM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHo946%2FbtsMmd0enfn%2Fansnkk3BJkuWWiyXJbEpM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1300&quot; height=&quot;889&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;889&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. OTPs 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 추가 보안계층으로 사용자를 인증하는 경우 이중 인증 요소 또는 증거를 사용할 수 있습니다. 사용자는 패스워드를 제공하는 것 욍에도 자신의 ID에 대한 추가 증거를 제공해야할 의무가 있으며 해당 증거는 코드 또는 보안키가 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OTP는 사용자 계정에서 2FA를 활성화하는 가장 일반적인 방법 중 하나 입니다.상대적으로 사용하기 쉽고 사용자를 읹ㅇ하는 경우 추가적인 보안을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OTP는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2FA를 구현하기 위한 유용한 방법이지만 몇가지 단점이 있습니다. OTP는 서버와 사용자간의 공유키를 사용하며 최종 사용자에게 높은 사용자 편의성을 제공하지 않으며 피싱 또는 스캠과 같은 공격에 취약합니다. 이 문제를&amp;nbsp; Keycloak 은 WebAuthn 보안 기기를 이중 요소로 사용해 OTP 약점을 보완할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 OTP를 사용해 사용자 구성과 인증을 손쉽게 수행하며 realm이 자동으로 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OTP&lt;span&gt; 기반의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2FA를 지원하도록 설정됩니다. 사용자는 또한 OTP코드를 생성하기 위한 기기를 등록해 사용자 계정의 2FA를 쉽게 설정 할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;7. OTP 정책 변경&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Keycloak에서 서로 다른 OTP정책을 정의할 수 있습니다. 해당 정책들은 좌측 메뉴에 있는 Authentication 링크를 클릭한 다음 OTP Policy 탭을 클릭해 변경할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xYtdz/btsMmnBBIFq/dGQkny3zhhIgTc1qdZq2C0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xYtdz/btsMmnBBIFq/dGQkny3zhhIgTc1qdZq2C0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xYtdz/btsMmnBBIFq/dGQkny3zhhIgTc1qdZq2C0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxYtdz%2FbtsMmnBBIFq%2FdGQkny3zhhIgTc1qdZq2C0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1648&quot; height=&quot;1228&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OTP는 특정 알고리즘을 사용해 해시된 비밀키와 사용자를 인증하기 위해 일회성으로 사용할 수 있는 현재 시간 또는 카운터와 같은 이동 계수(moving factor)를 기반으로 사용하는 코드입니다. Keycloak은 두가지 알고리즘을 사용해 사용자가 코드를 인증하도록 생성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Time-Based One-Time Password(TOTP)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- HMAC-Based One-Time Password(HOTP)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;기본적으로 Keycloak에서 작성된 realm은 TOTP를 사용하도록 설정됩니다. 또한 6자리로만 구성되며 30초간의 유효시간을 가집니다 필요한 경우 언제든지 해당 설정을 변경할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TOTP와&amp;nbsp; HOTP 알고리즘의 차이점은 코드를 생성하는데 사용되는 이동 계수와 검증 방법입니다. 이름에서 알수있듯이 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;TOTP&lt;/span&gt;는 시간을 기반으로 하므로 코드는 특정 시간 동안의 유효 시간을 가집니다. 반면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;HOTP는 카운터를 기반으로 동작합니다. 코드의 유효성은 코드가 검증되고 카운터가 증가하지 전까지 무한합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;어떤 알고리즘을 사용해야 하는지는 사용자 환경에 따라 달라집니다. 하지만 TOTP가 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;HOTP&lt;span&gt; 보다 더 높은 보안성을 제공합니다. 코드를 분실하거나 유출된 경우 TOTP의 유효 기간이 줄어들기 때문에 OTPs를 사용하는 경우 공격 표면을 감소시킬 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;사용자의 입장에서 Keycloak은 사용자가 안드로이드와 iOS앱스토어에서 다운받을 수 있는 2가지 주요 모바일 애플리케이션을 사용해 스마트폰이나 태블릿과 같은 자신의 개인 기기에서 OTP 코드를 획득할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;- FreeOTP&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- Google Authenticator&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 사용자가 OTP 사용여부를 선택할 수 있도록 허용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드를 사용해 사용자가 성공적으로 인증을 수행하면 Keycloak은 사용자가 계정 연동된 OTP 자격증명을 갖고 있는지 확인합니다. OTP 자격증명이 설정되지 않은 경우 Keycloak은 사용자를 인증하고 애플리케이션으로 다시 리다이렉트시킵니다. 위 과정들은 사용자가 realm에 인증을 수행하면서 거치는 과정들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 OTP 자격증명이 설정된 사용자의 경우 Keycloak은 사용자 인증을 수행하기 전에 사용자의 OTP를 획득하고 검증하기 위해 인증 흐름 과정에서 추가적인 단계를 수행해야합니다. 테스트 계정 콘솔에 로그인하여 OTP 획득 및 검증 과정을 확인해봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정 콘솔에 로그인하여 Signing In 페이지에서&amp;nbsp; Set up Authenticator Application 버튼을 클릭해 OTP를 통해 2FA를 설정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mfo8d/btsMm0Tvko8/kGKy3UPKJ8SCOesZyvjDyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mfo8d/btsMm0Tvko8/kGKy3UPKJ8SCOesZyvjDyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mfo8d/btsMm0Tvko8/kGKy3UPKJ8SCOesZyvjDyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmfo8d%2FbtsMm0Tvko8%2FkGKy3UPKJ8SCOesZyvjDyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1695&quot; height=&quot;823&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 인증자 설정을 선택하면 코드를 생성하기 위해 사용할 공유키를 포함한 QR 코드가 사용자에게 표시됩니다. 스마트폰을 사용하면 FreeOTP 또는 Google Authenticator (현재 기준 앱 이름 : Google OTP ) 모바일 애플리케이션을 통해 해당 QR 코드를 스캔할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1381&quot; data-origin-height=&quot;1336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ukZHA/btsMmsbRlwg/kPHLVKdIWb2gdabskkiVq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ukZHA/btsMmsbRlwg/kPHLVKdIWb2gdabskkiVq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ukZHA/btsMmsbRlwg/kPHLVKdIWb2gdabskkiVq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FukZHA%2FbtsMmsbRlwg%2FkPHLVKdIWb2gdabskkiVq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1381&quot; height=&quot;1336&quot; data-origin-width=&quot;1381&quot; data-origin-height=&quot;1336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증자를 사용해 QR코드를 스캔하면 OTP 자격증명 등록 프로세스를 수행하고 해당 프로세스를 수행한 후 사용자를 인증하기 위해 사용할 코드를 생성합니다. TOTP를 사용하는 경우 해당 코드는 30초마다 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OTP 자격증명 등록 프로세스를 수행하려면 사용 중인 모바일 애플리케이션의 코드를 사용해 one-time code필드를 설정하고 submit 버튼을 클릭합니다. 필요한 경우 사용자는 생성한 OTP 자격 증명의 별칭을 정의할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 한번 로그인을 하기위해 좌측 상단 코너에 있는 Sign Out 버튼을 클릭해 콘솔에 로그아웃하고 인증을 수행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;951&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TwzyE/btsMnpZM2Lm/6I7btbmaZQltpKDYXkppXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TwzyE/btsMnpZM2Lm/6I7btbmaZQltpKDYXkppXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TwzyE/btsMnpZM2Lm/6I7btbmaZQltpKDYXkppXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTwzyE%2FbtsMnpZM2Lm%2F6I7btbmaZQltpKDYXkppXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1347&quot; height=&quot;951&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;951&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OTP 설정하기 전과 비교했을대 이번에는 코드를 제공을 요청하는 페이지가 표시됩니다. 스마트폰을 사용해 코드를 획득하고 one-time code 필드에 입력하여 로그인합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. OTP를 통한 사용자 인증 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇몇 OTP 활용 사례에서 OTP 사용여부는 사용자의 요구가 아닌 realm에 정의된 보안정책을 기반으로 설정됩니다. keycloak을 사용하면 OTP 인증의 기본 동작을 변경해 인증 전에 사용자가 OTP 자격 증명을 설정하거나 기존 자격 증명을 성공적으로 realm에 인증을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 설정을 활성화 하려면 좌측 메뉴의 Authentication 을 클릭하고 사용가능한 흐름 리스트에서 Browser를 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Browser-conditional OTP를 Required로 설 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;1261&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxfSY1/btsMnLVJFLF/NF7GFYIVQMak4ZFxoCtEi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxfSY1/btsMnLVJFLF/NF7GFYIVQMak4ZFxoCtEi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxfSY1/btsMnLVJFLF/NF7GFYIVQMak4ZFxoCtEi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxfSY1%2FbtsMnLVJFLF%2FNF7GFYIVQMak4ZFxoCtEi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1948&quot; height=&quot;1261&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;1261&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 사용자 계정 설정으로 가서 연동된 otp 자격증명을 제거합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2491&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qzvlm/btsMnFBo26i/sKYg17BF23XDiFLYGz1hQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qzvlm/btsMnFBo26i/sKYg17BF23XDiFLYGz1hQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qzvlm/btsMnFBo26i/sKYg17BF23XDiFLYGz1hQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqzvlm%2FbtsMnFBo26i%2FsKYg17BF23XDiFLYGz1hQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2491&quot; height=&quot;886&quot; data-origin-width=&quot;2491&quot; data-origin-height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 http://localhost:9090/realms/myrealm/account 사용자 콘솔에 로그인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;1296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wmMoH/btsMnNlIhKo/c6oQLQRvXC51jmRjvU2AMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wmMoH/btsMnNlIhKo/c6oQLQRvXC51jmRjvU2AMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wmMoH/btsMnNlIhKo/c6oQLQRvXC51jmRjvU2AMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwmMoH%2FbtsMnNlIhKo%2Fc6oQLQRvXC51jmRjvU2AMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1864&quot; height=&quot;1296&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;1296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존과는 다르게 사용자는 이제 OTP 자격증명을 설정해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. 웹 인증 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹인증 즉 , WebAuthn 프로토콜은 인터넷에서 사용자 인증의 유용성과 보안을 개선하기 위해 사용됩니다. 즉 암호화 프로토콜을 사용해 사용자를 인증하기 위해 브라우저를 중개자로 사용해 서버와 보안 기기가 서로 통신 할 수 있는 추가 기능을 제공합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WebAuthn은 비대칭 키를 기반으로 사용자의 기기를 안전하게 등록하고 시스템에서 사용자를 인증합니다. 기기와 서버에서 공유되는 키를 사용하지 않으며 공개키만 사용합니다. 보안기기와 서버사의 중개자 역할을 수행함으로써 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WebAuthn은 생체 정보를 통해 해당 기기들을 2FA, MFA로 활용하거나 보안 기기 이외의 명시적 자격증명 없이 사용자를 원활하게 인증할 수 있도록 해줍니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2FA에 사용할 경우 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WebAuthn은 Keycloak과 코드 생성에 사용되는 서드파티 애플리케이션에 공유 키가 없기 떄문에 OTP보다 더 안전합니다. 대신 사용자는 민감한 데이터를 노출하지 않고 2FA와 통신하기 위해 강력한 암호화를 사용하는 보안 기기를 소지해야합니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WebAuthn은 패스워드 또는 OTP코드를 처리할 필요가 없기 떄문에 사용자가 싯템에 인증을 수행할 경우 더 나은 펴의성을 제공합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;보안 기기 또는 인증자는 FIDO2의 요구사항을 준수하는 경우 어떠한 것도 사용할 수 있습니다. 지문을 지원하는 스마트폰, USB에 포함된 보안키, NFC(Near-field Communication) 기기 를 사용할 수 있습니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WebAuthn은 해당 기기를 통해 사용자가 등록하고 인증하는 방법에 대해 다양한 측면에 세부적으로 제어할 수 있습니다 기기를 소유한 사용자의 ID를 확인하는 방법에 대한 요구사항을 제어하거나 자격증명을 기기에 저장할 수도 있기 떄문에 서버에 자격증명을 저장해야 하는 필요성을 제거할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 WebAuthn을 통해 다음과 같은 다양한 이용 사례를 해결 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 인증 과정 또는 계정 콘솔을 사용해 기기를 등록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- OTP의 좀더 안전한 대안으로 2FA용 보안 기기를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 보안 기기에서 지원하는 모든 형태의 생체 인증을 사용해 MFA용 보안기기를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 이름 또는 패스워드가 없는 인증에 보안 기기를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 사용자가 로그인 페이지에서 다양한 인증 방법을 선택할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 WebAuthn을 통해 패스워드 없는 인증 또는 OTP를 이중 인증으로 사용하는 패스워드 기반 인증 사용 여부를 사용자가 선택할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12. 인증 흐름에서 WebAuthn 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 기기를 사용해 인증을 수행하려면 WebAuthn을 지원하는 인증 흐름 정의를 생성해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 단계를 통해 신규흐름을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; browser을 복제 -&amp;gt; My WebAuthn 이름으로 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2541&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nUJb8/btsMnDKquvn/GuHTwL1EvlZo6gwtwVr2H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nUJb8/btsMnDKquvn/GuHTwL1EvlZo6gwtwVr2H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nUJb8/btsMnDKquvn/GuHTwL1EvlZo6gwtwVr2H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnUJb8%2FbtsMnDKquvn%2FGuHTwL1EvlZo6gwtwVr2H1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2541&quot; height=&quot;793&quot; data-origin-width=&quot;2541&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My WebAuthn Browser -Conditional OTP 하위 흐름은 OTP Form 실행 삭제&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b00YFM/btsMma3QmaG/2w6u7L6Pn1EF3l9aM1LXN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b00YFM/btsMma3QmaG/2w6u7L6Pn1EF3l9aM1LXN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b00YFM/btsMma3QmaG/2w6u7L6Pn1EF3l9aM1LXN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb00YFM%2FbtsMma3QmaG%2F2w6u7L6Pn1EF3l9aM1LXN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1191&quot; height=&quot;292&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My WebAuthn Browser -Conditional OTP 우측 추가 아이콘 클릭 &amp;gt; Add step 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;309&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyIiO5/btsMnqdu2FD/cKna6sey6jOfVw0KVHwEr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyIiO5/btsMnqdu2FD/cKna6sey6jOfVw0KVHwEr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyIiO5/btsMnqdu2FD/cKna6sey6jOfVw0KVHwEr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyIiO5%2FbtsMnqdu2FD%2FcKna6sey6jOfVw0KVHwEr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1666&quot; height=&quot;309&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;309&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My WebAuthn Browser -Conditional OTP 하위 흐름에 WebAuthn Authenticator 선택 Add 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8q6Xx/btsMnPjygGi/qqglkZ1KDTErqpRzbf1sdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8q6Xx/btsMnPjygGi/qqglkZ1KDTErqpRzbf1sdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8q6Xx/btsMnPjygGi/qqglkZ1KDTErqpRzbf1sdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8q6Xx%2FbtsMnPjygGi%2FqqglkZ1KDTErqpRzbf1sdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1254&quot; height=&quot;739&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebAuthn Authenticator을 Required로 설정,&amp;nbsp; My WebAuthn Browser -Conditional OTP 을 Conditional로 설정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LATUB/btsMmIlvleT/q9PkmkI6gnXoDPi19A0Wy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LATUB/btsMmIlvleT/q9PkmkI6gnXoDPi19A0Wy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LATUB/btsMmIlvleT/q9PkmkI6gnXoDPi19A0Wy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLATUB%2FbtsMmIlvleT%2Fq9PkmkI6gnXoDPi19A0Wy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1948&quot; height=&quot;451&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My WebAuthn&amp;nbsp; 우측 Action &amp;gt; Bind flow 클릭 &amp;gt; Browser flow로 설정.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2022&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHU4M8/btsMoE9Kh5u/S1Klyg7PlvctIwkEdJ6Q21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHU4M8/btsMoE9Kh5u/S1Klyg7PlvctIwkEdJ6Q21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHU4M8/btsMoE9Kh5u/S1Klyg7PlvctIwkEdJ6Q21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHU4M8%2FbtsMoE9Kh5u%2FS1Klyg7PlvctIwkEdJ6Q21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2022&quot; height=&quot;790&quot; data-origin-width=&quot;2022&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OTP Form 실행을 WebAuthn Authenticator 실행으로 변경한 것 외에는 변경사항이 없습니다. 사용자가 아직 보안 기기 설정을 하지 않았기 때문에 로그인을 수행하면 아직까지 패스워드를 통해 로그인을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정 콘솔에서 보안기기를 등록하는 방법을 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;13. 보안기기 등록 및 인증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;WebAuthn을 realm에 활성화하기 위한 첫번째 단계는 사용자의 기기를 등록하는 것입니다. 패스워드 및 OTP와 마찬가지로 보안 기기의 등록은 특정 required action을 수행해야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;좌측메뉴에 있는 Authentication 링크를 클릭한 다음 Required Action 탭을 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2469&quot; data-origin-height=&quot;1149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BlbPJ/btsMnBMV1e9/sHbX7kVqElG378cvKRr41k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BlbPJ/btsMnBMV1e9/sHbX7kVqElG378cvKRr41k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BlbPJ/btsMnBMV1e9/sHbX7kVqElG378cvKRr41k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBlbPJ%2FbtsMnBMV1e9%2FsHbX7kVqElG378cvKRr41k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2469&quot; height=&quot;1149&quot; data-origin-width=&quot;2469&quot; data-origin-height=&quot;1149&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Webauthn Register 액션&amp;nbsp; On 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2059&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BM7pF/btsMnRaTPGR/hTvOYAwqNKqDPABbW4n8Q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BM7pF/btsMnRaTPGR/hTvOYAwqNKqDPABbW4n8Q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BM7pF/btsMnRaTPGR/hTvOYAwqNKqDPABbW4n8Q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBM7pF%2FbtsMnRaTPGR%2FhTvOYAwqNKqDPABbW4n8Q1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2059&quot; height=&quot;486&quot; data-origin-width=&quot;2059&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Webauthn Register&lt;span&gt; 을 활성화하면 계정 콘솔에서 보안기기를 등록할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;http://localhost:9090/realms/myrealm/account 에 로그인합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;Signing In &amp;gt; Set up Passkey 버튼을 클릭합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1687&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ygTyx/btsMnC59qBx/jpNcyjvr3rU3AyrQ9vSkFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ygTyx/btsMnC59qBx/jpNcyjvr3rU3AyrQ9vSkFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ygTyx/btsMnC59qBx/jpNcyjvr3rU3AyrQ9vSkFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FygTyx%2FbtsMnC59qBx%2FjpNcyjvr3rU3AyrQ9vSkFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1687&quot; height=&quot;756&quot; data-origin-width=&quot;1687&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 기기를 등록하려면 Register버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z2kei/btsMmogNMx6/crdXcOTVbFqYqWCKl8XrUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z2kei/btsMmogNMx6/crdXcOTVbFqYqWCKl8XrUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z2kei/btsMmogNMx6/crdXcOTVbFqYqWCKl8XrUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz2kei%2FbtsMmogNMx6%2FcrdXcOTVbFqYqWCKl8XrUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1699&quot; height=&quot;838&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자로 인증을 수행하는 경우 인증을 완료하기 위해 보안 기기와 상호작용을 요청하는 메시지가 표시됩니다. 이러한 작업은 OTP를 이중 인증으로 사용하는 방법과 유사하지만 사용자는 특정코드를 입력하거나 전송할 필요가 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nLoyD/btsMomO1e7c/v0ampC87rlxVBkwRJGy8z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nLoyD/btsMomO1e7c/v0ampC87rlxVBkwRJGy8z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nLoyD/btsMomO1e7c/v0ampC87rlxVBkwRJGy8z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnLoyD%2FbtsMomO1e7c%2Fv0ampC87rlxVBkwRJGy8z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1068&quot; height=&quot;834&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;14. 강력한 인증 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강력한 인증은 최근 널리 사용되는 용어입니다. 해당용어의 정의는 강력한 인증이 사용되는 상황에 따라 다릅니다.일반적으로 강력한 인증은 사용자를 인증하기 위해 이중 인중 또는 다중 인증을 적용하는 것을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 살펴본 것처럼 Keycloak은 realm에 대한 2FA (Two-factor authentication 2단계 인증) 또는 MFA(Multi Factor Authentication 다중인증)를 활성화하는데 필요한 기능을 제공합니다. 2FA를 통해 강력한 인증 요구 사항을 수행하는 경우 WebAuthn을 통해 OTP 또는 보안 기기를 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 MFA는 아마도 생체 인증을 통해 사용자를 안전하게 식별하고 인증하는 핵심 측면을 가진 가장 강력한 인증 유형일 것입니다. 이와 같은 경우 , WebAuthn을 사용해 사용자의 ID(예를들어 지문인식)를 인증하기 위해 보안 기기를 설정하고 인증을 시도하는 사용자가 해당 보안 기기를 사용 중인지 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 강력한 인증에는 2FA (Two-factor authentication 2단계 인증) 또는 MFA(Multi Factor Authentication 다중인증)를 활용해 IP주소 히스토리 및 사용자가 인증을 수행하기 위해 사용하는 기기와 같은 여러가지 인증 요소를 활성화하는 것도 포함됩니다.이와 같은 경우 위험 점수 또는 사용자의 행동을 기반으로 사용자를 인증하는 최적의 요소를 선택할 수 있습니다. 또는 사용자가 민감한 데이터에 접근하거나 시스템에서 중요한 작업을 수행하는 경우 사용자에게 재인증을 요청할 수 있습니다. keycloak-26.0.7 기준, 아직까지는&amp;nbsp; Keycloak은 적응형 인증 , 리스크 기반 인증 또는 단계형 인증과 같은 범용 인증을 자체적으로 지원하지는 않습니다. 하지만 Keycloak은 realm에 대한 새로운 유형의 인증을 구성하고 구현하는 방법에 있어서 매우 유연합니다. Keycloak은 개발자들이 핵심 기능을 확장하기 위해 사용하는 SPIs(Service Provider Interfaces) 집합을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak otp</category>
      <category>keycloak 로그인</category>
      <category>keycloak 로그인 화면 변경</category>
      <category>keycloak 로그인변경</category>
      <category>keycloak 이중인증</category>
      <category>keycloak 인증</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/102</guid>
      <comments>https://marshmello.tistory.com/102#entry102comment</comments>
      <pubDate>Tue, 18 Feb 2025 13:15:12 +0900</pubDate>
    </item>
    <item>
      <title>import androidx.graphics.shapes.Shapes_androidKt;                               ^  symbol:   class Shapes_androidKt  location: package androidx.graphics.shapes</title>
      <link>https://marshmello.tistory.com/101</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;import&amp;nbsp;androidx.graphics.shapes.Shapes_androidKt; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;^ &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;symbol:&amp;nbsp;&amp;nbsp;&amp;nbsp;class&amp;nbsp;Shapes_androidKt &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;location:&amp;nbsp;package&amp;nbsp;androidx.graphics.shapes&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9L68X/btsMi2SjTf4/lMYSoDBzDS2wwbHHkPwbBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9L68X/btsMi2SjTf4/lMYSoDBzDS2wwbHHkPwbBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9L68X/btsMi2SjTf4/lMYSoDBzDS2wwbHHkPwbBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9L68X%2FbtsMi2SjTf4%2FlMYSoDBzDS2wwbHHkPwbBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1914&quot; height=&quot;1026&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/material-components/material-components-android&quot; data-turbo-frame=&quot;repo-content-turbo-frame&quot; data-pjax=&quot;#repo-content-pjax-container&quot;&gt;material-components-android&lt;/a&gt;&lt;/b&gt; 프로젝트를 실행하면 위와 같은 에러가 나타납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;gradle.properties 에 아래 소스 추가 후 Sync Now 클릭&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739543935534&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;android.disableAutomaticComponentCreation=true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1829&quot; data-origin-height=&quot;657&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAagyb/btsMkL2wFJN/IR2gH73I4sNJ1iGnbJ3sQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAagyb/btsMkL2wFJN/IR2gH73I4sNJ1iGnbJ3sQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAagyb/btsMkL2wFJN/IR2gH73I4sNJ1iGnbJ3sQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAagyb%2FbtsMkL2wFJN%2FIR2gH73I4sNJ1iGnbJ3sQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1829&quot; height=&quot;657&quot; data-origin-width=&quot;1829&quot; data-origin-height=&quot;657&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Run selected steps 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brcCQ6/btsMk1RAbL9/vM8wK1Gks6d7HhSMh5lyN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brcCQ6/btsMk1RAbL9/vM8wK1Gks6d7HhSMh5lyN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brcCQ6/btsMk1RAbL9/vM8wK1Gks6d7HhSMh5lyN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrcCQ6%2FbtsMk1RAbL9%2FvM8wK1Gks6d7HhSMh5lyN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;825&quot; height=&quot;236&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Run selected steps 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;lib/build.gradle 에 from components.release을&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;from components.findByName('release')로 변경 Try Again 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pp1bG/btsMj58jeMM/q9dPVuSN9e9Wg5RSQaVns1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pp1bG/btsMj58jeMM/q9dPVuSN9e9Wg5RSQaVns1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pp1bG/btsMj58jeMM/q9dPVuSN9e9Wg5RSQaVns1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpp1bG%2FbtsMj58jeMM%2Fq9dPVuSN9e9Wg5RSQaVns1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1248&quot; height=&quot;662&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 android.disableAutomaticComponentCreation=true 삭제 후 Sync now 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z2BlO/btsMkY1D0GE/H4oTaTWHNAnKKNHSZz1RYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z2BlO/btsMkY1D0GE/H4oTaTWHNAnKKNHSZz1RYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z2BlO/btsMkY1D0GE/H4oTaTWHNAnKKNHSZz1RYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ2BlO%2FbtsMkY1D0GE%2FH4oTaTWHNAnKKNHSZz1RYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1038&quot; height=&quot;556&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;catalog/build.gradle: namespace 'io.material.catalog' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;추가 후 Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bITvAf/btsMkcM2rZD/901ONDbfnpKZDedy5RGip0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bITvAf/btsMkcM2rZD/901ONDbfnpKZDedy5RGip0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bITvAf/btsMkcM2rZD/901ONDbfnpKZDedy5RGip0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbITvAf%2FbtsMkcM2rZD%2F901ONDbfnpKZDedy5RGip0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;845&quot; height=&quot;452&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;lib/build.gradle: 에 namespace 'com.google.android.material' 추가 후 Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxCS2k/btsMkxXHMEP/S2DRU9Xc42zCcAeq3RHOq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxCS2k/btsMkxXHMEP/S2DRU9Xc42zCcAeq3RHOq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxCS2k/btsMkxXHMEP/S2DRU9Xc42zCcAeq3RHOq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxCS2k%2FbtsMkxXHMEP%2FS2DRU9Xc42zCcAeq3RHOq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1012&quot; height=&quot;498&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;testing/java/com/google/android/material/testapp/build.gradle:&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;namespace 'com.google.android.material.testapp' 추가 후 &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;Sync now 버튼 클릭&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1641&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/db0jas/btsMjqrN27G/DFm2u86vKKWxWlQaDMWqCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/db0jas/btsMjqrN27G/DFm2u86vKKWxWlQaDMWqCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/db0jas/btsMjqrN27G/DFm2u86vKKWxWlQaDMWqCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdb0jas%2FbtsMjqrN27G%2FDFm2u86vKKWxWlQaDMWqCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1641&quot; height=&quot;539&quot; data-origin-width=&quot;1641&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;testing/java/com/google/android/material/testapp/animation/build.gradle:&amp;nbsp; 에&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;namespace 'com.google.android.material.testapp.animation' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;추가 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;395&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6tEkc/btsMjTNL6vZ/OjrdkvTm9XjQ1DN5A2kkTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6tEkc/btsMjTNL6vZ/OjrdkvTm9XjQ1DN5A2kkTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6tEkc/btsMjTNL6vZ/OjrdkvTm9XjQ1DN5A2kkTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6tEkc%2FbtsMjTNL6vZ%2FOjrdkvTm9XjQ1DN5A2kkTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1037&quot; height=&quot;395&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;395&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;testing/java/com/google/android/material/testapp/base/build.gradle:&lt;br /&gt;namespace 'com.google.android.material.testapp.base' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;추가 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baXpQC/btsMjEp52Mi/8SIFg2PX7H1Ssx3zizDWX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baXpQC/btsMjEp52Mi/8SIFg2PX7H1Ssx3zizDWX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baXpQC/btsMjEp52Mi/8SIFg2PX7H1Ssx3zizDWX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaXpQC%2FbtsMjEp52Mi%2F8SIFg2PX7H1Ssx3zizDWX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1013&quot; height=&quot;476&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;testing/java/com/google/android/material/testapp/custom/build.gradle:&lt;br /&gt;namespace 'com.google.android.material.testapp.custom' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;추가 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDrojs/btsMjTtshHj/K21kIdumc0cCqUBKien9s0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDrojs/btsMjTtshHj/K21kIdumc0cCqUBKien9s0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDrojs/btsMjTtshHj/K21kIdumc0cCqUBKien9s0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDrojs%2FbtsMjTtshHj%2FK21kIdumc0cCqUBKien9s0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;466&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;testing/java/com/google/android/material/testapp/theme/build.gradle:&lt;/span&gt;&lt;br /&gt;namespace 'com.google.android.material.testapp.theme' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;추가 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;Sync now 버튼 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GbhOw/btsMktHNIty/k7BFOAdamz5mZdivKl7oi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GbhOw/btsMktHNIty/k7BFOAdamz5mZdivKl7oi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GbhOw/btsMktHNIty/k7BFOAdamz5mZdivKl7oi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGbhOw%2FbtsMktHNIty%2Fk7BFOAdamz5mZdivKl7oi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1016&quot; height=&quot;542&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <category>import androidx.graphics.shapes.shapes_androidkt</category>
      <category>package androidx.graphics.shapes</category>
      <category>^  symbol:   class shapes_androidkt</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/101</guid>
      <comments>https://marshmello.tistory.com/101#entry101comment</comments>
      <pubDate>Sat, 15 Feb 2025 00:17:12 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 6</title>
      <link>https://marshmello.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 사용자 생성 및 관리 방법, 사용자 자신의 계정을 관리하는 방법, 자격증명을 관리하는 방법과 사용자를 인증하기 위한 서로 다른 ID 저장소 및 ID 제공자 통합 방법 그리고 OpenID Connect, SAML(Security Assertion Markup Language), LDAP(Lightweight Directory Access Protocol)와 같은 오픈 프로토콜을 사용해 사용자의 정보를 가져오는 방법과 같은 ID관리 및 연합과 관련돼 Keycloak에서 제공하는 기능들에 대해 자세히 알아볼것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 로컬 사용자 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 신규 사용자를 생성하는 경우, Users 메뉴를 클링하면 해당 realm에 등록된 모든 사용자가 포함된 리스트가 표시됩니다. 리스트의 우측 상단에는 Add User 버튼이 있습니다. 해당 버튼을 클릭하면 사용자 생성페이지가 표시됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 사용자를 생성하는 경우, 사용자이름 username만 입력하면 신규사용자를 생성할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;927&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/or0Rc/btsMdJysOco/Ou7lQC8Gj5YHfX7wUOIYiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/or0Rc/btsMdJysOco/Ou7lQC8Gj5YHfX7wUOIYiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/or0Rc/btsMdJysOco/Ou7lQC8Gj5YHfX7wUOIYiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2For0Rc%2FbtsMdJysOco%2FOu7lQC8Gj5YHfX7wUOIYiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1359&quot; height=&quot;927&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;927&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자가 사용자에 대한 모든 정보를 사전에 알고 있는 경우 관리 콘솔을 사용해 사용자를 생성하는 것이 편리합니다.하지만 사용 사례에 따라 항상 그렇진 않기 떄문에 사용자가 자신의 realm에 직접 등록하도록 허용하거나 인증 프로세스의 일부로 사용자에게 정보를 요청할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 사용자의 추가적인 정보를 포함시킬 수 있으며, 사용자가 생성된 후에는 사용자가 속한 realm을 통해서만 인증을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 사용자 자격증명 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자를 생성하면 realm에 인증할 수 있습니다. 해당 인증을 수행하기 위해 사용자 자격증명을 설정해야합니다. Keycloak은 다양한 유형의 자격증명을 통해 다양한 형태의 인증을 지원합니다. 사용자는 패스워드, 일회용키, 보안기기,X.509 인증서 등을 사용해 인증할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;927&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qLaWd/btsMdonJaNb/kY9Up5Kg6OegqGBGK9tQ71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qLaWd/btsMdonJaNb/kY9Up5Kg6OegqGBGK9tQ71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qLaWd/btsMdonJaNb/kY9Up5Kg6OegqGBGK9tQ71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqLaWd%2FbtsMdonJaNb%2FkY9Up5Kg6OegqGBGK9tQ71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;752&quot; height=&quot;410&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;927&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 자격증명을 관리하려면 사용자 리스트에서 사용자를 선택한 다음 Credentials 탭을 클릭합니다. 해당 탭에는 사용자와 관련된 모든 자격증명이 표시되며, 자격증명 삭제 및 수정과 같은 작업을 수행할 수 있습니다. 사용자에 대한 패스워&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드를 쉽게 설정할 수 있는 바로가기(shortcuts)도 제공됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 자격증명과 관련된 민감한 데이터를 노출하지 않으며 자격증명과 관련된 기본 및 민감하지 않은 데이터만 노출합니다. 보안 요구 사항에 따라 데이터베이스에 저장된 데이터를 암호화할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당작업을 수행하려면 Password를 입력하고 Temporary 설정을 비활성화합니다. Temporary설정을 비활성화하면 사용자의 최종 패스워드를 생성한다는 것입니다. Set password 버튼을 클릭하여 사용자패스워드를 설정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DI5Nc/btsMfg2H7Qk/4UaB8YKJ0BV8Cb7XvV24ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DI5Nc/btsMfg2H7Qk/4UaB8YKJ0BV8Cb7XvV24ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DI5Nc/btsMfg2H7Qk/4UaB8YKJ0BV8Cb7XvV24ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDI5Nc%2FbtsMfg2H7Qk%2F4UaB8YKJ0BV8Cb7XvV24ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;322&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드를 설정하면 자격증명 리스트가 위에서 설정한 사용자의 신규 패스워드로 업로드 되었음을 확인 할 수 있습니다. 해당 리스트에서 사용자의 자격증명에 대한 정보(민감하지않음)를 확인할 수 있으며 삭제도 할수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 사용자가 realm에 인증할 수 있는지 확인해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://localhost:9090/realms/myrealm/account 에 URL을 통해 해당&amp;nbsp;Realm의&amp;nbsp;계정&amp;nbsp;관리&amp;nbsp;콘솔에&amp;nbsp;접근하여&amp;nbsp;로그인할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2193&quot; data-origin-height=&quot;1233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xhe0n/btsMeuHtqxP/8o2UGT4b3ONx7xer4K5XB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xhe0n/btsMeuHtqxP/8o2UGT4b3ONx7xer4K5XB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xhe0n/btsMeuHtqxP/8o2UGT4b3ONx7xer4K5XB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXhe0n%2FbtsMeuHtqxP%2F8o2UGT4b3ONx7xer4K5XB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2193&quot; height=&quot;1233&quot; data-origin-width=&quot;2193&quot; data-origin-height=&quot;1233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초 로그인시 사용자에게 필요한 필수입력 정보를 입력받습니다. 필수 정보 입력 후 submit 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;1107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcMbD9/btsMfufnzKp/DsktfNx6MiZzcwLIvqrcv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcMbD9/btsMfufnzKp/DsktfNx6MiZzcwLIvqrcv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcMbD9/btsMfufnzKp/DsktfNx6MiZzcwLIvqrcv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcMbD9%2FbtsMfufnzKp%2FDsktfNx6MiZzcwLIvqrcv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;633&quot; height=&quot;596&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;1107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속 후 화면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2055&quot; data-origin-height=&quot;1179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD0XLc/btsMec74B0A/URncNLMkea1r5hVIDeSxZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD0XLc/btsMec74B0A/URncNLMkea1r5hVIDeSxZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD0XLc/btsMec74B0A/URncNLMkea1r5hVIDeSxZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD0XLc%2FbtsMec74B0A%2FURncNLMkea1r5hVIDeSxZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2055&quot; height=&quot;1179&quot; data-origin-width=&quot;2055&quot; data-origin-height=&quot;1179&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 사용자 정보 획득 및 검증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 인증 프로세스 과정에서 Required User Actions라는 기능을 사용해 사용자와 상호작용할 수 있습니다. 해당 설정은 사용자가 realm에 인증하기 전에 수행해야하는 작업들입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이메일 검증: 이메일 검증이 설정된 경우, 이메일이 사용자 소유가 맞는지 확인하기 위해 사용자에게 이메일 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패스워드 업데이트 : 사용자에게 패스워드업데이트 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로파일 업데이트 : 사용자에게 이름 및 이메일 정보를 통해 사용자에게 프로파일 업데이트 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 옵션도 존재하지만 위의 작업을 통해 해당 설정이 얼마나 강력한지, 사용자가 인증할때 사용자와 상호작용할 수 있는 방법을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 test01의 Update profile 작업을 설정하고, 해당 계정의 누락된 정보를 획득합니다. 해당 작업을 수행하기 위해 사용자 리스트에서 test01을 선택하고, Required User Actions 필드에서 사용 가능한 작업 리스트에서 Update profile을 선택합니다. 그다음 Save 버튼을 클릭합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1994&quot; data-origin-height=&quot;1207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pROzh/btsMemiudM1/Ba3Kyjikmwrn6NuEar4Hv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pROzh/btsMemiudM1/Ba3Kyjikmwrn6NuEar4Hv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pROzh/btsMemiudM1/Ba3Kyjikmwrn6NuEar4Hv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpROzh%2FbtsMemiudM1%2FBa3Kyjikmwrn6NuEar4Hv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1994&quot; height=&quot;1207&quot; data-origin-width=&quot;1994&quot; data-origin-height=&quot;1207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://localhost:9090/realms/myrealm/account 에 접속하여 로그인하면 프로필 정보를 입력하도록 나타납니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2503&quot; data-origin-height=&quot;1363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5mlj4/btsMdmjmofK/IBSIetKi0Ei704iSuXjKl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5mlj4/btsMdmjmofK/IBSIetKi0Ei704iSuXjKl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5mlj4/btsMdmjmofK/IBSIetKi0Ei704iSuXjKl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5mlj4%2FbtsMdmjmofK%2FIBSIetKi0Ei704iSuXjKl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2503&quot; height=&quot;1363&quot; data-origin-width=&quot;2503&quot; data-origin-height=&quot;1363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 자동 등록 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 경우 realm의 계정 자동 등록을 활성화하고 해당 계정 정보의 책임을 사용자에게 위임할 수 있습니다. 수동으로 사용자를 생성하는 것과 달리 Keycloak은 로그인 페이지에 사용자 자동 등록을 위한 링크를 제공합니다. 해당 링크를 사용하려면, 좌측 메뉴에서 Realm setting 버튼을 클릭하고 Login탭을 클릭합니다. User registration을 활성화합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;1146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nzzOZ/btsMecNS97G/JsGwyPwzcMUp5GNV45mRnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nzzOZ/btsMecNS97G/JsGwyPwzcMUp5GNV45mRnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nzzOZ/btsMecNS97G/JsGwyPwzcMUp5GNV45mRnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnzzOZ%2FbtsMecNS97G%2FJsGwyPwzcMUp5GNV45mRnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;659&quot; height=&quot;764&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;1146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 링크를 클릭하면 관리 콘솔에서 사용자를 생성할 때 사용자 것과 동일한 정보를 요청하는 등록 페이지가 표시됩니다. 요구하는 정보를 필드에 입력하고 Register 버튼을 클릭해 신규 사용자를 생성합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://localhost:9090/realms/myrealm/account 에 접속하면 Register 버튼이 생성된것을 확인 할 수 있습니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;962&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eiKiKd/btsMe3XkzFa/nGPKKSHuESHXf6ewhdoLck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eiKiKd/btsMe3XkzFa/nGPKKSHuESHXf6ewhdoLck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eiKiKd/btsMe3XkzFa/nGPKKSHuESHXf6ewhdoLck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeiKiKd%2FbtsMe3XkzFa%2FnGPKKSHuESHXf6ewhdoLck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1313&quot; height=&quot;962&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;962&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 사용자 속성 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 속성을 활용해 사용자의 추가적인 메타데이터를 관리할 수 있도록 해줍니다. Keycloak은 기본 정보 집합을 활용해 사용자를 식별하고 인증합니다. 또한 해당 정보는 토큰을 검사하거나 사용자 프로파일에 접근하기 위해 사용할 수도 있습니다. 사용자 속성을 관리하기 위해 사용자 리스트에서 해당 사용자를 선택하고 Attributes 탭을 클릭합니다. 각 속성은 키와 텍스트값을 가집니다. 사용자 속성은 사용자에 대한추가 정보를 애플리케이션에 제공하며 ABAC과 같은 다양한 형태의 권한 부여와 같이 다양한 유형의 문제를 해결할 수 있습니다. 속성을 사용하면 해당 속성을 애플리케이션에서 사용하기 위해 프로토콜 매퍼를 생성해 속성을 토큰에 매핑해야 하며 Introspection 토큰 및 userinfo 엔드포인트를 쿼리할때도 속성을 사용할 수 있습니다. Keycloak을 확장하는 경우 Keycloak 확장과 같이 속성을 통해 사용자 계정에 추가적인 정보를 포함해 계정 콘솔을 확장할 수 있습니다. 또한 동일한 방법으로 프로파일 업데이트 페이지를 사용자 정의하기 위해 사용할 수 있습니다. 해당 페이지는 인증 프로세스 과정에서 사용자에게 표시됩니다. 해당 페이지에서 속성을 사용해 인증 프로세스 단계에서 수집된 사용자 정의 정보를 저장할 수 있습니다. 사용자 속성을 활용해 Keycloak의 여러 부분을 확장해 사용자로부터 추가 정보를 획득하고 사용자 속성으로 저장할 수 있습니다.&amp;nbsp; 그리고 사용자 속성은 일반적으로 프로토콜 매퍼를 통해 사용자에 대한 추가 정보를 애플리케이션에 전달하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. LDAP 및 액티브 디렉터리 통합&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 조직에서 여전이 LDAP 디렉터리를 디지털 ID에 대한 단일 정보 소스로 사용합니다. Keycloak은 다양한 LDAP 서버 구현을 통합해 기존 보안 인프라를 활용하고 Keycloak에서 제공하는 모든 인증 및 인가 기능을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 LDAP을 사용해 여러 방법으로 통합을 수행할 수 있습니다. LDAP 디렉터리의 데이터를 Keycloak 데이터베이스로 가져오고 LDAP 디렉터리와 동기화된 상태로 유지하는 상태 저장 브로커 역할을 수행할 수 있으며, 자격 증명 확인을 LDAP 디렉터리에 위임하는 상태 비저장 브로커 역할을 수행할 수도 있습니다.&amp;nbsp; 또한 단일 realm 내에 여러개의 LDAP 디렉터리를 설정할 수 있고, Keycloak에서 사용자를 인증 할 때 준수해야 하는 우선순위를 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 사용자 연합이라는 용어는 외부 ID 저장소와 통합하는 기능을 의미합니다. LDAP은 사용자 연합의 한 형태이며, 관리 콘솔의 좌측 메뉴에 있는 User Federation 링크를 클릭해 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User federation 메뉴 &amp;gt; Add Ldap providers 버튼 클릭&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;833&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7681L/btsMgsCsYGF/Fs0lcCjYYIKtzu9CWj7IZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7681L/btsMgsCsYGF/Fs0lcCjYYIKtzu9CWj7IZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7681L/btsMgsCsYGF/Fs0lcCjYYIKtzu9CWj7IZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7681L%2FbtsMgsCsYGF%2FFs0lcCjYYIKtzu9CWj7IZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;990&quot; height=&quot;833&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;833&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필수입력 사항 입력 후 save 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;765&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MHJiE/btsMeMbf2eX/aCoKdPdESCXVcx3ISVs0hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MHJiE/btsMeMbf2eX/aCoKdPdESCXVcx3ISVs0hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MHJiE/btsMeMbf2eX/aCoKdPdESCXVcx3ISVs0hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMHJiE%2FbtsMeMbf2eX%2FaCoKdPdESCXVcx3ISVs0hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1081&quot; height=&quot;765&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;765&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;833&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FdVo7/btsMgI54CsV/Qr4trqEYlMWFztJ0yNp34k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FdVo7/btsMgI54CsV/Qr4trqEYlMWFztJ0yNp34k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FdVo7/btsMgI54CsV/Qr4trqEYlMWFztJ0yNp34k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFdVo7%2FbtsMgI54CsV%2FQr4trqEYlMWFztJ0yNp34k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1136&quot; height=&quot;833&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;833&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공자를 선택하면 LDAP 디렉터리와 통합하기 위해 필요한 모든 설정이 포함된 페이지가 표시됩니다. Keycloak은 액티브 디렉터리를 포함해서 대부분이 LDAP 벤더를 지원합니다. Vendor 필드에서 여러 벤더 중 하나를 선택 할 수 있으며, Keycloak은 선택한 벤더에 가장 적합한 디폴트 설정을 찾습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LDAP을 통해 Keycloak을 통합하고자 하는 경우 현재 페이지에 있는 대부분의 설정 즉 , 다양한 연결 설정 및 LDAP 디렉터리 구조와 관련된 설정에 익숙해야합니다. Import Users 설정에서 사용자는 Keycloak이 LDAP 서버의 데이터를 데이터베이스에 취합할 것인지에 대한 여부를 정의할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 이 설정은 사용자가 LDAP 공급자를 통해 인증할 때마다 해당 사용자에 대한 정보가 데이터베이스에 유지되도록 활성화됩니다. 해당 설정이 기본적으로 활성화된 주요 이유 중 하나는그렇지 않은 경우 Keycloak의 모든 기능을 활용 할 수 없기 때문입니다. 해당 기능이 활성화되지 않은 경우 LDAP 디렉터리를 통해 사용자를 인증하는 브로커만 사용할수 있습니다. 일반적으로 사용자가 인증을 시도하면 Keycloak은 해당 사용자가 데이터베이스에 존재하는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 데이터베이스에 없는 경우, Keycloak은 LDAP 디렉터리에서 사용자를 조회합니다. 인증하려는 사용자가 있는 경우, Keycloak은 LDAP 프로토톨을 사용해 사용자를 인증하고, 인증이 성공하면 데이터베이스에 사용자를 등록합니다.사용자를 등록하면 사용자는 연합 사용자로 설정되며 사용자 및 LDAP 제공자 간에 링크가 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자와 LDAP 공급자 간의 링크는 사용자연합의 중요한 부분입니다. 사용자가 가진 LDAP과 같은 특정 사용자 연합 제공자의 링크를 확인해 Keycloak은 local user와 federated user를 구분할 수 있습니다. 여기서 federated라는 용어는 ID 및 접근 관리 데이터를 공유하기 위해 Keycloak과 외부 ID 저장소(LDAP 디렉터리)간에 생성된 신뢰를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 LDAP 디렉터리에 데이터를읽고 쓴느 방법을 관리하기 위한몇가지 키 동기화설정을 제공합니다. 다른 작업을 수행하기 전에 Edit Mode 설정을 통해 원하는 동기화 전략을 결정해야합니다. READ_ONLY, WRITABLE 및 UNSYNCED의 세가지 전략 중에서 선택할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;READ_ONLY 전략을 사용하면 LDAP 디렉터리를 읽기 전용 모드로 사용할 수 있으며, 연합 사용자에 대한 변경 사항은 LDAP 디렉터리에 다시 복제되지 않습니다. 반명 WRITEABLE 전략은 연합 사용자에게 적용된 모든 변경 사항을 LDAP 디렉터리에 복제할 수 있는 강력한 전략입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 전략을 사용해야하는지는 활용 사례에 따라 달라집니다.&amp;nbsp; 특정 환경에서는 LDAP이 사용자가 제어할 수 있는 권한이 제한된 ID의 단일 정보 소스인 경우도 있습니다.LDAP 디렉터리의 ID 관리를 중앙 집중화하면서 Keycloak을 사용해 보안인프라를 현대화 하는 경우 READ_ONLY 전략이 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 LDAP으로 마이그레이션할 계획이 있고, Keycloak을 통해 ID 관리를 중앙 집중화하려는 경우 writable 전략이 해당 전환 과정에서 도움이 될 것입니다. 또한 해당 전략을 통해 LDAP을 활성화 상태로 유지하고 Keycloak을 통해 변경된 사항을 동기화할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 적절한 동기화 전략을 결정하면 Keycloak에서 제공하는 추가설정을 확인해 동기화 방법을 제어할 수 있습니다. Keycloak을 사용하면 관리 콘솔을 통해 프로세스를수동으로 실행해 사용자정보를동기화하거나 자동으로 동기화가 수행되도록 시간을 설정해 동기화를 수행 할 수 있습니다.&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 정보의 수동 동기화를 실행하려면 Synchronize All Users 버튼을 클릭해야합니다. 해당 버튼은 LDAP 제공자를 활성화 하면 됩니다. 제공자를 생성한 다음 바로 전체 동기화를 실행하는 것이 권장 됩니다.&amp;nbsp; 초기 인증을 수행할 때 전체 동기화를 수행하면 사용자 가져오기가 실행되지 않기 때문입니다.또한 마지막 동기화 후 변경된 로컬 사용자 동기화, LDAP 제공자에서 가져온 사용자 제거, 사용자와 LDAP 제공자간의 링크제거 등 수행할여러 작업이 제공돼 사용자를 효과적으로 일반 로컬 사용자로 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자를 가져온 후에는 필요에 따라 주기적 동기화를 예약할 수 있습니다.전체 또는 부분 동기화에 대한 동기화를 예약할 수 있습니다. 전체 동기화를 수행하면 Keycloak이 데이터베이스에 복제해야하는 LDAP 트리의 변경 사항을 확인해 LDAP에서 생성된 신규 사용자 및 해당 사용자의 갱신된 정보가 지속적으로 동기화됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부분 동기화는 마지막 동기화를 수행한 후 Keycloak이 신규 사용자를 찾고 기존 사용자를 갱신하기 때문에 좀 더 효율적인 전략을 통해 Keycloak을 최신상태로 유지할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. LDAP 매퍼 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사용자와 마찬가지로 Keycloak 또한 LDAP에서다양한 유형의 정보를 가져옵니다. LDAP에서 사용자를 가져오는 방법과 달리 해당 정보는 매퍼를 통해 가져옵니다. LDAP 매퍼는 LDAP에서 Keycloak으로 또는 그 반대로 정보를 매핑하기 위한 Keycloak의 특별하고 강력한 기능입니다. LDAP 매퍼는 사용자, 그룹, 역할, 인증서 또는 액티브디렉터리와 같은 특정 LDAP 제공자를 사용할 때만&amp;nbsp; 접근할 수 있는 정보에 대한 LDAP 데이터 읽기 및 쓰기 방법에 대한 세부적인 제어와 LDAP 통합에 대한 또 다른 확장 포인트를 제공합니다. LDAP에서 특정 데이터 집합을 매핑해야 하는 경우 지원 가능한 매퍼 리스트를 확인하고 적절한 매퍼를 찾으면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 제공자를 생성하는경우 Keycloak은 제공자 설정에 기반해 자동으로 매퍼 집합을 설정합니다. 예를 들어 가져오기 모드 또는 편집 모드에 따라 다른 매퍼 집합이 생성됩니다. 따라서 제공자를 생성하기 전에 모드를 설정하는 것이 중요합니다. 해당 설정을 수행하지 않으면 공급자가 생성된 후 설정에따라 매퍼를 변경해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LDAP 제공자와 관련된 매퍼를 관리하려면 사용 중인 제공자의 Mappers 탭을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q4WAT/btsMgJqnYNh/Tvk0mLwFNlzDlW0wn5Kmfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q4WAT/btsMgJqnYNh/Tvk0mLwFNlzDlW0wn5Kmfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q4WAT/btsMgJqnYNh/Tvk0mLwFNlzDlW0wn5Kmfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq4WAT%2FbtsMgJqnYNh%2FTvk0mLwFNlzDlW0wn5Kmfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;858&quot; height=&quot;806&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 탭에서 사용중인 공급자의 현재 활성화된 모든 매퍼 리스트가 표시됩니다.또한 신규 매퍼를 제공자와 연동할 수 있습니다. 리스트의 우측 상단에 있는 Create 버튼을 클릭해 해당 작업을 수행할 수 있습니다. 사용 가능한 여러 가지 유형의 매퍼가 있으며 각 매퍼는 특정 작업과 관련돼 있습니다.&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 그룹 동기화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LDAP의 그룹 데이터를&amp;nbsp; 관리하려면 매퍼 리스트 맵퍼를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X519b/btsMgr4CidL/qyCdCbCYnkmbGCBfIMV7w1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X519b/btsMgr4CidL/qyCdCbCYnkmbGCBfIMV7w1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X519b/btsMgr4CidL/qyCdCbCYnkmbGCBfIMV7w1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX519b%2FbtsMgr4CidL%2FqyCdCbCYnkmbGCBfIMV7w1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;446&quot; height=&quot;520&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Add mapper 클릭&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/snrem/btsMg5fsKSG/dfRQ3pTR9JagWNUulFXqkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/snrem/btsMg5fsKSG/dfRQ3pTR9JagWNUulFXqkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/snrem/btsMg5fsKSG/dfRQ3pTR9JagWNUulFXqkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsnrem%2FbtsMg5fsKSG%2FdfRQ3pTR9JagWNUulFXqkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;475&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;신규 매퍼이름을 입력하고 Mapper Type 필드에서 group-ldap-mapper를 선택 후 저장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIrfZn/btsMkA1G0ND/QFkj7ILuAQgdI1Ep4QnuW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIrfZn/btsMkA1G0ND/QFkj7ILuAQgdI1Ep4QnuW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIrfZn/btsMkA1G0ND/QFkj7ILuAQgdI1Ep4QnuW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIrfZn%2FbtsMkA1G0ND%2FQFkj7ILuAQgdI1Ep4QnuW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1056&quot; height=&quot;297&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2cWCL/btsMe9KGcpF/o25VEckir8iiNVJsdqZ0d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2cWCL/btsMe9KGcpF/o25VEckir8iiNVJsdqZ0d1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2cWCL/btsMe9KGcpF/o25VEckir8iiNVJsdqZ0d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2cWCL%2FbtsMe9KGcpF%2Fo25VEckir8iiNVJsdqZ0d1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1134&quot; height=&quot;824&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 페이지의 설정 중 일부는 LDAP 트리에서 그룹을 설정하는 방법과 관련이 있습니다. 예를 들어 그룹이 속한 DN(Distinguished Name)을 제공해야합니다. 해당 속성은 그룹 이름을 가져오기 위해 사용되며, Keycloak이 사용자가 속한 그룹을 자동을 검색할 수 있도록 LDAP 트리에서 멤버십 정보를 정의하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;group-ldap-mapper 유형은 LDAP으로부터 그룹을 가져오는 방법을 설정하기 위한 몇가지 설정을 제공합니다. 일부 설정은 LDAP 트리에서 그룹이 구성되는 방식에 따라 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 매퍼를 생성하는 첫번째 단계는 LDAP 트리에서 그룹 위치를 설정하는 것입니다. 해당 작업을 수행하려면 전체 그룹이 위치한 베이스 DN을 포함해 LDAP Groups DN 필드를 작성해야합니다. 또한 몇몇 기준에 따라 그룹을 가져와야하는 복잡한 LDAP 트리가 있는 경우 추가 필터를 제공해야 합니다. LDAP Filter 필드를 사용해 해당 작업을 수행할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 그룹 엔트리에 정의된 오브젝트 클래스를 기반으로 베이스 DN에서 그룹 엔트리를 조회합니다. Group Object Classes 필드를 사용해 오브젝트 클래스를 설정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IIbVS/btsMkaoOihB/FEJ3f5OKKnRg4KNACnX9Dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IIbVS/btsMkaoOihB/FEJ3f5OKKnRg4KNACnX9Dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IIbVS/btsMkaoOihB/FEJ3f5OKKnRg4KNACnX9Dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIIbVS%2FbtsMkaoOihB%2FFEJ3f5OKKnRg4KNACnX9Dk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1058&quot; height=&quot;204&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;204&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 단계는 Keycloak에서 그룹 엔트리 정보를 Keycloak과 매핑하는 방법을 설정하는 것입니다. 그룹 이름은 Group Name LDAP Attribute 필드를 통해 해당 엔트리에서 매핑될 수 있습니다. 해당 필드는 그룹 이름을 저장하기 위해 사용하는 LDAP 속성으로 변경할 수 있습니다. 일반적으로는 CN(Common Name) 속성으로 사용합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 LDAP에서 그룹을 검색하고 해당 정보를 Keycloak에 매핑하는 방법을 이해했기 떄문에 그룹계층 및 사용자 멤버십을 매핑하는 방법을 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1101&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3RZyl/btsMlBezAd9/i2spdaHZhosT072QpLI321/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3RZyl/btsMlBezAd9/i2spdaHZhosT072QpLI321/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3RZyl/btsMlBezAd9/i2spdaHZhosT072QpLI321/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3RZyl%2FbtsMlBezAd9%2Fi2spdaHZhosT072QpLI321%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1101&quot; height=&quot;726&quot; data-origin-width=&quot;1101&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LDAP에서 그룹은 일반적으로 조직 트리를 나타내기 위해 계층 구조로 구성됩니다. Keycloak을 사용하면 LDAP에서 그룹을 가져올 때 해당 트리를 자동으로 생성해 그룹 계층 구조를 매핑하고 유지할 수 있습니다. 첫번째 Membership LDAP Attribute 필드를 사용해 계층 구조에서 그룹 간의 관계를 추론하는데 사용되는 속성을 설정하는 것입니다. Keycloak은 해당 속성값을 확인해 하위 그룹을 조회합니다. 해당 포맷은 일반적으로 다른 그룹 엔트리의 FQN(Fully Qualified Name)을 사용합니다. 또한 Keycloak은 LDAP의 사용자 멤버십을 매핑해 사용자를 가져오는 경우 사용자가 속한 그룹에 사용자를 자동으로 할당합니다. 해당 작업을 수행하기 위해 LDAP에서 멤버십을 설정하는 방법에 대해 다른 전략을 설정할 수 있습니다. &lt;span&gt;User Groups Retrieve Strategy&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;필드를 사용해 그룹의 member 속성에 따라 사용자 멥버십 자격을 가져올지(그룹계층 구조를 가져오는 것과 유사함) 또는 LDAP 사용자 엔트리에 포함된 다른 속성을 통해 멤버십 자격을 가져올지 여부를 선택할 수 있습니다. 동기화 측면에서는 매퍼를 사용하면 그룹 정보를 LDAP 디렉터리와 동기화하는 방법과 그룹을 Keycloak으로 가져오는 방법을 세부적으로 제어할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰기 권한을 가진 LDAP 제공자를 사용하는 경우, 매퍼는 기본적으로 사용자 멤버십을 포함해 LDAP에서 가져온 그룹에 대한 변경 사항을 재작성합니다. 해당 작업은 그룹 정보를 가져와 LDAP에 다시 동기화하는 방법에 대한 다양한 전략을 제공하는 Mode 필드를 통해 수행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 LDAP에서 가져온 그룹은 Keycloak에서 최상위 그룹으로 생성됩니다. 상황에 따라 LDAP에서 가져온 그룹을 로컬 그룹과 구별하기 위해 Keycloak의 특정 그룹에 포함시키는 것이 유용할 수 있습니다. 해당 작업을 수행하려면 Groups Path 필드를 Keycloak의 기존 그룹으로 설정하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 역할 동기화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그룹과 마찬가지로 역할도 특정 매퍼를 사용해 LDAP에서 매핑됩니다. 역할 데이터를 가져오려면 매퍼 리스트의 우측 상단 코너에 있는 Add mapper 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ib9I5/btsMlA00HoB/msV6ddHdBYyt2GK37Mase1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ib9I5/btsMlA00HoB/msV6ddHdBYyt2GK37Mase1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ib9I5/btsMlA00HoB/msV6ddHdBYyt2GK37Mase1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIb9I5%2FbtsMlA00HoB%2FmsV6ddHdBYyt2GK37Mase1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;933&quot; height=&quot;760&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 매퍼의 이름을 입력하고 Mapper Type필드에서 role-ldap-mapper를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/divJxA/btsMlizvjUX/dulU8IJlPCXGiVw6vkJ9f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/divJxA/btsMlizvjUX/dulU8IJlPCXGiVw6vkJ9f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/divJxA/btsMlizvjUX/dulU8IJlPCXGiVw6vkJ9f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdivJxA%2FbtsMlizvjUX%2FdulU8IJlPCXGiVw6vkJ9f0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1116&quot; height=&quot;433&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 설정은 주로 Keycloak이 LDAP 트리에서 엔트리를 조회하는 방법을 설정하는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 Keycloak에 인증할 때마다 Keycloak에서 역할을 자동으로 가져옵니다. 또한 Keycloak을 사용해 매퍼를 생성한 후 수동으로 동기화를 실행 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할을 가져오는 경우 Keycloak은 기본적으로 해당 역할을 realm역할로 생성합니다. realm의 사용자는 LDAP에 설정된 역할과 동일한 역할이 자동으로 설정됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 작업은 Use Realm Roles Mapping 필드를 통해 수행되며, 또한 Keycloak에서 가져온 역할이 특정 클라이언트의 클라이언트 역할로 생성되도록 비활성화 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zFVgZ/btsMjGaTocH/33YKnZcfXKtpSyEIFhKyl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zFVgZ/btsMjGaTocH/33YKnZcfXKtpSyEIFhKyl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zFVgZ/btsMjGaTocH/33YKnZcfXKtpSyEIFhKyl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzFVgZ%2FbtsMjGaTocH%2F33YKnZcfXKtpSyEIFhKyl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1067&quot; height=&quot;397&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;397&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Keycloak을 통해 데이터를 가져오는 방법을 세밀하게 제어할 수 있고, LDAP에서 가져온 정보에 변경 사항이 발생할 때마다 해당 변경 사항이 LDAP 반영되는 것을 확인했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. 서드파티 ID 제공자 통합&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 개방형 표준 프로토콜을 활용해 keycloak을 서드파티 ID 제공자와 연동할 수 있습니다. ID 제공자는 keycloak 및 ID 제공자 간의 크로스 도메인 트러스트(cross-domain trust)를 생성하기 위해 사용자 연합을 사용합니다. 크로스 도메인 트러스트는 사용자의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID 데이터를 공유하고 사용자를 keycloak에서 생성, 인증 그리고 인가하기 위해 사용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;서드파티 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID&lt;span&gt; 제공자 통합은 keycloak을 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID&lt;span&gt; 브로커로 사용해 수행할 수 있습니다. keycloak은 대상 ID&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 제공자의 사용자 인증 및 복제를 위한 중개 서비스 intermediary service 역할을 수행합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID&lt;span&gt; 브로커는 다양한 유형의 문제들을 해결할 수 있습니다. 레거시 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID 및 접근 관리 시스템의 통합 포인트로서 소셜 제공자와 통합하기 위해 사용할 수 있습니다. 또는 비즈니스 파트너 및 조작에서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID&lt;span&gt; 데이터를 공유할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak에서 지원하는 보안 프로토콜에 따라 두가지 주요 유형의 ID&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 제공자와 통합을 수행할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- SAML v2&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- OpenID Connect v1.0&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;ID 브로커를 통해 사용자에게 훨씬 더 나은 경험을 제공할 수 있으며, 사용자들은 realm에 인증 및 가입하기 위해 기존 계정을 활용할 수 있습니다. 해당 사용자들이 생성되고 서드파티 제공자로부터 해당 정보를 가져오면, 해당 사용자들은 realm의 사용자가 되고 keycloak에서 제공되는 모든 기능을 사용할 수 있습니다. 또한 realm의 보안 정책을 준수합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;11. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OpenID Connect&lt;span&gt; ID 제공자 생성&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak을 실행하여 third-party-provider realm을 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2238&quot; data-origin-height=&quot;1101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pZCWm/btsMk1y4dQd/ZHyFUOKb2zuJYrwVvnQpC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pZCWm/btsMk1y4dQd/ZHyFUOKb2zuJYrwVvnQpC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pZCWm/btsMk1y4dQd/ZHyFUOKb2zuJYrwVvnQpC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpZCWm%2FbtsMk1y4dQd%2FZHyFUOKb2zuJYrwVvnQpC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2238&quot; height=&quot;1101&quot; data-origin-width=&quot;2238&quot; data-origin-height=&quot;1101&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Client ID : broker-app 으로 입력한 후 다음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1585&quot; data-origin-height=&quot;1455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI9PyE/btsMkJyBEdh/sNytaKKo2WhiyPwCoZTHGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI9PyE/btsMkJyBEdh/sNytaKKo2WhiyPwCoZTHGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI9PyE/btsMkJyBEdh/sNytaKKo2WhiyPwCoZTHGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI9PyE%2FbtsMkJyBEdh%2FsNytaKKo2WhiyPwCoZTHGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1585&quot; height=&quot;1455&quot; data-origin-width=&quot;1585&quot; data-origin-height=&quot;1455&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Access Type 설정을 Confidential로 변경하기 위해&amp;nbsp; Client authentication을 활성화&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1993&quot; data-origin-height=&quot;1095&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bM3KbJ/btsMlA18Zv7/PRMmyUvTCTcg5cD2Ct0ZZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bM3KbJ/btsMlA18Zv7/PRMmyUvTCTcg5cD2Ct0ZZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bM3KbJ/btsMlA18Zv7/PRMmyUvTCTcg5cD2Ct0ZZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbM3KbJ%2FbtsMlA18Zv7%2FPRMmyUvTCTcg5cD2Ct0ZZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1993&quot; height=&quot;1095&quot; data-origin-width=&quot;1993&quot; data-origin-height=&quot;1095&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2122&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVfgPt/btsMmKvUxIz/ieSaaMMo2cDX4dIyAhAszK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVfgPt/btsMmKvUxIz/ieSaaMMo2cDX4dIyAhAszK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVfgPt/btsMmKvUxIz/ieSaaMMo2cDX4dIyAhAszK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVfgPt%2FbtsMmKvUxIz%2FieSaaMMo2cDX4dIyAhAszK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2122&quot; height=&quot;988&quot; data-origin-width=&quot;2122&quot; data-origin-height=&quot;988&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Root URL : http://localhost:9090/realms/third-party-provider/broker/oidc/endpoint로 입력 후 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추후 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ID&lt;span&gt; 제공자를 설정할 때 클라이언트 시크릿을 사용할 것이기 때문에 반드시 적어둬야합니다.( Copy 아이콘 클릭 )&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1635&quot; data-origin-height=&quot;1084&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XnvfD/btsMml4bFKz/EeHFgmCpnMj7r7iDh0bFS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XnvfD/btsMml4bFKz/EeHFgmCpnMj7r7iDh0bFS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XnvfD/btsMml4bFKz/EeHFgmCpnMj7r7iDh0bFS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXnvfD%2FbtsMml4bFKz%2FEeHFgmCpnMj7r7iDh0bFS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1635&quot; height=&quot;1084&quot; data-origin-width=&quot;1635&quot; data-origin-height=&quot;1084&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;third-party-provider&lt;span&gt; realm에 third-party-user 사용자를 생성하고 패스워드를 설정합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1837&quot; data-origin-height=&quot;1377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l0N8J/btsMkJ6s3jP/Lr9Px9ukLdnI0wWoml8eVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l0N8J/btsMkJ6s3jP/Lr9Px9ukLdnI0wWoml8eVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l0N8J/btsMkJ6s3jP/Lr9Px9ukLdnI0wWoml8eVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl0N8J%2FbtsMkJ6s3jP%2FLr9Px9ukLdnI0wWoml8eVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1837&quot; height=&quot;1377&quot; data-origin-width=&quot;1837&quot; data-origin-height=&quot;1377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDXNPq/btsMlyQJ1dq/z8rvlK7rY7Ej0dSc6qnmSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDXNPq/btsMlyQJ1dq/z8rvlK7rY7Ej0dSc6qnmSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDXNPq/btsMlyQJ1dq/z8rvlK7rY7Ej0dSc6qnmSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDXNPq%2FbtsMlyQJ1dq%2Fz8rvlK7rY7Ej0dSc6qnmSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1714&quot; height=&quot;964&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;myrealm realm에 신규 ID 제공자를 생성합니다. 해당 작업을 수행하려면 좌측 사이드 메뉴에서&amp;nbsp; Identity Providers를 클릭합니다. Identity Providers 페이지에서 신규 제공자를 생성하거나 realm에 제공자가 아직 설정되지 않은 경우 신규 제공자를 생성하기 위해 제공자 유형을 선택하기 위한 메시지가 표시됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공자 리스트에서 OpenID Connect v1.0 을 선택하면 제공자 설정 페이지로 이동합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pJtdt/btsMnj5FS4k/KrbqW5kU53QpEOIQbslx7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pJtdt/btsMnj5FS4k/KrbqW5kU53QpEOIQbslx7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pJtdt/btsMnj5FS4k/KrbqW5kU53QpEOIQbslx7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpJtdt%2FbtsMnj5FS4k%2FKrbqW5kU53QpEOIQbslx7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1672&quot; height=&quot;817&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정페이지에는 읽기 전용 Redirect URL 필드가 있으며 해당 값은 broker-app 클라이언트의 root URL로 설정된 URL입니다. 해당 URL은 사용자가 ID 제공자를 통해 인증되면 리다이렉트되는 위치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;OpenID Connect&lt;span&gt;&amp;nbsp; Provider(OP)는 특정 엔드포인트에서 사용할 수 있는 문서를 통해 엔드포인트와 상호 작용하기 위해 사용할 수 있는 엔드포인트를 공개합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;해당 엔드포인트를 사용하면 Provider settings 페이지에 있는 대부분의 설정은 통합하고자 하는 OP의 정보를 사용해 자동으로 채워지기 떄문에 ID 제공자를 신속하게 설정할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Discovery endpoint : http://localhost:9090/realms/third-party-provider/.well-known/openid-configuration&lt;br /&gt;Display Name : My Third-Party Provider&lt;br /&gt;Client Authentication : Client secret send as post&lt;br /&gt;Client ID : broker-app&lt;br /&gt;Client&amp;nbsp;Secret&amp;nbsp;:&amp;nbsp;&amp;lt;복사한&amp;nbsp;클라이언트&amp;nbsp;시크릿&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 후 저장 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;1281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVK5h/btsMlF3li4v/5xPXoBL7kBpM1KtXOmsn3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVK5h/btsMlF3li4v/5xPXoBL7kBpM1KtXOmsn3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVK5h/btsMlF3li4v/5xPXoBL7kBpM1KtXOmsn3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVK5h%2FbtsMlF3li4v%2F5xPXoBL7kBpM1KtXOmsn3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1693&quot; height=&quot;1281&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;1281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 신규 생성된 제공자를 통해 신규 사용자가 인증을 수행하고 realm에 등록할 수 있는지 테스트해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://localhost:9090/realms/myrealm/account에 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. 사용자 데이터 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 권한의 관리자 콘솔을 통해 사용자를 관리하는 방법에 대해 알아봤습니다. 또한 realm에 사용자를 자체 등록하는 방법도 알아봤습니다. 하지만 keycloak 주요기능 중 하나는 사용자들이 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;keycloak&lt;span&gt; 계정 콘솔 서비스를 통해 자신의 계정을 관리 할 수 있도록 한느 것입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;keycloak&lt;span&gt; 계정 콘솔은 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;keycloak에서 제공하는 일반 애플리케이션이며 계정 콘솔에서 사용자들은 자신들의 계정을 관리할 수 있습니다. 또한 다음과 같은 작업을 수행할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 사용자 프로파일 업데이트&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 사용자 패스워드 업데이트&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 2차 인증 활성화&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 인증된 애플리케이션을 포함해 애플리케이션 보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 다른 세션에서 원격으로 로그아웃하는 것을 포함해 열려있는 세션보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mggyu/btsMmJD1JuR/mHsZ7bZv3O8fbTZKM21nV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mggyu/btsMmJD1JuR/mHsZ7bZv3O8fbTZKM21nV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mggyu/btsMmJD1JuR/mHsZ7bZv3O8fbTZKM21nV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMggyu%2FbtsMmJD1JuR%2FmHsZ7bZv3O8fbTZKM21nV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1764&quot; height=&quot;1150&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개인 정보 : 사용자는 이메일, 이름과 같은 프로파일 정보를 관리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 계정 보안 : 사용자는 자격증명 관리 , OTP 및 보안 기기를 각각 사용해 이중 및 멀티인증을 설정할 수 있으며 계정 활동을 추적할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션 : 사용자는 로그인, 로그아웃한 애플리케이션과 애플리케이션에 부여한 권한을 관리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정 콘솔이 일반 애플리케이션이기 떄문에 keycloak은 사용자가 계정 데이터를 인증하고 접근 할 수 있도록 realm에 account 클라이언트를 자동으로 생성합니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;realm에&lt;span&gt; 사용자가 생성된 경우 manage-account 클라이언트 역할이 자동으로 부여됩니다. 해당 역할은 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;account&lt;span&gt; 클라이언트에 포함되며 계정 콘솔에 대한 접근 여부를 제어합니다. 사용자의 계정 콘솔을 비활성화하려면 사용자의 역할 매핑을 변경해 해당 역할을 삭제해야합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;사용자는 keycloak에서 계정 콘솔을 취향에 맞게 꾸밀수 있으며 사용자의 추가 정보를 저장하고 획득한 다음 계정 콘솔에서 정보를 표시하는 방법과 관리하는 방법 또한 설정할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak console</category>
      <category>keycloak 설정</category>
      <category>keycloak 설정하기</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/100</guid>
      <comments>https://marshmello.tistory.com/100#entry100comment</comments>
      <pubDate>Tue, 11 Feb 2025 14:45:46 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 5</title>
      <link>https://marshmello.tistory.com/99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번글에서는 다양한 인가 전략(Authorization strategies) 옵션과 RBAC(Role-Based Access Control), GBAC(Group-Based Access Control), OAuth2 scopes 그리고 ABAC(Attribute-Based Access Control)과 같은 접근 제어 메커니즘을 사용해 애플리케이션 인가를 활성화하고 사용하는 방법을 작성하겠습니다. 또한 해당 옵션의 차이점과 가장 적합한 전략을 선택하는 방법에 대해서도 작성할 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 인가란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 인가 시스템은 사용자가 리소스에 접근하고 해당 리소스에 대한 작업 가능 여부를 판단합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ID 공급자로서 Keycloak은 애플리케이션에게 토큰을 발행합니다. 따라서 애플리케이션은 해당 토큰이 인가 데이터를 포함하고 있다고 예상할 수 있습니다. Keycloak에서 발생한 토큰은 사용자에 대한 정보와 사용자가 인증된 컨텍스트를 전송합니다. 컨텍스트는 사용중인 클라이언트에 대한 정보 또는 인증 프로세스 과정에서 수집된 기타 정보를 포함할 수 있습니다. 하지만 제약 사항에는 사용자가 갖고 있는 단일속성, 하나 이상의 역할 집합 또는 현재 트랜잭션과 관련된 데이터에 이르기까지 다양한 유형의 데이터가 포함될 수 있습니다. 토큰에 포함된 정보에 따라 애플리케이션은 보호된 리소스에 대한 접근을 수행할 때 토큰에 포함된 클래임을 해석하는 방법에 따라 다양한 접근 제어 메커니즘을 선택할 수 있습니다. 보호된 리소스에 적용되는 접근 제한을 구현하고 적용하기 위한 2가지 주요 인가 패턴이 존재합니다. 가장 일반적인 패턴은 일부 메타데이터 및 설정을 사용해 선언적 또는 프로그래밍적인 방식으로 애플리케이션 수준에서 접근 제어를 수행하는 것입니다. 다른 하나는 애플리케이션이 접근 허가 여부를 외부 서비스에 위임하고 해당 서비스에서 수행된 결정을 기반으로 접근 제어를 수행할 수도 있습니다. 그 해당 패턴은 통합 인가라고 합니다. 2개의 패턴은 상호 배타적이지 않으며, 애플리케이션에 2개의 패턴을 사용할 수 있습니다. Keycloak은 매우 유연하며 다양한 접근 제어 메커니즘을 사용해 애플리케이션 수준에서 리소스를 보호하기 위해 필요한 모든 정보를 교환할 수 있습니다. 또한 접근 제어를 관리하고 수행하기 위해 다양한 인가 패턴 중에서 해당 접근 제어 매커니즘을 선택할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. RBAC (Role-Based Access Control) 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 많이 사용되는 접근 제어 메커니즘 중 하나인 RBAC를 통해 사용자에게 부여된 역할에 따라 리소스를 보호할 수 있습니다. Keycloak에는 역할 관리뿐만 아니라 토큰을 사용해 애플리케이션에 역할을 전파할 수 있는 기능을 내장하고 있습니다. 역할은 일반적으로 조직 또는 애플리케이션 컨텍스트에서 사용자가 갖는 역할을 나타냅니다. 예를 들어 사용자에게 애플리케이션의 모든 리소스에 접근하고 작업을 수행할 수 있는 권한을 가진 관리자 역할을 부여할 수 있습니다. 또는 하위 조직과 관련된 자원에 접근하고 작업을 수행할 수 있는 권한을 가진 people-manager 역할을 부여할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 realm 및 client와 같은 두 종류의 역할을 갖고 있습니다. realm 레벨에서 정의된 역할을 realm roles라고 합니다. 해당 역할은 일반적으로 realm에 공존하는 다양한 클라이언트에 관계없이 조직 내에서 사용자의 역할을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 client roles는 클라이언트에 따라 다르며, 역할의 의미는 클라이언트가 사용하는 시맨틱에 따라 달라집니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할은 realm 또는 클라이언트 역할로 정의하는 시점에 대한 결정은 역할이 갖고 있는 범위에 따라 달라집니다. 해당 범위가 동일한 의미를 유지하면서 realm의 여러 클라이언트에 포함돼 있는 경우 realm 역할은 유효합니다. 그에 반해 특정 클라이언트만 역할을 수행해야 하는 경우 클라이언트 역할을 사용하는 것이 더 적절합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할을 사용하는 경우 무분별한 역할 사용을 피해야합니다. 즉 시스템에 과도하게 많은 역할이 있는 경우 관리하기 어렵게 될 수 있습니다. 해당 문제를 방지하기위한 한가지 방법은 역할이 관련된 범위와 애플리케이션에서 역할과 관련된 권한의 세분성을 고려해 매우 신중하게 역할을 생성하는 것입니다. 역할의 범위가 세분화될수록 시스템에는 더 많은 역할이 존재합니다. 경험에 비춰볼때, 세분화된 인가를 위해 역할을 사용하는것을 권장하지 않습니다. 역할은 인가를 위해 사용하면 안됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서는 그룹에 역할을 부여할 수 있습니다. 그룹 멤버들은 해당 그룹의 역할을 자동으로 부여받기 때문에 유용한 기능입니다. 해당 기능을 활용하면 특정 권한을 개별 사용자에게 각각 부여하지 않아도 되기 때문에 역할 관리 이슈를 해결할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 또한 다른 역할을 연결하는 특별한 유형의 복합 역할 개념을 제공합니다. 복합 역할을 부여받은 사용자는 체인에 포함된 모든 역할이 자동으로 부여됩니다. 해당 기능은 Keycloak의 강력하고 고유한 기능이지만 여러 복합 역할을 연결하는 경우 발생할 수 있는 성능 문제와 시스템의 역할 확산 및 권한의 세분화로 인한 관리 효율성 문제를 예방하기 위해 신중하게 사용해야합니다. 사용자에게 다양한 역할을 부여해야 하는 경우 그룹을 사용해 해당 그룹에 역할을 할당하는 것을 권장합니다. 그룹을 사용하는 것이 복합 역할을 사용하는 거보다 더 적절한 권한 모델입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 역할을 모델링하는 방법은 Keycloak에서 발행하는 토큰의 크기에도 영향을줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰에는 클라이언트가 로컬에서 또는 해당 토큰을 사용하는 다른 서비스에 접근할 때 사용자에게 권한을 부여하는 데 필요한 최소한의 역할 집합이 포함되는 것이 가장 적절합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. GBAC (Group-Based Access Control) 활용&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak에서 realm 그룹을 관리할 수 있으며 사용자는 조직 내의 특정 부서에 포함될 수 있고, 관리 작업을 수행할 수 있는 권한을 가진 특정 사용자 그룹을 설정하는 것과 같이 애플리케이션에서 사용자의 역할에 따라 그룹화할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 그룹과 역할은 상호 교환해서 사용할 수 있는데, 이러한 특성은 권한 모델을 정의할 때 약간의 혼란을 야기합니다. Keycloak은 그룹과 역할을 명확히 구분하며, 역할과 달리 그룹은 사용자를 구성하고 그룹과 관련된 역할에 따라 권한을 부여합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할을 그룹에 할당할 수 있기 때문에 Keycloak을 사용하면 realm의 각 개별 사용자에 대한 역할을 부여 및 취소하지 않고도 다양한 사용자의 역할을 훨씬 쉽게 관리 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak의 그룹은 계층 구조이며, 토큰이 발행되면 그룹의 경로를 보고 계층 구조를 순회합니다. 예를 들어 인사팀 그룹이 있고, 해당 그룹의 하위 그룹을 매니저 그룹이 있을 수 있습니다. Keycloak이 그룹에 대한 정보를 토큰에 포함할 경우 해당 정보는 /human resource/manager형식으로 저장됩니다. 해당 정보는 객체(사용자)가 그룹의 멤버인 서버에서 발급된 모든 토큰에 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할과 달리 그룹 정보는 토큰에 자동으로 포함되지 않습니다. 이런 경우 특정 프로토콜 매퍼를 클라이언트와 연결해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 그룹 멤버십을 토큰에 매핑하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할과는 달리 자동으로 그룹 정보를 토큰에 포함시키는 디폴트 프로토콜 매퍼가 존재하지 않습니다.해당 작업을 수행하기 위해 프로토콜 매퍼를 클라이언트에 생성해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령프롬프트 창을 열어 keycloak을 실행합니다.[Keycloak 시작하기 4 &lt;a href=&quot;https://marshmello.tistory.com/97&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://marshmello.tistory.com/97&lt;/a&gt; 참조]&lt;/p&gt;
&lt;pre id=&quot;code_1739237698597&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\keycloak-26.0.7\keycloak-26.0.7
bin\kc.bat start-dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clients 메뉴 &amp;gt; Create client 선택 후 myclient 클라이언트를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;649&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcZXfc/btsMdHNwqxB/ur3KKrCfj7DrT8lCsQh3C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcZXfc/btsMdHNwqxB/ur3KKrCfj7DrT8lCsQh3C1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcZXfc/btsMdHNwqxB/ur3KKrCfj7DrT8lCsQh3C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcZXfc%2FbtsMdHNwqxB%2Fur3KKrCfj7DrT8lCsQh3C1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;683&quot; height=&quot;410&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;649&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Client ID를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;myclient&lt;span&gt; 로 입력 후 Next&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;753&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgZ68v/btsMexXyXlD/a5ZQDANUMhEdRKpASaS6i1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgZ68v/btsMexXyXlD/a5ZQDANUMhEdRKpASaS6i1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgZ68v/btsMexXyXlD/a5ZQDANUMhEdRKpASaS6i1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgZ68v%2FbtsMexXyXlD%2Fa5ZQDANUMhEdRKpASaS6i1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;498&quot; height=&quot;391&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;753&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1465&quot; data-origin-height=&quot;1212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jjl7x/btsMdHfIlzD/yla4P8AN9NSNVH1LSbOQx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jjl7x/btsMdHfIlzD/yla4P8AN9NSNVH1LSbOQx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jjl7x/btsMdHfIlzD/yla4P8AN9NSNVH1LSbOQx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJjl7x%2FbtsMdHfIlzD%2Fyla4P8AN9NSNVH1LSbOQx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;548&quot; height=&quot;453&quot; data-origin-width=&quot;1465&quot; data-origin-height=&quot;1212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Save 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be4DEz/btsMeu7KSaR/0UEZCpKktQ2tnNGRTrklk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be4DEz/btsMeu7KSaR/0UEZCpKktQ2tnNGRTrklk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be4DEz/btsMeu7KSaR/0UEZCpKktQ2tnNGRTrklk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe4DEz%2FbtsMeu7KSaR%2F0UEZCpKktQ2tnNGRTrklk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;520&quot; height=&quot;597&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Users 메뉴 &amp;gt; Create new user 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pSG7V/btsMcdUeUmL/Ib2NidTBmPnDoGnzX9nLKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pSG7V/btsMcdUeUmL/Ib2NidTBmPnDoGnzX9nLKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pSG7V/btsMcdUeUmL/Ib2NidTBmPnDoGnzX9nLKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpSG7V%2FbtsMcdUeUmL%2FIb2NidTBmPnDoGnzX9nLKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1632&quot; height=&quot;902&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;902&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;username을 test01로 입력 후 사용자 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1058&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvYHdm/btsMeaVYSF7/acXpQC5pvmBEvTKPMLhqT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvYHdm/btsMeaVYSF7/acXpQC5pvmBEvTKPMLhqT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvYHdm/btsMeaVYSF7/acXpQC5pvmBEvTKPMLhqT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvYHdm%2FbtsMeaVYSF7%2FacXpQC5pvmBEvTKPMLhqT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;577&quot; height=&quot;512&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1058&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clients 메뉴 &amp;gt; Client scopes 탭 &amp;gt; 생성한 clientid-dedicated 이름으로 된 client를 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EXuIX/btsMcRwd4A5/5LbffOmDUYyHBPzToebTOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EXuIX/btsMcRwd4A5/5LbffOmDUYyHBPzToebTOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EXuIX/btsMcRwd4A5/5LbffOmDUYyHBPzToebTOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEXuIX%2FbtsMcRwd4A5%2F5LbffOmDUYyHBPzToebTOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;691&quot; height=&quot;361&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Add predefined mapper 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;695&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqcrFA/btsMesPCJ1Q/xKFGFmkycQlDt9bRNa4qDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqcrFA/btsMesPCJ1Q/xKFGFmkycQlDt9bRNa4qDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqcrFA/btsMesPCJ1Q/xKFGFmkycQlDt9bRNa4qDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqcrFA%2FbtsMesPCJ1Q%2FxKFGFmkycQlDt9bRNa4qDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;515&quot; height=&quot;297&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;695&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;groups 선택 후 Add 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;1212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oax8P/btsMcSWiE5G/9P6bwdghgRYbVHBuDfBRSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oax8P/btsMcSWiE5G/9P6bwdghgRYbVHBuDfBRSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oax8P/btsMcSWiE5G/9P6bwdghgRYbVHBuDfBRSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOax8P%2FbtsMcSWiE5G%2F9P6bwdghgRYbVHBuDfBRSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;654&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;1212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Groups 메뉴 &amp;gt; Create group 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1606&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mEVQt/btsMcJSKqCh/Au3xS0OdLfiUCcc3Y2PkDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mEVQt/btsMcJSKqCh/Au3xS0OdLfiUCcc3Y2PkDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mEVQt/btsMcJSKqCh/Au3xS0OdLfiUCcc3Y2PkDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmEVQt%2FbtsMcJSKqCh%2FAu3xS0OdLfiUCcc3Y2PkDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;580&quot; height=&quot;292&quot; data-origin-width=&quot;1606&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그룹명에 Project Management Office 입력 후 Create 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ep4ceg/btsMcPrMrDG/zKg1975ZfLj65vH2RN9TTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ep4ceg/btsMcPrMrDG/zKg1975ZfLj65vH2RN9TTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ep4ceg/btsMcPrMrDG/zKg1975ZfLj65vH2RN9TTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fep4ceg%2FbtsMcPrMrDG%2FzKg1975ZfLj65vH2RN9TTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;254&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Users 메뉴 &amp;gt; test01 버튼을 클릭하여 test01 사용자 상세보기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btsneW/btsMcIM7XO5/4OciLpxphT05ODy1WT01Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btsneW/btsMcIM7XO5/4OciLpxphT05ODy1WT01Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btsneW/btsMcIM7XO5/4OciLpxphT05ODy1WT01Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtsneW%2FbtsMcIM7XO5%2F4OciLpxphT05ODy1WT01Kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;653&quot; height=&quot;420&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Users 메뉴 &amp;gt; Groups 탭 &amp;gt; Join Group 버튼 클릭&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zHJHN/btsMe2XeqXb/OSeYRrymGaxDudlzVexwn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zHJHN/btsMe2XeqXb/OSeYRrymGaxDudlzVexwn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zHJHN/btsMe2XeqXb/OSeYRrymGaxDudlzVexwn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzHJHN%2FbtsMe2XeqXb%2FOSeYRrymGaxDudlzVexwn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;657&quot; height=&quot;256&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Project Management Office 선택 후 Join 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJnndj/btsMebAx39J/5UAt2TQzwT1LlLoRhgAyfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJnndj/btsMebAx39J/5UAt2TQzwT1LlLoRhgAyfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJnndj/btsMebAx39J/5UAt2TQzwT1LlLoRhgAyfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJnndj%2FbtsMebAx39J%2F5UAt2TQzwT1LlLoRhgAyfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;517&quot; height=&quot;367&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 test01은 Project Management Office 그룹의 멤버입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. OAuth2 범위 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Keycloak은 OAuth2 인가 서버입니다. OAuth2 자체에는 클라이언트와 리소스 서버의 두가지 주요 애플리케이션 유형이 있습니다. 클라이언트에게 접근 토큰을 발행하고 해당 토큰은 사용자 권한을 기반으로 하는 범위 집합을 제한하는 방식으로 사용자 역할을 수행할 수 있게 해줍니다. 또한 리소스 서버는 접근 토큰을 활용해 사용자가 부여한 범위에 따라 클라이언트가 리소스 서버의 보호된 리소스에 대한 접근 여부를 결정하기 위해 접근 토큰을 검증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 OAuth2 범위를 사용한 권한 부여는 전적으로 사용자 동의를 기반으로 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서드파티를 사용자의 API와 통합시키고자 할 때 가장 좋은 전력입니다. 따라서 서드파티 애플리케이션의 리소스에 접근 여부에 대한 결정을 사용자에게 위임 할 수 있습니다. 해당 전략에서 중요한 점은 리소스 서버에서 일반리소스가 아닌 사용자 정보를 보호하는 것입니다. OAuth2 범위를 사용하는 것과 지금까지 살펴본 여러 가지 인가 전략 사이에는 주로 시스템을 보호하는 엔티티 측면에서 근본적인 차이가 있습니다. 예를 들어 RBAC를 사용하는 경우 사용자로부터 시스템을 보호하는 반면, OAuth2 범위를 사용하면 클라이언트로부터 시스템을 보호할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 클라이언트는 사용자를 대신해 일부 작업을 수행하거나 리솟에 접근할 수 있으며, 일반적인 위임 사용사례는 OAuth2를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak이 주로 기업환경에서 사용되기 때문에 기본적으로 Keycloak의 클라이언트는 사용자 동의를 요청하지 않도록 설정돼 있습니다. 위임 활용 사례와 다른점은 클라이언트가 엔터프라이즈 경계 내에 있고 접근해야 하는 리소스가 사용자의 동의가 필요하지 않지만 시스템 관리자 부여한 접근 권한을 사용한다는 것입니다. 또한 클라이언트는 역할, 그룹 또는 사용자와 관련된 특정 속성에 따라 접근 범위가 정의되는 사용자를 인증하는 것에 더 초점을 둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. ABAC (Attribute-Based Access Control) 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 Keycloak을 통해 인증하는 경우 서버에서 발급한 토큰에는 인증 컨텍스트에 대한 중요한 정보가 포함됩니다.토큰에는 인증된 사용자 및 토큰이 발급된 클라이언트에 대한 정보와 인증 프로세스 수행 중에 수집할 수 있는 다양한 정보가 포함됩니다. 따라서 토큰이 제공하는 모든 정보를 사용해 애플리케이션에 대한 접근 권한을 인가하기 위해 사용할 수 있습니다. 해당 정보들은 토큰에 매핑된 클레임 (Claims)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ABAC은 인증 컨텍스트에 대한 정보뿐만 아니라 ID(토큰으로 표현됨)와 관련된 다양한 속성들을 사용해 리소스에 대한 접근 권한을 수행합니다. ABAC은 가장 유연한 접근 제어 메커니즘이며, 따라서 세분화된 인가를 지원합니다. 토큰 기반 인가와 함께 Keycloak을 사용하는 애플리케이션에서는 리소스를 보호하기 위해 손쉽게 ABAC를 활성화 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰 기반 권한 인가는 토큰을 검사하고 해당 정보를 사용해 접근 권한 부여 여부를 결정합니다.해당 정보는 속성 또는 클레임 집합으로 표시되며 접근 권한을 활성화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션에서 접근 권한을 적용하기 위해 역할을 사용하는 방법에대해 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할은 특정 클레임 집합을 사용해 토큰에 매핑됩니다. 역할을 사용해 접근 권한을 수행하려면 애플리케이션에서 이러한 클레임을 사용해 사용자에게 부여된 역할을 확인한 다음 특정 리소스에 접근 권한을 부여해야하는지 여부를 결정해야합니다. 역할을 사용해 접근 권한을 적용하려면 어떤 역할이 사용자에게 부여됐는지 확인하기 위해 애플리케이션은 해당 클레임만 확인하면 됩니다. 그리고 특정 리소스에 접근 허용 여부를 결정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 클레임은 애플리케이션이 모든 클레임을 사용해 접근 권한을 적용할 수 있는 토큰내의 다른 클레임과 동일합니다. 각 클라이언트에서 토큰에 저장되는 클레임 및 표명을 조정할 수 있습니다. 해당 작업을 수행하기 위해 Keycloak은 프로토콜 매퍼라는 기능을 제공합니다. Keycloak을 사용하면 원하는 정보를 토큰에 매핑해 애플리케이션 수준에서 접근 권한을 적용할 수 있습니다. ABAC은 다중접근제어 메커니즘을 지원할 만큼 충분히 유연하지만 구현 및 관리가 쉽지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 통합 Keycloak 인가 서버 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 특정 접근 제어 메커니즘에 의존하는 인증 전략을 살펴봤습니다. ABAC을 제외하고 해당 전략은 사용자에 대한 특정 데이터 집합에 의존해 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;애플리케이션&lt;/span&gt;에 접근 권한을 적용합니다. 또한 해당 전략은 애플리케이션과 긴밀하게 연동돼 보안 요구 사항을 변경하면 애플리케이션 코드를 변경해야합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1739251443709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(User.hasRole(&quot;pm&quot;) ){
	//pm 권한이 있는 사람에 대한 소스코드
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 pm권한이 부여된 사용자만 보호된 리소스에 접근할 수 있는 RBAC을 사용해 간단한 검증을 수행합니다. 요구 사항이 변경돼 동일한 리소스에 대한 접근 권한을 특정 사용자에게도 부여해야 한다면 어떻게 될까? 또한 다른 역할이 부여된 사용자에게 해당 리소스에 대한 접근 권한을 부여할 수 있을까? 또는 ABAC을 활용해 리소스에 접근하는 컨텍스트에 대한 다양한 정보를 확인 할 수 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소한 코드를 변경하고 애플리케이션을 다시 배포해야 하며, 변경 사항이 프로덕션에 사용할 준비가 됐는지 확인하기 위해 지속적인 통합 및 전달 프로세스를 수행해야합니다. 통합 인가는 외부 인가 서비스를 사용해 애플리케이션의 접근 관리 및 의사 결정을 외부화합니다. 해당 서비스는 애플리케이션을 접근 제어 메커니즘과 연동하지 않고도 다중 제어 메커니즘을 사용할 수 잇도록 해주며 애플리케이션의 다양한 보호 리소스를 참조하기 위해 사용되는 동일한 시맨틱을 사용해 접근 권한을 활성화합니다&lt;/p&gt;
&lt;pre id=&quot;code_1739251764354&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(User.canAccess(&quot;PM Resource&quot;)){
....
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 소스는 동일한 접근 검사를 제공하는 코드입니다. 이 코드는 특정 접근 제어 메커니즘에 대한 참조는 존재하지 않습니다. 접근제어는 사용자가 보호를 수행하는 리소스로 구성됩니다. 그리고 애플리케이션은 외부 인가 서비스에서 부여한 권한만 고려합니다. PM Resource에 접근할 수 있는 방법을 변경하면 애플리케이션 코드에 영향을 미치지 않지만 인가 서비스를 통해 해당 리소스에 대한 접근을 제어하는 정책은 변경해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 Authorization Service 기능을 통해 통합 인가 서비스의 역할을 수행할 수 있습니다. 해당 기능은 다양한 접근 제어 메커니즘을 포함하는 정책 집합으로 구성됩니다. 접근 제어 메커니즘은 보호 리소스와 연동됩니다. 모든 작업은 Keycloak 관리 콘솔과 REST API를 통해 관리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak 인가 서비스 기능은 애플리케이션에서 세분화된 인가를 수행하기 위해 ABAC를 활용합니다. 기본적으로 리소스를 보호할때 다양한 인가 전략을 쉽게 지원하기 위해 해당 정책을 통합할 수 있는 가능성과 함께 다양한 접근 제어 메커니즘을 나타내는 해당 정책 집합이 즉시 제공됩니다. 또한 Keycloak 인가 서비스 기능은 특정 작업 및 보호하는 리소스와 관련된 속성에 대한 접근 권한을 제어합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통합 인가 서버의 일반적인 이슈는 접근 결정을 수행하기 위한 추가적인 통신이 필요하다는 것입니다. 토큰 기반 인가를 사용하면 Keycloak 인가 서비스 기능은 서버에서 부여한 모든 권한을 가진 토큰을 발급해 해당 이슈를 해결할 수 있습니다. 따라서 해당 토큰을 사용하는 애플리케이션은 토큰을 내부적으로 검증하는 것 외에는 추가적인 네트워크 요청을 수행할 필요가 없습니다. 또한 필요한 경우 신규 권한을 획득할 수 있는 제한된 권한 집합이 토큰에 발급되는 증분 인가도 지원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번글에서는 통합 인가 및 Keycloak 인가 서비스가 통합 인가 서버의 역할을 수행하는 것을 살펴보았습니다. 또한 토큰 기반 인가를 활용하면 애플리케이션에 세분화된 Keycloak 인가 서비스를 사용할 수 있다는 점을 작성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음글에서는 Keycloak 설정 및 관리 방법을 작성하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak group</category>
      <category>keycloak roles</category>
      <category>keycloak 권한</category>
      <category>keycloak 권한설정</category>
      <category>keycloak 역할</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/99</guid>
      <comments>https://marshmello.tistory.com/99#entry99comment</comments>
      <pubDate>Tue, 11 Feb 2025 10:31:47 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 4</title>
      <link>https://marshmello.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번글에서는 다양한 유형의 애플리케이션을 보호하기 위한 보안 원리와 베스트 프랙티스에 대해 작성하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹, 모바일 및 네이티브 애플리케이션을 보호하는 방법과 REST API, gRPC, Websocket 및 기타유형의 서비스를 포함한 다양한 유형의 서비스를 보호하기 위해 bearer 토큰을 이용하는 방법을 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 내부 및 외부 애플리케이션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션을 보호할대 가장 먼저 고려해야할 사항은 애플리케이션이 내부 애플리케이션인지 혹은 외부 애플리케이션인지 확인하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 애플리케이션은 기업이 보유한 애플리케이션입니다. 애플리케이션을 누가 개발했는지 또는 호스팅 방법은 중요하지 않습니다. 애플리케이션은 상용 애플리케이션, SaaS(Software as a Service)에서 호스팅되는 애플리케이션이 될 수도 있지만 해당 애플리케이션도 내부 애플리케이션으로 고려해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 애플리케이션의 경우 해당 애플리케이션은 신뢰할 수 있고, Keycloak에 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;애플리케이션&lt;/span&gt;을 등록한 관리자가 사용자를 대신해 접근 권한을 사전 승인할 수 있으므로 사용를 인증할 때 사용자에게 애플리케이션에 대한 접근 권한을 부여하도록 요청할 필요가 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;관리자 창을 열어 keycloak 관리자 모드를 실행합니다. (keycloak 설정 방법은 Keycloak 시작하기 3 글 참고)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739147458823&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\keycloak-26.0.7\keycloak-26.0.7
bin\kc.bat start-dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp88xa/btsMaU8gWpZ/BEAMpW7TLaolhWpJJVTLVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp88xa/btsMaU8gWpZ/BEAMpW7TLaolhWpJJVTLVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp88xa/btsMaU8gWpZ/BEAMpW7TLaolhWpJJVTLVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp88xa%2FbtsMaU8gWpZ%2FBEAMpW7TLaolhWpJJVTLVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2542&quot; height=&quot;1321&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Consent required를 활성화면 사용자에게 접근 권한을 승인받아야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZbNoI/btsMdsomNzD/qNTSyAxmDkFBrvFkV5K9UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZbNoI/btsMdsomNzD/qNTSyAxmDkFBrvFkV5K9UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZbNoI/btsMdsomNzD/qNTSyAxmDkFBrvFkV5K9UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZbNoI%2FbtsMdsomNzD%2FqNTSyAxmDkFBrvFkV5K9UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;443&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;656&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 API를 호출하는 SPA(Single Page Application) 유형 애플리케이션인 경우 고려해야할 2가지 추가 옵션이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션이 외부 REST API를 직접 호출하는지 , 아니면 애플리케이션과 함께 호스팅 되는 전용 REST API를 호출하는지 입니다. 위의 내용을 기반으로 다음 내용 중에서 보호하려는 애플리케이션의 아키텍처에 해당되는 내용을 결정해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Server side :&lt;/b&gt; 웹 애플리케이션이 웹 서버 내부 또는 애플리케이션 서버 내에서 실행 중인 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- SPA with dedicated REST API :&lt;/b&gt; 애플리케이션이 브라우저에서 실행되거나 동일 도메인에서 전용 REST API만 호출하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- SPA with intermediary API :&lt;/b&gt; 애플리케이션이 브라우저에서 실행되거나 애플리케이션과 동일한 도메인에서 호스팅되는 중개 API를 통해 외부 REST API를 호출하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- SPA with external API :&lt;/b&gt; 애플리케이션이 브라우저에서 실행되거나 다른 도메인에서 호스팅되는 API만 호출하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 다양한 웹 애플리케이션 아키텍쳐에 대한 세부 사항을 살펴보기 전에 모든 아키텍처에서 공통되는 부분이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 가장 중요한 것은 PKCE(Proof Key for Code Exchange) 확장과 함께 인가 코드 흐름(Authorization Code flow)을 사용해 웹 애플리케이션을 보호해야 한다는 것입니다. PKCE 확장 기능은 인가 요청을 전송한 애플리케이션에 인가 코드를 바인딩하는 OAuth2.0 확장기능입니다.해당 확장 기능은 유출될 경우 인가코드가 남용되는 것을 방지합니다. 만약 라이브러리를 사용하지 않는 경우 OAuth2.0 및 OpenID Connect를 활용하기 위한 관련 사양을 직접 참조해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 사용하기 위해 기존 애플리케이션을 포팅하는 경우, 기존 애플리케이션의 로그인 페이지를 유지한 다음 리소스 소유자 암호 자격증명 부여를 사용해 토큰의 사용자 이름과 패스워드를 교환하는게 효율적으로 보일 수 있습니다. 해당방법은 애플리케이션을 LDAP서버와 통합하는 것과 유사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 해당 방법은 사용하면 안됩니다. 애플리케이션에서 사용자 자격증명을 수집하는 것은 단일 애플리케이션의 보안 이 손상된 경우 공격자는 사용자가 접근 할 수 있는 모든 애플리케이션에 접근할 수 있음을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자들은 보통 패스워드를 재사용하기 때문에 Keycloak으로 보호되지 않는 애플리케이션이 포함됩니다. 또한 이중 인증과 같은 강력한 인증을 적용할 수 있는 기능도 없습니다. 결과적으로 해당 방법을 사용하면 SSO 및 소셜 로그인과 같은 Keycloak의 장점을 사용할 수 없게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 페이지를 기존 프로그램 내에 유지하는 대신 Keycloak 로그인 페이지를 iframe 방식으로 애플리케이션을 포함시키는 방법도 생각했을 수 있습니다. 하지만 이또한 반드시 피해야하는 설정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션에 포함된 로그인 페이지를 사용하면 애플리케이션의 취약점의 영향을 받을 수 있고, 잠재적으로 공격자가 사용자 이름과 패스워드에 대한 접근 권한을 획득 할 수 있습니다. 로그인 페이지가 iframe내에서 렌더링되기 때문에 사용자는 로그인 페이지의 출처를 확인하기 어려우며 사용자는 애플리케이션에 패스워드를 직접 입력하는 것을 신뢰하지 않을 수 있습니다. 마지막으로 여러 사이트에서 서드파티 쿠키를 사용자 추적에 활용하면서 브라우저는 점점더 서브파티 쿠키를 차단하는 상황이며, 이로 인해 Keycloak 로그인 페이지에 작동하는데 필요한 쿠키에 접근하지 못 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면, 애플리케이션이 인증을 위해 (특히 SSO환경에서) 사용자를 신뢰할 수 있는 ID 제공자로 리다이렉티해야한다는 것입니다. 또한 해당 환경은 최근 폭넓게 사용되는 패턴이기 때문에 대부분의 사용자가 이미 익숙할 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;757&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFj6Ay/btsMbY2Z0Dh/xuDROWXANNwqbcukrn9aMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFj6Ay/btsMbY2Z0Dh/xuDROWXANNwqbcukrn9aMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFj6Ay/btsMbY2Z0Dh/xuDROWXANNwqbcukrn9aMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFj6Ay%2FbtsMbY2Z0Dh%2FxuDROWXANNwqbcukrn9aMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;553&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;757&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션 자체에 내장돼 있지 않은 로그인 페이지 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp; 서버 사이드 웹 애플리케이션 보호&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 사용해 서버 사이드 웹&amp;nbsp; 애플리케이션을 보호하는 경우 Keycloak에 보안 클라이언트(Confidencial Client)를 등록해야합니다. 보안 클라이언트를 사용하면 공격자가 유출된 인가 코드를 악용할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PKCE확장은 여러가지 유형의 공격에 대한 보호를 제공하기 때문에 해당 확장을 활용하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 클라이언트에 적절한 Redirect URIs를 설정해야합니다. 그렇지 않은 경우 오픈 리다이렉트 취약점이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 스팸 공격의 경우, 오픈 리다이렉트를 사용해 사용자가 신뢰하는 사이트를 클릭하고 있는 것으로 속일 수 있습니다. 클라이언트에 대한 적절한 redirect URL를 설정하지 않으면 Keycloak은 사용자를 공격자가 제공한 사이트로 리다이렉트하게 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 사이드 웹 애플리케이션의 HTTP 세션 수립에는 일반적으로 ID 토큰만 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 사이드 웹 애플리케이션은 또한 사용자 컨텍스트 환경에서 외부 REST API를 호출하는 경우 접근 토큰을 활용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 애플리케이션은 Keycloak의 ID 토큰을 획득하기 위해 인가 코드흐름을 활용합니다. 해당 ID토큰은 인증된 HTTP 세션을 수립하기 위해 사용됩니다. 서버 사이드 애플리케이션인 경우 OpenID Connect를 사용하는 대신 SAML2.0을 사용할수도 있습니다. 일반적으로 OpenID Connect를 사용하는 것이 편하기 때문에 사용중인 애플리케이션이 이미 SAML2.0을 지원하는 것이 아니라면 OpenID Connect를 사용하는 것을 권장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 전용 REST API가 포함된 SPA&amp;nbsp; 보호&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 도메인에 전용 REST API가 포함된 SPA는 서버사이드 웹 애플리케이션과 동일한 방식으로 Keycloak을 사용해 보호됩니다. 애플리케이션은 REST API를 포함하기 때문에 최고 수준의 보안을 위해 보안 클라이언트의 인가 코드 흐름을 활용해야 하며, 클라이언트 사이드에서 전용 REST API로 전송되는 API 요청을 보호하기 위해 HTTP 세션을 사용해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 전용 REST API로 전송되는 요청은 HTTP 세션 쿠키를 포함합니다. 요약하면 애플리케이션은 권한 부여 코드 흐름을 활용해 Keycloak에 ID 토큰 을 획득합니다. 해당 토큰은 인증된 HTTP 세션을 수립하기 위해 사용되며, 이를 통해 SPA는 웹 서버에서 제공되는 REST API를 안전하게 호출할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 중계 REST API를 사용하는 SPA 보호&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 외부 REST API를 호출하는 가장 안전한 방법은 SPA와 동일한 도메인에서 호스팅되는 중계 API 사용하는 것입니다. 중계 API를 사용하면 보안 클라이언트를 활용할 수 있고 브라우저에서 직접 토큰에 접근 할 수 없기 때문에 토큰이 유출될 위험이 줄어듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 유형의 SPA를 보통 프론트엔드 패턴용 백엔드라고 합니다. 해당 SPA는 높은 보안 수준을 가졌으며, SPA의 호환성을 높이고 쉽게 개발 할 수 있습니다. 애플리케이션이 외부 API를 직접 처리할 필요가 없고 프론트엔드 SPA 서비스를 제공하기 위한 목적으로 구축한 전용 REST API가 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 기본적으로 브라우저의 CORS(Cross-Origin Resource Sharing)가 활성화 되어 있기 떄문에 SPA가 다른 도메인에서 제공하는 REST API를 호출하는 것을 브라우저에서 허용되지 않습니다. CORS를 사용하면 REST API가 브라우저에서 다른 오리진의 요청을 허용하는 특정 HTTP 헤더를 응답 할 수 있습니다.해당 SPA는 동일한 도메인의 중계 REST API를 통해 요청을 생성하기 때문에 CORS를 처리할 필요가 없습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 애플리케이션은 인증 코드 흐름을 활용해 Keycloak에서 ID 토큰을 획득하며, 해당 ID 토큰은 인증된 HTTP 세션을 수립하기 위해 사용됩니다. 해당 HTTP 세션을 통해 SPA는 안전하게 웹 서버를 호출하고, 웹 서버는 해당 요청을 외부 REST API로 프록시합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 외부 REST API가 포함된 SPA 보호&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 통해 SPA를 보호하는 가장 간단한 방법은 Keycloak에 등록된 공용 클라이언트를 사용해 SPA 자체에서 직접 인가 코드 흐름을 수행하는 것입니다. 해당 접근 방법은 토큰(리프레시 토큰 포함)이 브라우저에서 직접 노출되기 떄문에 약간 보안 수준이 낮은 방법입니다. 금융 애플리케이션과 같이 민감한 애플리케이션의 경우 해당 접근 방식을 사용하는 것을 권장하지 않습니다. 하지만 다음과 같이 해당 접근 방법에 적절한 수준의 보안을 제공하기 위해 활용할 수 있는 여러가지 기법이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리프레시 토큰의 만료 시간을 짧게 설정한다. 해당 설정은 Keycloak의 클라이언트 세션 타임아웃에서 설정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정을 수행하면 클라이언트에게 30분 동안 유효한 리프레시 토큰을 제공하고 반면 SSO 세션은 며칠동안 유효하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리프레시 토큰을 갱신한다. Keycloak에서 realm의 Revoke Refresh Token을 활성화해 이전에 사용한 리프레스 토큰을 폐기합니다. 폐기한 리프레시 토큰을 사용하는 경우 세션은 무효화된다.따라서 SPA와 공격자가 리프레시 토큰을 사용하려고 하면 유출된 리프레시 토큰이 즉시 폐기된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- PKCE 확장을 사용한다. 공용 클라이언트의 경우 PKCE 확장을 사용해야 한다. 그렇지 않으면 공격자는 유출된 인가 코드를 통해 토큰을 획득할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 토큰을 윈도우 상태 또는 HTTP5 스토리지 세션에 저장하고 window.sessionStorage.accessToken과 같이 쉽게 유추할 수 있는 키를 사용하지 않아야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- OWASP(Open Web Application&amp;nbsp; Security Project)의 베스트 프랙티스를 활용해 XSS(Cross-site scripting) 및 여러가지 공격으로 부터 SPA를 보호한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션에서 서드파티 스크립트를 사용하는 경우 주의를 기울여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 적절한 수준의 보안을 설정하는 것은 사용자가 스스로 결정해야하는 사안입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰이 유출될 위험이 없고 SPA의 보안이 적절하다고 생각된다면 위 접근 방식을 사용해 더욱 효율적으로 애플리케이션유지보수 비용도 절감 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션을 보호하는 베스트 프랙티스는 PKCE 확장을 포함하는 인가 코드흐름을 통해 Keycloak 로그인 페이지로 리다이렉트하는 것을 알 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 네이티브 및 모바일 애플리케이션 보호&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak을 통해 웹 애플리케이션을 보호하는 것이 네이티브 또는 모바일 애플리케이션을 보호하는 것보다 더 간단합니다. Keycloak 로그인 페이지는 기본적으로 웹 애플리케이션이며 사용자가 이미 브라우저를 사용하는 경우 다른 웹 애플리케이션으로 리다이렉트하는 것이 더 적절합니다. 애플리케이션 자체에서 로그인 페이지를 구현해 사용자 이름과 패스워드를 수집한 다음 OAuth2.0 리소스 소유자 패스워드 자격증명 부여를 활용해 토큰을 획득하고자 할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 방법은 권장하지 않습니다. 애플리케이션은 사용자 자격증명에 직접 접근해서는 안되며 해당 접근 방법은 또한 Keycloak에서 제공하는 다양한 기능을 활용하지 않음을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이티브 및 모바일 애플리케이션을 보호하려면 PKCE 확장이 포함된 인가 코드 흐름을 사용해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 접근 방법은 좀 더 높은 보안을 제공함과 동시에 Keycloak이 가진 장점을 최대한 활용할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실상 네이티브 또는 모바일 프로그램이 Keycloak 인증을 위해 브라우저를 사용해야함을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 관련해 애플리케이션 유형에 따라 다음 세가지 옵션을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 임베디드 웹 뷰 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 외부 사용자 에이전트 사용(사용자의 기본 브라우저)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 안드로이드 및 IOS와 같은 일부 플랫폼에서 지원하는 애플리케이션이 필요 없는 인앱 브라우저 탭 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임베디드 웹 뷰를 사용하게 되면 애플리케이션 내에 로그인 페이지를 배치할 수 있기 때문에 편리해 보일 수 있습니다. 하지만 해당 옵션은 자격증명 탈취와 관련된 취약점이 있기 때문에 권장하지 않습니다. 또한 여러 애플리케이션 간의 공유 쿠키가 없기 때문에 SSO를 사용하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션의 로그인 페이지를 표시하면서 시스템 브라우저를 활성화하기 때문에 인앱 브라우저 탭을 사용하는 것은 적절한 방법입니다.하지만 악의적인 애플리케이션이 인앱 브라우저탭과 유사한 애플리케이션 로그인 페이지를 랜더링해 자격증명을 탈취하는게 가능합니다. 해당 취약점을 피하고 싶은 사용자는 외부 브라우저에서 로그인 페이지를 접속하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인가 코드를 애플리케이션에 반환하는 경우, OAuth2.0에서 정의한 특수 리다이렉트 URI를 사용하는 4개의 서로 다른 접근 방법이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Claimed HTTPS scheme :&lt;/b&gt; 일부 플랫폼에서는 애플리케이션이 HTTPS 구조를 요청할 수 있으며, 시스템 브라우저를 사용하는 대신 애플리케이션에서 URI에 접근할 수 있습니다. 예를 들어 https://app.test01.org/oauth2callback/provider-name URI를&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Test01&lt;span&gt; &lt;/span&gt;&lt;/span&gt;APP 애플리케이션이 요청할 수 있으며&amp;nbsp; 브라우저가 아닌 Test01 APP 에서 콜백이 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Custom URI Scheme :&lt;/b&gt; 사용자 설정 URI 구조를 애플리케이션에 등록한다. Keycloak이 해당 사용자 URI 구조로 리다이렉트하면 애플리케이션에 요청이 전송된다. 사용자 지정 URI 구조는 애플리케이션 개발자가 소유한 도메인의 역순과 일치해야 한다. 예를들어 org.test01.app://oauth2/providename 리다이렉트 URI는 app.test01.org 도메인 네임과 일치해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Loopback interface :&lt;/b&gt; 애플리케이션은 루프백 인터페이스에서 임시 웹 서버의 임의의 포트를 오픈한 다음, http://127.0.0.1/oauth2/provider-name 리다이렉트 URI를 등록해 애플리케이션 웹서버에 요청을 보낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- A special redirect URI: 특수한 urn:left:wg:oauth2:2.0:oob 리다이렉트 URI를 사용하면 인가 코드가 Keycloak에서 표시되기 때문에 사용자는 수동으로 인가 코드를 복사해 애플리케이션에 붙여넣기할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTPS 구조를 사용할 수 있는 경우 HTTPS가 더 안전하기 때문에 해당 접근 방식 사용이 권장됩니다. CLI 환경과 같이 HTTPS 구조와 사용자 지정 구조를 사용할 수 없는 경우 루프백 인터페이스를 활용하는것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래픽 인터페이스 환경을 제공하지 않는 서버에서 터미널을 실행하는 경우와 같이 브라우저를 사용할 수 없는 상황도 존재합니다. 이런 경우 디바이스 코드 승인 유형을 활용하는 것이 권장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면, 디바이스 코드 승인 유형은 서로 다른 디바이스 브라우저에서 사용자가 인증서버의 특정 엔드포인트에 제공하는 짧은 코드를 표시하는 애플리케이션 기반에서 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 입력하면 사용자가 로그인돼 있지 않은 경우 로그인을 해야합니다. 로그인을 하게 되면 애플리케이션은 인가 서버에서 인가 코드를 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. REST API 및 서비스 보호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션이 Keycloak으로 보호되는 REST API를 호출하려는 경우, 먼저 Keycloak에서 접근 토큰을 얻은 다음 REST API로 보내는 요청에 권한 부여 헤더에 접근 토큰을 포함합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1739164585258&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Authorization : bearer eyJkcGciOiJsuZ1NilsInR55c__&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 REST API는 접근 토큰을 확인해 접근 권한 승인 여부를 결정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 접근 방식을 사용하면 많은 애플리케이션에서 활용할 수 있는 REST API를 쉽게 제공할 수 있으며, 또한 REST API를 서드파티 애플리케이션이 사용할 수 있도록 인터넷에서 공용 API로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이크로서비스에서 토큰을 사용해 서비스를 보호하는 것은 서비스가 다른 서비스를 호출할 때 인증 컨텍스트를 전파 할 수 있기 때문에 다음 다이어그램과 같이 전체적인 사용자 종단 (end-to-end)간 인증을 쉽게 제공할 수 있으므로 특히 유용합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAXqK5/btsMdId2ERP/TrjK2HwL2JToDlm2xi8VaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAXqK5/btsMdId2ERP/TrjK2HwL2JToDlm2xi8VaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAXqK5/btsMdId2ERP/TrjK2HwL2JToDlm2xi8VaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAXqK5%2FbtsMdId2ERP%2FTrjK2HwL2JToDlm2xi8VaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;187&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서 애플리케이션은 서비스 A를 호출할 때 접근 토큰을 포함합니다. 그다음 서비스 A는 동일한 접근 토큰을 사용해 서비스 B와 서비스 C를 호출하며, 모든 서비스가 동일한 인증 컨텍스트를 사용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak은 또한 서비스 계정을 지원하므로 서비스가 클라이언트 자격증명 승인 유형을 사용해 자체적으로 접근 토큰을 획득할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API만 토큰을 활용하는 것은 아닙니다. 다양한 프로토콜 인증에 자주 사용되는 SASL(Simple Authentication and Security Layer)은 bearer 토큰 또한 지원합니다. gRPC 및 Websockets은 안전한 호출을 위해 bearer 토큰을 활용할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 요청에 Bearer 토큰을 포함해 서비스에 전송하면 해당 서비스는 토큰을 직접 검증하거나 토큰 점검 엔드포인트를 사용해 해당 요청의 수락여부를 결정한다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이글에서는 Keycloak을 활용해서 애플리케이션을 보호하는 원리와 베스트 프랙티스에 대해 작성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음글에서는 전체 애플리케이션을 Keycloak과 통합하기 위해 사용할 수 있는 옵션에 대해 작성하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수고하셨습니다.~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak</category>
      <category>keycloak 개념</category>
      <category>keycloak이란</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/97</guid>
      <comments>https://marshmello.tistory.com/97#entry97comment</comments>
      <pubDate>Mon, 10 Feb 2025 09:29:36 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 3</title>
      <link>https://marshmello.tistory.com/96</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. keycloak에 DB 연동하기 (PostgreSQL)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.keycloak.org/downloads&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.keycloak.org/downloads&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738560624198&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;downloads - Keycloak&quot; data-og-description=&quot;Keycloak is a Cloud Native Computing Foundation incubation project &amp;copy; Keycloak Authors 2024. &amp;copy; 2024 The Linux Foundation. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Founda&quot; data-og-host=&quot;www.keycloak.org&quot; data-og-source-url=&quot;https://www.keycloak.org/downloads&quot; data-og-url=&quot;https://www.keycloak.org/downloads&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.keycloak.org/downloads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.keycloak.org/downloads&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;downloads - Keycloak&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Keycloak is a Cloud Native Computing Foundation incubation project &amp;copy; Keycloak Authors 2024. &amp;copy; 2024 The Linux Foundation. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Founda&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.keycloak.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1982&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0tizH/btsL6rwbyW1/z92jjJLiU8iJ28RpTsJ8Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0tizH/btsL6rwbyW1/z92jjJLiU8iJ28RpTsJ8Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0tizH/btsL6rwbyW1/z92jjJLiU8iJ28RpTsJ8Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0tizH%2FbtsL6rwbyW1%2Fz92jjJLiU8iJ28RpTsJ8Ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1982&quot; height=&quot;658&quot; data-origin-width=&quot;1982&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak 공식 홈페이지에서 keycloak 다운로드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드한 keycloak 폴더의 압축을 풉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 포트값은 8080인데 변경하려면 conf/keycloak.conf 파일을 실행하여 아래와 같이 작성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1738560813617&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http-port=9090&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7eOCR/btsL4zJvFwR/LpcGkstVFYjWR17pbCKyNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7eOCR/btsL4zJvFwR/LpcGkstVFYjWR17pbCKyNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7eOCR/btsL4zJvFwR/LpcGkstVFYjWR17pbCKyNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7eOCR%2FbtsL4zJvFwR%2FLpcGkstVFYjWR17pbCKyNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;497&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.keycloak.org/getting-started/getting-started-zip&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.keycloak.org/getting-started/getting-started-zip&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738560849902&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;OpenJDK - Keycloak&quot; data-og-description=&quot;From a terminal, open the keycloak-26.1.0 directory. Enter the following command: On Linux, run: On Windows, run: Using the start-dev option, you are starting Keycloak in development mode. In this mode, you can try out Keycloak for the first time to get it&quot; data-og-host=&quot;www.keycloak.org&quot; data-og-source-url=&quot;https://www.keycloak.org/getting-started/getting-started-zip&quot; data-og-url=&quot;https://www.keycloak.org/getting-started/getting-started-zip&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cRY9bi/hyYceEzU1a/ivDOkcoC2Ieohq2qQpOMC0/img.png?width=1294&amp;amp;height=858&amp;amp;face=0_0_1294_858,https://scrap.kakaocdn.net/dn/ctqS5H/hyX72FOoKI/sk3xoVV3jOhVpJvMKy4DI1/img.png?width=1186&amp;amp;height=763&amp;amp;face=0_0_1186_763&quot;&gt;&lt;a href=&quot;https://www.keycloak.org/getting-started/getting-started-zip&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.keycloak.org/getting-started/getting-started-zip&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cRY9bi/hyYceEzU1a/ivDOkcoC2Ieohq2qQpOMC0/img.png?width=1294&amp;amp;height=858&amp;amp;face=0_0_1294_858,https://scrap.kakaocdn.net/dn/ctqS5H/hyX72FOoKI/sk3xoVV3jOhVpJvMKy4DI1/img.png?width=1186&amp;amp;height=763&amp;amp;face=0_0_1186_763');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;OpenJDK - Keycloak&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;From a terminal, open the keycloak-26.1.0 directory. Enter the following command: On Linux, run: On Windows, run: Using the start-dev option, you are starting Keycloak in development mode. In this mode, you can try out Keycloak for the first time to get it&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.keycloak.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;관리자 창을 열어 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1738560905728&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\keycloak-26.0.7\keycloak-26.0.7
bin\kc.bat start-dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1591&quot; data-origin-height=&quot;397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBKRYk/btsL4W5fNjs/36kcUgdCRWq0Ty0sZyV3o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBKRYk/btsL4W5fNjs/36kcUgdCRWq0Ty0sZyV3o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBKRYk/btsL4W5fNjs/36kcUgdCRWq0Ty0sZyV3o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBKRYk%2FbtsL4W5fNjs%2F36kcUgdCRWq0Ty0sZyV3o1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1591&quot; height=&quot;397&quot; data-origin-width=&quot;1591&quot; data-origin-height=&quot;397&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익스플로러를 실행하여 127.0.0.1:9090을 실행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1869&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dONgzP/btsL46GGCZg/KVXlvbnjprzRPbJFNdy05K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dONgzP/btsL46GGCZg/KVXlvbnjprzRPbJFNdy05K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dONgzP/btsL46GGCZg/KVXlvbnjprzRPbJFNdy05K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdONgzP%2FbtsL46GGCZg%2FKVXlvbnjprzRPbJFNdy05K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1869&quot; height=&quot;923&quot; data-origin-width=&quot;1869&quot; data-origin-height=&quot;923&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak은 java h2 db를 사용하고 있습니다. 그러나 자체적으로 데이터베이스를 관리하기 위해 postgres 데이터베이스를 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.postgresql.org/download/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738561029053&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;PostgreSQL: Downloads&quot; data-og-description=&quot;&quot; data-og-host=&quot;www.postgresql.org&quot; data-og-source-url=&quot;https://www.postgresql.org/download/&quot; data-og-url=&quot;https://www.postgresql.org/download/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.postgresql.org/download/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;PostgreSQL: Downloads&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.postgresql.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1805&quot; data-origin-height=&quot;555&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxmIlV/btsL3ZWa31D/MrTyX245md3gEFqSOZ1Vt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxmIlV/btsL3ZWa31D/MrTyX245md3gEFqSOZ1Vt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxmIlV/btsL3ZWa31D/MrTyX245md3gEFqSOZ1Vt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxmIlV%2FbtsL3ZWa31D%2FMrTyX245md3gEFqSOZ1Vt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1805&quot; height=&quot;555&quot; data-origin-width=&quot;1805&quot; data-origin-height=&quot;555&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드받은 postgres 설치파일을 실행하여 postgresql을 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dbeaver를 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dbeaver.io/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://dbeaver.io/download/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738561115125&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Download | DBeaver Community&quot; data-og-description=&quot;Download DBeaver Community 24.3.4 Released on February 2nd 2025 (Milestones). It is free and open source (license). Also you can get it from the GitHub mirror. System requirements. DBeaver PRO 24.3 Released on December 16th, 2024 PRO version website: dbeav&quot; data-og-host=&quot;dbeaver.io&quot; data-og-source-url=&quot;https://dbeaver.io/download/&quot; data-og-url=&quot;https://dbeaver.io/download/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iQrHC/hyX7P7vOs8/w3v9eLlaDh7JliCQSycU60/img.png?width=1083&amp;amp;height=222&amp;amp;face=0_0_1083_222&quot;&gt;&lt;a href=&quot;https://dbeaver.io/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dbeaver.io/download/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iQrHC/hyX7P7vOs8/w3v9eLlaDh7JliCQSycU60/img.png?width=1083&amp;amp;height=222&amp;amp;face=0_0_1083_222');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download | DBeaver Community&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download DBeaver Community 24.3.4 Released on February 2nd 2025 (Milestones). It is free and open source (license). Also you can get it from the GitHub mirror. System requirements. DBeaver PRO 24.3 Released on December 16th, 2024 PRO version website: dbeav&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dbeaver.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF92PA/btsL6kjOJBO/R52lENywRqT0m9D7Wbfkjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF92PA/btsL6kjOJBO/R52lENywRqT0m9D7Wbfkjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF92PA/btsL6kjOJBO/R52lENywRqT0m9D7Wbfkjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF92PA%2FbtsL6kjOJBO%2FR52lENywRqT0m9D7Wbfkjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1217&quot; height=&quot;894&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dbeaver를 실행하여 설치한 postgres를 연결합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Database Navigator에서 마우스 우측 클릭 &amp;gt; Create &amp;gt; Connect 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;485&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8k0eP/btsL36U9ZuP/jgyNziKe664bry6zcukw21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8k0eP/btsL36U9ZuP/jgyNziKe664bry6zcukw21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8k0eP/btsL36U9ZuP/jgyNziKe664bry6zcukw21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8k0eP%2FbtsL36U9ZuP%2FjgyNziKe664bry6zcukw21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;485&quot; height=&quot;247&quot; data-origin-width=&quot;485&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;postgreSQL 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djsccZ/btsL4ZgAps0/LFTuD2vvEBdfKuLyWvtdr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djsccZ/btsL4ZgAps0/LFTuD2vvEBdfKuLyWvtdr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djsccZ/btsL4ZgAps0/LFTuD2vvEBdfKuLyWvtdr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjsccZ%2FbtsL4ZgAps0%2FLFTuD2vvEBdfKuLyWvtdr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;872&quot; height=&quot;378&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;postgres 설치시 입력한 db 비밀번호 입력 후 Test Connection.. 버튼 클릭 (show all databases 체크)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD2EWK/btsL5tVTYhE/b9L0FrdQQew4g0mqkRKBY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD2EWK/btsL5tVTYhE/b9L0FrdQQew4g0mqkRKBY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD2EWK/btsL5tVTYhE/b9L0FrdQQew4g0mqkRKBY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD2EWK%2FbtsL5tVTYhE%2Fb9L0FrdQQew4g0mqkRKBY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;593&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결 성공 메시지를 확인했다면 확인 버튼 클릭 후 완료합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Database에 마우스 우측 클릭 &amp;gt; Create New Database 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mck76/btsL352YJfI/z4oKomucah0BCJlQXGrW7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mck76/btsL352YJfI/z4oKomucah0BCJlQXGrW7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mck76/btsL352YJfI/z4oKomucah0BCJlQXGrW7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmck76%2FbtsL352YJfI%2Fz4oKomucah0BCJlQXGrW7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;373&quot; height=&quot;139&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloakdb라는 데이터베이스를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ErJAE/btsL4ziwtsL/twk620ldIDWCqB0oDpk9E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ErJAE/btsL4ziwtsL/twk620ldIDWCqB0oDpk9E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ErJAE/btsL4ziwtsL/twk620ldIDWCqB0oDpk9E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FErJAE%2FbtsL4ziwtsL%2Ftwk620ldIDWCqB0oDpk9E0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;209&quot; height=&quot;290&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성 완료 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t2voU/btsL4JrAbgA/MT1OiCaXHW9KKrjjJ4p38k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t2voU/btsL4JrAbgA/MT1OiCaXHW9KKrjjJ4p38k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t2voU/btsL4JrAbgA/MT1OiCaXHW9KKrjjJ4p38k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft2voU%2FbtsL4JrAbgA%2FMT1OiCaXHW9KKrjjJ4p38k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;211&quot; height=&quot;206&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 Keycloak 폴더의 conf/keycloak.conf 파일을 수정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VQwXW/btsL5A8wWzp/ROOJ83vb8RHmgTnNuBUrYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VQwXW/btsL5A8wWzp/ROOJ83vb8RHmgTnNuBUrYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VQwXW/btsL5A8wWzp/ROOJ83vb8RHmgTnNuBUrYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVQwXW%2FbtsL5A8wWzp%2FROOJ83vb8RHmgTnNuBUrYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;813&quot; height=&quot;377&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;db = postgres&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;db-username=postgres&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;db-password= postgres 설치시 입력한 비밀번호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;db-url=jdbc:postgresql://localhost:5432/keycloakdb&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령프롬프트 창을 열어 keycloak 개발자 모드를 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1738561904013&quot; class=&quot;css&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cd C:\keycloak-26.0.7\keycloak-26.0.7
bin\kc.bat start-dev&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2488&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D4HNx/btsL51kv2cV/waU2kEpjMMZLnZ4ZF8durk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D4HNx/btsL51kv2cV/waU2kEpjMMZLnZ4ZF8durk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D4HNx/btsL51kv2cV/waU2kEpjMMZLnZ4ZF8durk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD4HNx%2FbtsL51kv2cV%2FwaU2kEpjMMZLnZ4ZF8durk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2488&quot; height=&quot;1034&quot; data-origin-width=&quot;2488&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익스플로러 창을 열면 다시 관리자 사용자를 추가하라는 화면이 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;957&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y93a2/btsL6riHZF6/iOhJKlWqOn7oGZWCGb4FgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y93a2/btsL6riHZF6/iOhJKlWqOn7oGZWCGb4FgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y93a2/btsL6riHZF6/iOhJKlWqOn7oGZWCGb4FgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy93a2%2FbtsL6riHZF6%2FiOhJKlWqOn7oGZWCGb4FgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1472&quot; height=&quot;957&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;957&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dbeaver 창을 열어 확인해보면 테이블이 추가된 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pVneC/btsL6isNVRg/okviCBrd7b3VKckEb8erNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pVneC/btsL6isNVRg/okviCBrd7b3VKckEb8erNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pVneC/btsL6isNVRg/okviCBrd7b3VKckEb8erNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpVneC%2FbtsL6isNVRg%2FokviCBrd7b3VKckEb8erNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;391&quot; height=&quot;544&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익스플로러 화면에서 관리자 사용자를 추가한 후 create user 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sqtO7/btsL6kKVmK5/EhV8wd5u8LwEj7fTka9EhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sqtO7/btsL6kKVmK5/EhV8wd5u8LwEj7fTka9EhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sqtO7/btsL6kKVmK5/EhV8wd5u8LwEj7fTka9EhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsqtO7%2FbtsL6kKVmK5%2FEhV8wd5u8LwEj7fTka9EhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;711&quot; height=&quot;788&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Open Administration Console 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZiquy/btsL4yjBuxm/RcSlnwd8FgNILDHnX2NKF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZiquy/btsL4yjBuxm/RcSlnwd8FgNILDHnX2NKF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZiquy/btsL4yjBuxm/RcSlnwd8FgNILDHnX2NKF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZiquy%2FbtsL4yjBuxm%2FRcSlnwd8FgNILDHnX2NKF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;776&quot; height=&quot;508&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 관리자 아이디와 패스워드로 로그인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 검색 엔드포인트 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keycloak realm을 추가합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3SuAW/btsL4MWfssu/X3Z4PSW8RfWYM5k9g2zt01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3SuAW/btsL4MWfssu/X3Z4PSW8RfWYM5k9g2zt01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3SuAW/btsL4MWfssu/X3Z4PSW8RfWYM5k9g2zt01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3SuAW%2FbtsL4MWfssu%2FX3Z4PSW8RfWYM5k9g2zt01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1430&quot; height=&quot;736&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;736&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Configure 항목의 Realm settings 메뉴를 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하단의 Endpoints 을 확인하면 OpenID Endpoint Configuration , SAML 2.0 Identity Provider Metadata 2가지가 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1033&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFDA4z/btsL4FJBjtD/JwMMZhY6gRAZz8eO4Rmk3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFDA4z/btsL4FJBjtD/JwMMZhY6gRAZz8eO4Rmk3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFDA4z/btsL4FJBjtD/JwMMZhY6gRAZz8eO4Rmk3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFDA4z%2FbtsL4FJBjtD%2FJwMMZhY6gRAZz8eO4Rmk3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1033&quot; height=&quot;989&quot; data-origin-width=&quot;1033&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Endpoint Configuration 을 클릭하면 아래와 같은 화면이 나타납니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;973&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yHaIn/btsL5rKEjKB/YUsMPJ0f8rEShYryKk8sD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yHaIn/btsL5rKEjKB/YUsMPJ0f8rEShYryKk8sD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yHaIn/btsL5rKEjKB/YUsMPJ0f8rEShYryKk8sD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyHaIn%2FbtsL5rKEjKB%2FYUsMPJ0f8rEShYryKk8sD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;967&quot; height=&quot;973&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;973&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OIDC 검색 (OpenID Connect Discovery) 명세는 OIDC 신뢰자 (Relying Party) 라이브러리의 상호 운용성과 가용성 측면에서 모두 중요합니다. 해당 명세가 없는 경우 OpenID 제공자로 인증할 수 있도록 애플리케이션에서 많은 메뉴얼 설정을 수행해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OIDC 검색 명세는 OpenID 제공자가 구현 여부를 결정할 수 있는 선택 명세입니다. 다행히 Keycloak을 포함한 대부분의 OpenID 제공자는 해당 명세를 구현합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID 제공자에 대한 base URL( 보통 issue url)을 알기만 하면 신뢰자는 제공자에 대한 유용한 정보를 많이 검색할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;base URL&amp;gt;/.well-known/openid-configuration 에서 표준 엔드포인트인 OpenID 제공자 메타데이터를 로드해 해당 작업을 수행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;issuer : Keycloak은 멀티 테넌시 multi-tenancy를 지원하기 때문에 Keycloak 인스턴스의 각 영역을 분리하기 위해 사용됩니다.&lt;/li&gt;
&lt;li&gt;authorization_endpoint : 인증 요청을 위한 URL&lt;/li&gt;
&lt;li&gt;token_endpoint : 토큰 요청을 위한 URL&lt;/li&gt;
&lt;li&gt;introspection_endpoint : 점검 요청을 위한 URL&amp;nbsp;&lt;/li&gt;
&lt;li&gt;userinfo_endpoint : UserInfo 요청을 위한 URL&lt;/li&gt;
&lt;li&gt;grant_types_supported : 지원 가능한 승인 유형 리스트&lt;/li&gt;
&lt;li&gt;response_types_supported : 지원 가능한 응답 유형 리스트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K8UVA/btsL4zv8h9c/KcsXagWSkEmfrrZkg7PNKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K8UVA/btsL4zv8h9c/KcsXagWSkEmfrrZkg7PNKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K8UVA/btsL4zv8h9c/KcsXagWSkEmfrrZkg7PNKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK8UVA%2FbtsL4zv8h9c%2FKcsXagWSkEmfrrZkg7PNKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;543&quot; height=&quot;522&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;733&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;[인가코드흐름]&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 사용자가 애플리케이션의 로그인 버튼을 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② 애플리케이션이 인증 요청을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;③ 인증 요청은 302 리다이렉트 형식으로 사용자에게 전송되며, user-agent에게 keycloak에서 제공하는 인가 엔드포인트로 리다이렉트되도록 알려줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;④ User-agent는 인증 요청을 통해 애플리케이션에서 명시한 쿼리 파라미터를 사용해 인가 엔드포인트를 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑤ Keycloak은 사용자에게 로그인 페이지를 표시합니다. 사용자는 사용자이름과 패스워드를 입력하고 해당 양식을 제출합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑥ Keycloak은 사용자의 자격 증명을 검증한 다음 애플리케이션에게 제공할 인가 코드를 생성합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑦ 애플리케이션은 인가 코드를 ID 토큰과 리프레시 토큰으로 교환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak db연결</category>
      <category>keycloak db연동</category>
      <category>keycloak postgres 연동</category>
      <category>keycloak 데이터베이스 연동</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/96</guid>
      <comments>https://marshmello.tistory.com/96#entry96comment</comments>
      <pubDate>Mon, 3 Feb 2025 14:54:03 +0900</pubDate>
    </item>
    <item>
      <title>Keycloak 시작하기 2</title>
      <link>https://marshmello.tistory.com/95</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. OAuth 2.0 을 이용한 접근 권한 인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0은 현재 널리 사용되는 업계 표준 프로토콜입니다. OAuth2.0의 핵심은 전체 웹 사이트 생태계를 서로 통합할 수 있는 OAuth2.0 프레임워크가 위치합니다. OAuth2.0을 사용하면 서드파티 어플리케이션과 사용자 데이터를 쉽게 공유하고, 사용자 자격증명을 공유할 필요가 없으며 공유할 데이터를 제어할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0은 서드파티 애플리케이션을 제어하는 것 외에도 자체 애플리케이션에 대한 접근 제한에도 매우 유용합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서드파티 애플리케이션이 다른 사이트에서 사용자 이름과 패스워드를 요청하는 것이 일반적인 것처럼 기업 내부에서도 이는 일반적인 패턴이었습니다. 예를 들어 LDAP 사용자 이름과 패스워드를 요청하고 기업 내부의 다른 서비스에 접근하기 위해 해당 자격증명을 사용합니다.즉 하나의 애플리케이션이 보안 위험에 노출되면 기업 내부의 모든 서비스 또한 위협에 노출될 수 있음을 의마합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0에는 다음과 같은 롤이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 리소스 오너 (Resource Owner) :&lt;/b&gt; 일반적으로 애플리케이션이 접근하고자 하는 리소스를 소유한 최종 소유자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 리소스 서버 (Resource Server) :&lt;/b&gt; 보호된 자원을 소유한 서비스.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 클라이언트(Client) :&lt;/b&gt; 리소스에 접근하는 애플리케이션&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 인가 서버 ( Authorization Server) :&lt;/b&gt; 클라이언트에게 접근 권한을 발급하는 서버이며 Keycloak이 해당 역할을 수행함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 OAuth2.0 프로토콜 흐름에서 클라이언트는 인가 서버에서 리소스 오너를 대신해 리소스에 대한 접근을 요청합니다. 인가 서버는 리소스에 대한 제한된 접근 권한을 가진 접근 토콜을 발급합니다. 접근 토큰을 획특한 후 , 클라이언트는 요청에 접근 토큰을 포함해 리소스 서버에 있는 리소스에 접근 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 유형 및 사용자 활용 사례에 따라, 사용 가능한 여러가지 흐름이 존재합니다. 적절한 애플리케이션 흐름 유형을 선택하기 위해 다음과 같은 공식을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션 자체적으로 리소스에 접근하는 경우( 애플리케이션이 리소스 오너의 경우) Client Credentials flows를 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션이 브라우저가 없는 장치에서 실행 중이거나 입력이 제한된 경우 Device flow를 사용 (ex, 스마트TV)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 그 밖의 경우에는 Authorizaion Code flow를 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Implicit flow : 네이티브 애플리케이션 및 클라이언트 사이드 애플리케이션을 위해 간소화된 흐름 (안전하지 않아 현재 사용하지 않음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Resource Owner Password Credentials flow :&amp;nbsp; 애플리케이션 사용자의 자격증명을 직접 수집하고, 해당 자격증명을 접근 토큰과 교환함. (현재 사용하지 않음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1656&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NUBrw/btsLYEv4C8K/jXznFy1GArl6otm9KszjKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NUBrw/btsLYEv4C8K/jXznFy1GArl6otm9KszjKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NUBrw/btsLYEv4C8K/jXznFy1GArl6otm9KszjKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNUBrw%2FbtsLYEv4C8K%2FjXznFy1GArl6otm9KszjKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1656&quot; height=&quot;852&quot; data-origin-width=&quot;1656&quot; data-origin-height=&quot;852&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;[OAuth2.0 간소화된 인가 코드 승인]&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 애플리케이션은 인가 요청을 처리하고, 사용자의 브라우저를 Keycloak으로 리다이렉트시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② 사용자의 브라우저는 사용자를 인가 엔드 포인트라는 Keycloak엔드포인트로 리다이렉트합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;③ 사용자가 Keycloak을 통해 인증되지 않은 경우, Keycloak이 사용자를 인증합니다. 인증이 완료된 후 Keycloak은 사용자를 대신해 애플리케이션이 서비스에 접근 할 수 있도록 하기 위해 사용자의 동의를 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;④ 애플리케이션은 인가 응답에서 인가 코드를 Keycloak으로부터 수신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑤ 애플리케이션은 Keycloak의 토큰 엔드포인트에 대한 접근 토큰 요청을 통해 인가 코드를 접근 토큰으로 교환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑥ 이제 애플리케이션은 보호된 리소스를 호출하기 위해 접근 토큰을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0 흐름에는 기밀 및 공용 클라이언트 흐름이 존재합니다. 기밀 클라이언트는 인가 서버를 인증하기 위한 자격증명을 안전하게 저장할 수 있는 서버 사이드 애플리케이션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공용 클라이언트는 자격증명을 안전하게 저장할 수 없는 클라이언트 사이드 애플리케이션입니다. 공용 클라이언트 인가 서버를 인증할 수 없기 때문에 다음과 같은 2가지 보안을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인가 서버는 사전 등록된 리다이렉트 URL을 가진 애플리케이션에 인가코드를 전송합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- OAuth2.0의 확장 기능인 Proof key for Code Exchange는 노출된 인가 코드를 접근 토큰으로 교환되지 않도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 토큰은 애플리케이션에서 서비스로 전달되기 때문에 일반적으로 짧은 수명을 가집니다. 전체 흐름을 수행하지 않고 애플리케이션이 신규 접근 토큰을 사용하려면 리프레시 토큰을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0핵심 프레임워크 외에도 추가적으로 알아둬야할 사양이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Bearer Tokens(RFC 6750)&amp;nbsp; :&lt;/b&gt; OAuth2.0은 접근 토큰 유형이나 사용 방법에 대해 정의돼 있지않습니다. Bearer 토큰은 현재 가장 일반적으로 사용되는 접근 토큰 유형이며 일반적으로 HTTP인가 헤더를 통해 리소스 서버로 전송됩니다. 또한 인코딩 처리된(form-endocded) 페이로드(body), 또는 쿼리 파라미터로 전달됩니다. 여기서 주의해야할 점은 Bearer 토큰을 쿼리 파라미터로 전송되는 것은 그 자체로 보얀취약점이기 때문에 사용하지 말아야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Token Introspection(RFC 7662) :&lt;/b&gt; OAuth2.0 접근 토큰의 내용은 애플리케이션에 노출되지 않습니다. 따라서 애플리케이션은 접근 토큰의 내용을 알 수 없습니다. 클라이언트는 토큰 점검 엔드포인트(token introspection endpoint)를 통해 접근 토큰의 형식을 이해하지 않고로 접근 토큰에 대한 정보를 얻을 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Token Revocation(RFC 7009) :&lt;/b&gt; OAuth2.0은 접근 토큰을 애플리케이션에서 발급하는 방법을 고려하지만 취소하는 방법은 고려하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 OAuth2.0사용방법에 대한 다양한 베스트 프랙티스가 존재합니다. 보안 고려 사항과 베스트 프랙티스를 포함해 네이티브 애플리케이션, 브라우저 기반 애플리케이션에 대한 권장 사항도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0은 리소스에 접근 권한을 부여할 수 있지만, 사용자 인증을 수행하지 않습니다. 인증은 OpenID Connect라는 OAuth2.0확장에서 수행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. OpenID Connect를 통한 사용자 인증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0은 인가 프로토콜이기 때문에 인증을 수행하지 않습니다. 인증을 수행하기 위해 OpenID Connect가 OAuth2.0과 함께 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect의 핵심은 &lt;b&gt;OpenID Connect Core specification&lt;/b&gt;이며, 전체 웹사이트 생태계에서 더이상 사용자 관리 및 사용자 인증을 처리하지 않도록 만들었습니다. 또한 사용자 인증을 수행하는 횟수와 사용자가 기억해야 하는 다양한 패스워드의 개수, 즉 사용자가 접근하는 모든 웹사이트에 필요한 패스워드 관리 부담을 감소시켰습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 또는 기타 소셜 네트워크를 사용해 로그인할 수 있는 수많은 웹사이트들이 존재합니다. OpenID Connect를 구현하는 대신 OAuth2.0을 상황에 맞게 수정해야 사용하는 일부 웹사이트들과 비교할 때 구글은 구글 로그인하기 기능을 아주 쉽게 추가할 수 있는 OpenID Connect를 제대로 구현하고 있기 때문에 다른 소셜 네트워크보다 구글을 강조하고자 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect는 소셜 로그인 기능뿐만 아니라 싱글 사인온 기능을 지원하는 통합 인증 솔루션을 구축하고자 하는 기업에게도 매우 유용합니다. 도한 애플리케이션이 사용자 자격증명에 직접 접근할수 없기때문에 보안을 크게 향상 시킬 수 있으며, 애플리케이션에 추가적인 설정을 하지 않고도 OTP 또는 WebAuthn과 같은 강력한 인증을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect는 기업의 인증 도입을 용이하게 할 뿐만 아니라 파트너 회사의 직원과 같은 제3자가 기업 내에서 개별 계정을 생성하지 않고도 애플리케이션에 접근할 수 있도록 합니다. OAuth2.0과 마찬가지로 OpenID Connect 또한 프로토콜과 관련된 다양한 역할이 정의돼 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 최종 사용자 (End User) :&lt;/b&gt; OAuth2.0의 리소스 오너에 해당되며 사용자를 인증함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Relying Party(RP) :&lt;/b&gt; 사용자의 ID를 인증하는 OpenID Connect Provider를 신뢰하기 때문에 신뢰자(Relying Party)라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- OpenID Provider(OP) :&lt;/b&gt; 사용자를 인증하는 ID 제공자이며, keycloak이 해당 역할을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 OpenID Connect 프로토콜 흐름에서 신뢰자는 OpenID Provider가 인증한 사용자의 ID를 요청합니다. OAuth2.0과 연동돼 있기 때문에 사용자의 ID를 요청함과 동시에 접근 토큰을 획득할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect는 OAuth2.0인가 인가 코드(Authorization Code)승인 유형을 사용합니다. 주요 차이점은 클라이언트의 초기 요청에 scope = openid가 포함되며 인가 요청이 아닌 인증 요청을 생성하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0은 서로 다른 흐름 승인 유형을 요청하지만 OpenID Connect에서 해당 요청들을 흐름으로 처리합니다. OpenID Connect에는 알고 있어야 하는 2개의 흐름이 존재합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;- 인가 코드 흐름 :&lt;/b&gt; OAuth2.0 인가 코드 승인 요청과 동일한 흐름을 사용하고 OAuth2.0과 같은 인가 코드를 반환합니다. 해당 인가 코드는 ID 토큰 , 접근 토큰 그리고 리프레시 토큰과 교환 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 하이브리드 흐름 :&lt;/b&gt; 하이브리드 흐름에서 ID 토큰은 인증코드와 함께 초기 요청에서 반환됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0과 마찬가지로 OpenID Connect 또한 암시적 흐름(Implicit flow)을 정의합니다. 하지만 암시적 흐름 사용을 권장하지 않습니다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;OpenID Connect 클라이언트 자격증명 흐름 및 장치 흐름에 해당하는것은 정의하지 않습니다. 해당 흐름은 사용자를 인증할 필요가 없으므로 서비스에 대한 접근 권한만 부여하면 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect의 인가 코드 흐름에 익숙하지 않은 경우 , 다음 다이어그램을 통해 코드흐름의 동작 방식을 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;857&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbqW2O/btsLYSHP80h/0kkQZ8O70NlbcDpmwsC4HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbqW2O/btsLYSHP80h/0kkQZ8O70NlbcDpmwsC4HK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbqW2O/btsLYSHP80h/0kkQZ8O70NlbcDpmwsC4HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbqW2O%2FbtsLYSHP80h%2F0kkQZ8O70NlbcDpmwsC4HK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;674&quot; height=&quot;442&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;857&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;[간소화된 OpenID Connect 인가 코드 흐름]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 애플리케이션은 인가 요청을 생성하고 사용자의 브라우저를 Keycloak으로 리다이렉트시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② 사용자의 브라우저는 사용자를 Keycloak의 인가 엔드포인트로 리다이렉트시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;③ 사용자가 Keycloak에 인증되지 않은 경우 , Keycloak은 사용자를 인증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;④ 애플리케이션은 Keycloak의 인가 응답으로부터 인가 코드를 수신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑤ 애플리케이션은 Keycloak의 토큰 엔드포인트에 대한 토큰 요청을 통해 인가 코드를 ID 토큰 및 접근 토큰으로 교환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⑥ 애플리케이션은 사용자의 ID를 검증할 수 있는 ID 토큰을 가지고 사용자와 인증된 세션을 수립합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect Core 명세 외에도 알아야 할 몇가지 추가 명세가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Discovery :&lt;/b&gt; 클라이언트가 OpenID 제공자에 대한 정보를 동적으로 검색합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Dynamic Registration :&lt;/b&gt; 클라이언트가 OpenID 제공자에 동적으로 자신을 등록합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Session Management :&lt;/b&gt; OpenID 제공자와 최종 사용자의 인증 세션을 모니터링 하는 방법과 클라이언트가 로그아웃 방법을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Front-Channel Logout :&lt;/b&gt; 임베디드 iframe을 사용해 여러 애플리케이션의 싱글 사인아웃 매커니즘을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Back-Channel Logout :&lt;/b&gt; back-channel 요청 매커니즘을 사용해 여러 애플리케이션에 대한 단일 로그아웃 매커니즘을 정의합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect는 OAuth2.0외의 2개의 추가적인 개념을 가집니다. 해당 개념은 OAuth2.0의 접근 토큰과 달리 모호하지않은 JWT 명세를 활용해 ID 토큰의 형식을 명확하게 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 개념은 포맷이 잘 정의돼 있으며, 토큰에 포함된 값은 클라이언트가 직접 확인할 수 있습니다. 이것을 통해 클라이언트는 인증된 사용자에 대한 정보를 일반적인 방법으로 검색할 수 있습니다. 또한 접근 토큰으로 호출할 수 있는 userinfo endpoint를 정의하며, ID 토큰에 포함된 것과 동일한 표준 클레임을 반환합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;높은 보안 수준이 필요한 활용 사례에 경우 Financial-grade API 워킹 그룹이라고 하는 프로파일 집합이 있다. 해당 프로파일은 OpenID Connect 및 관련 명세를 고위험 시나리오에서 사용하는 방법에 대한 베스트 프랙티스를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 OpenID Connect에 대한 기본적인 동작 방식과 애플리케이션에 적용하는 방법을 알아봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenID Connect 토큰에 대한 표준 포맷을 정의하지만 접근 토큰은 정의하지 않습니다. Keycloak에서 왜 JWT를 디폴트 접근 토큰으로 사용하지 않는지 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. JWT를 토큰으로 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 초창기 때부터 Keycloak은 접근 토큰 포맷으로 JWT를 사용해왔습니다. 성능과 호환성을 고려한 결정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교적 쉽게 사용할 수있는 표준형식을 사용해 해당 포맷이 Keycloak과 유연하게 통합될 수 있도록 했습니다. JWT는 JSON기반이기 때문에, 모든 프로그래밍 언어에서 쉽게 파싱할 수 있고 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 리소스 서버는 이제 접근 토큰의 값을 직접 읽을 수 있으므로 OAuth2.0 토큰 검사 엔드포인트 또는 OpenID Connect Userinfo 엔드포인트에 해당 요청을 전송할 필요가 없습니다. 따라서 Keycloak의 리소스 서버 요청에 대한 2개의 추가적인 요청을 하지 않아도 되며, 지연 시간이 단축될뿐만 아니라 Keycloak에 대한 요청 개수가 크게 감소합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT JOSE 제품군에 속하며, JWT는 Javascript Object Sigining And Encryption의 약자입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련 명세는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JSON WEB Token(JWT, RFC 7519) :&lt;/b&gt; 점 dot, 헤더 및 클레임 집합으로 구분된 2개의 base64url-encoded JSON 문서로 구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JSON WEB Signature(JWT, RFC 7515) :&lt;/b&gt; 헤더 및 클레임의 디지털 시그니처 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JSON WEB Encryption(JWT, RFC 7516):&lt;/b&gt; 클레임 암호화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JSON WEB Algorithms(JWT, RFC 7518) :&lt;/b&gt; JWS 및 JWE에서 사용할 암호화 알고리즘 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JSON WEB Key(JWT, RFC 7517) :&lt;/b&gt; 암호화 키를 JSON 형식으로 나타내는 형식 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 명세 외에도 OpenID Connect Discovery 엔드포인트는 JWKS(JSON Web Key Set)를 검색할 수 있는 엔드포인트와 JWA 명세에서 지원하는 서명 및 암호화 메커니즘을 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 서버가 접근 토큰을 수신하면 다음과 같은 방법으로 토큰을 검증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- OpenID Connect Discovery 엔드포인트에서 JWKS URL을 검색합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JWKS URL 엔드포인트에서 OpenID 제공자에 대한 공개 서명 키 public signing key를 다운로드합니다. 해당 키는 일반적으로 리소스 서버에 캐시/저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- OpenID 제공자의 공개 서명키를 사용해 토큰의 서명을 검증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT를 검증할 때 JWT 명세에 몇 가지 잠재적인 문제로 보안을 적절히 수행하지 않은 경우 예기치 못한 취약점이 발생할 수 있습니다. 해당 명세를 잘못 적용해 발생할 수 있는 두가지 취약점은 다음과 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- alg=none : JWS 명세에서 알고리즘 값을 none으로 설정 할 수 있습니다. 해당 값의 의미는 기본적으로 JWS가 서명되지 않았음을 의미합니다. 해당 값은 정상적인 값이기 떄문에 JWT 라이브러리는 JWS가 실제로 서명되지 않더라도 해당값을 유효하다고 인식합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- RSA to HMAC : 잘 알려진 또 다른 이슈는 공용 RSA 키를 사용하지만 알고리즘을 HMAC으로 설정하는 것입니다. 몇몇 라이브러리는 공개 RSA 키를 선택해 HMAC을 비밀키로 사용하기 때문에 이러한 유형의 토큰을 검증 없이 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 유형의 취약점은 다음과 같은 방법으로 회피할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- alg=none을 처리하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 알고리즘과 필요한 경우에만 키를 사용하고, JWT 헤더의 값을 무조건 신뢰하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 신뢰할 수 있는 JWT 라이브러리를 선택해 적절한 방법을 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 토큰으로 JWT를 지원하는 OpneID Connect/OAuth2.0 라이브러리를 사용하는 것을 가장 권장합니다. 위의 두가지 방법을 모두 사용할 수 없는 경우 토큰의 유효성을 직접 확인하는 것보다 토큰 점검 엔드포인트를 사용하는 것이 더욱 안정적인 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. SAML2.0 이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAML2.0(Security Assertion Markup Language2.0) 은 성숙하고 신뢰할 수 있는 인증 및 인가 프로토콜입니다. 해당 프로토콜은 기업 내부 및 교육 , 정부기관의 싱글사인온을 구현하기 위해 널리 사용됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAML2.0은 기존 사용자를 신규 배포하는 애플리케이션에서 인증을 수행할 수 있게 해주는 것과 같이 기업 애플리케이션에서 매우 다양하게 활용됩니다.&amp;nbsp; 자체 호스팅 애플리케이션을 포함해 세일즈포스,구글앱스,오피스365와 같은 여러 SaaS(Software as&amp;nbsp; a Service) 솔루션에서도 활용될 수 있습니다. 기업 입장에서는 클라우드에서 호스팅되는 솔루션을 선택할 때 각 직원에 대한 계정을 생성할 필요없이 모든 직원이 해당 솔루션에 신속하게 접근할수 있도록 해주는 옵션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAML2.0이 좀 더 신뢰성 있고 더 널리 사용되곤 있지만, 신규 애플리케이션의 경우 SAML2.0보다 OpenID Connect를 사용하는 것을 더 선호할 수 있습니다. OpenID Connect는 단일 페이지 애플리케이션, 모바일 애플리케이션, REST API 및 마이크로서비스와 같은 최신 아키텍처에 좀 더 중점을 두고 있기 떄문에 추후 활용에 더욱 적합합니다. 개발자는 또한 OpenID Connect가 JSON 및 간소화된 쿼리 파라미터를 활용하는 반면, SAML2.0은 더 복잡한 XML 문서를 사용하기 떄문에 OpenID Connect가 더 이해하기 쉬움을 알게 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth2.0, OpenID Connect, SAML2.0의 세부 사항에 익숙하지 않은 경우 OAuth2.0 및 OpenID Connect 학습부터 하는것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Keycloak의 가장 큰 장점은 두가지 옵션을 모두 사용할 수 있다는 것입니다. 또한 동일 싱글사인온 환경에서 OpenID Connect를 사용하는 경우와 SAML2.0을 사용하는 애플리케이션을 원활하게 통합할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <category>keycloak 개념</category>
      <category>keycloak 사용방법</category>
      <category>keycloak 인증</category>
      <category>keycloak이란</category>
      <author>마시멜로co.</author>
      <guid isPermaLink="true">https://marshmello.tistory.com/95</guid>
      <comments>https://marshmello.tistory.com/95#entry95comment</comments>
      <pubDate>Thu, 23 Jan 2025 10:33:00 +0900</pubDate>
    </item>
  </channel>
</rss>