KEYCLOAK-740 Documentation of adapters clustering
This commit is contained in:
parent
c6fc44bcc2
commit
b1cfedb488
4 changed files with 302 additions and 1 deletions
|
@ -34,6 +34,7 @@
|
||||||
<!ENTITY ServerCache SYSTEM "modules/cache.xml">
|
<!ENTITY ServerCache SYSTEM "modules/cache.xml">
|
||||||
<!ENTITY SecurityVulnerabilities SYSTEM "modules/security-vulnerabilities.xml">
|
<!ENTITY SecurityVulnerabilities SYSTEM "modules/security-vulnerabilities.xml">
|
||||||
<!ENTITY Clustering SYSTEM "modules/clustering.xml">
|
<!ENTITY Clustering SYSTEM "modules/clustering.xml">
|
||||||
|
<!ENTITY ApplicationClustering SYSTEM "modules/application-clustering.xml">
|
||||||
]>
|
]>
|
||||||
|
|
||||||
<book>
|
<book>
|
||||||
|
@ -125,6 +126,7 @@ This one is short
|
||||||
&SAML;
|
&SAML;
|
||||||
&SecurityVulnerabilities;
|
&SecurityVulnerabilities;
|
||||||
&Clustering;
|
&Clustering;
|
||||||
|
&ApplicationClustering;
|
||||||
&Migration;
|
&Migration;
|
||||||
|
|
||||||
</book>
|
</book>
|
||||||
|
|
|
@ -291,6 +291,51 @@
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>auth-server-url-for-backend-requests</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Alternative location of auth-server-url used just for backend requests. It must be absolute URI. Useful
|
||||||
|
especially in cluster (see <link linkend="relative-uri-optimization">Relative URI Optimization</link>) or if you would like to use <emphasis>https</emphasis> for browser requests
|
||||||
|
but stick with <emphasis>http</emphasis> for backend requests etc.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>always-refresh-token</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If <emphasis>true</emphasis>, Keycloak will refresh token in every request. More info in <link linkend="refresh-token-each-req">Refresh token in each request</link> .
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>register-node-at-startup</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If <emphasis>true</emphasis>, then adapter will send registration request to Keycloak. It's <emphasis>false</emphasis>
|
||||||
|
by default as useful just in cluster (See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>register-node-period</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Period for re-registration adapter to Keycloak. Useful in cluster. See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link> for details.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>token-store</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Possible values are <emphasis>session</emphasis> and <emphasis>cookie</emphasis>. Default is <emphasis>session</emphasis>,
|
||||||
|
which means that adapter stores account info in HTTP Session. Alternative <emphasis>cookie</emphasis> means storage of info in cookie.
|
||||||
|
See <link linkend="stateless-token-store">Stateless token store</link> for details.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
254
docbook/reference/en/en-US/modules/application-clustering.xml
Normal file
254
docbook/reference/en/en-US/modules/application-clustering.xml
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
<chapter id="applicationClustering">
|
||||||
|
<title>Application Clustering</title>
|
||||||
|
|
||||||
|
<para>This chapter is focused on clustering support for your own AS7, EAP6 or Wildfly applications, which are secured by Keycloak.
|
||||||
|
We support various deployment scenarios according if your application is:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
stateless or stateful
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
distributable (replicated http session) or non-distributable and just relying on sticky sessions provided by loadbalancer
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
deployed on same or different cluster hosts where keycloak servers are deployed
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The situation is a bit tricky as application communicates with Keycloak directly within user's browser (for example redirecting to login screen),
|
||||||
|
but there is also backend (out-of-bound) communication between keycloak and application, which is hidden from end-user
|
||||||
|
and his browser and hence can't rely on sticky sessions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="stateless-token-store">
|
||||||
|
<title>Stateless token store</title>
|
||||||
|
<para>
|
||||||
|
By default, the servlet web application secured by Keycloak uses HTTP session to store information about authenticated
|
||||||
|
user account. This means that this info could be replicated across cluster and your application will safely survive
|
||||||
|
failover of some cluster node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
However if you don't need or don't want to use HTTP Session, you may alternatively save all info about authenticated
|
||||||
|
account into cookie. This is useful especially if your application is:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
stateless application without need of HTTP Session, but with requirement to be safe to failover of some cluster node
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
stateful application, but you don't want sensitive token data to be saved in HTTP session
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
stateless application relying on loadbalancer, which is not aware of sticky sessions (in this case cookie is your only way)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To configure this, you can add this line to configuration of your adapter in <literal>WEB-INF/keycloak.json</literal> of your application:
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
"token-store": "cookie"
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Default value of <literal>token-store</literal> is <literal>session</literal>, hence saving data in HTTP session. One disadvantage of cookie store is,
|
||||||
|
that whole info about account is passed in cookie KEYCLOAK_ADAPTER_STATE in each HTTP request. Hence it's not the best for network performance.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="relative-uri-optimization">
|
||||||
|
<title>Relative URI optimization</title>
|
||||||
|
<para>
|
||||||
|
In many deployment scenarios will be Keycloak and secured applications deployed on same cluster hosts. For this case Keycloak
|
||||||
|
already provides option to use relative URI as value of option <emphasis>auth-server-url</emphasis> in <literal>WEB-INF/keycloak.json</literal> .
|
||||||
|
In this case, the URI of Keycloak server is resolved from the URI of current request.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example if your loadbalancer is on <emphasis>https://loadbalancer.com/myapp</emphasis> and auth-server-url is <emphasis>/auth</emphasis>,
|
||||||
|
then relative URI of Keycloak is resolved to be <emphasis>https://loadbalancer.com/myapp</emphasis> .
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For cluster setup, it may be even better to use option <emphasis>auth-server-url-for-backend-request</emphasis> . This allows to configure
|
||||||
|
that backend requests between Keycloak and your application will be sent directly to same cluster host without additional
|
||||||
|
round-trip through loadbalancer. So for this, it's good to configure values in <literal>WEB-INF/keycloak.json</literal> like this:
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
"auth-server-url": "/auth",
|
||||||
|
"auth-server-url-for-backend-requests": "http://${jboss.host.name}:8080/auth"
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This would mean that browser requests (like redirecting to Keycloak login screen) will be still resolved relatively
|
||||||
|
to current request URI like <emphasis>https://loadbalancer.com/myapp</emphasis>, but backend (out-of-bound) requests between keycloak
|
||||||
|
and your app are send always to same cluster host with application .
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that additionally to network optimization,
|
||||||
|
you may not need "https" in this case as application and keycloak are communicating directly within same cluster host.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="admin-url-configuration">
|
||||||
|
<title>Admin URL configuration</title>
|
||||||
|
<para>
|
||||||
|
Admin URL for particular application can be configured in Keycloak admin console. It's used by Keycloak server to
|
||||||
|
send backend requests to application for various tasks, like logout users or push revocation policies.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example logout of user from Keycloak works like this:
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
User sends logout request from one of applications where he is logged.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Then application will send logout request to Keycloak
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Keycloak server logout user in itself, and then it re-sends logout request by backend channel to all
|
||||||
|
applications where user is logged. Keycloak is using admin URL for this. So logout is propagated to all apps.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You may again use relative values for admin URL, but in cluster it may not be the best similarly like in <link linkend='relative-uri-optimization'>previous section</link> .
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some examples of possible values of admin URL are:
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>http://${jboss.host.name}:8080/myapp</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is best choice if "myapp" is deployed on same cluster hosts like Keycloak and is distributable.
|
||||||
|
In this case Keycloak server sends logout request to itself, hence no communication with loadbalancer
|
||||||
|
or other cluster nodes and no additional network traffic.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that since the application is distributable,
|
||||||
|
the backend request sent by Keycloak could be served on any application cluster node as invalidation
|
||||||
|
of HTTP Session on <emphasis>node1</emphasis> will propagate the invalidation to other cluster nodes due to replicated HTTP sessions.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>http://${application.session.host}:8080/myapp</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Keycloak will track hosts where is particular HTTP Session served and it will send session
|
||||||
|
invalidation message to proper cluster node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example application is deployed on <emphasis>http://node1:8080/myapp</emphasis> and <emphasis>http://node2:8080/myapp</emphasis> .
|
||||||
|
Now HTTP Session <emphasis>session1</emphasis> is sticky-session served on cluster node <emphasis>node2</emphasis> .
|
||||||
|
When keycloak invalidates this session, it will send request directly to <emphasis>http://node2:8080/myapp</emphasis> .
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is ideal configuration for distributable applications deployed on different host than keycloak
|
||||||
|
or for non-distributable applications deployed either on same or different nodes than keycloak.
|
||||||
|
Good thing is that it doesn't send requests through load-balancer and hence helps to reduce network traffic.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="registration-app-nodes">
|
||||||
|
<title>Registration of application nodes to Keycloak</title>
|
||||||
|
<para>
|
||||||
|
Previous section describes how can Keycloak send logout request to proper application node. However in some cases admin
|
||||||
|
may want to propagate admin tasks to all registered cluster nodes, not just one of them. For example push new notBefore
|
||||||
|
for realm or application, or logout all users from all applications on all cluster nodes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In this case Keycloak should
|
||||||
|
be aware of all application cluster nodes, so it could send event to all of them. To achieve this, we support auto-discovery mechanism:
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Once new application node joins cluster, it sends registration request to Keycloak server
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The request may be re-sent to Keycloak in configured periodic intervals
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If Keycloak won't receive re-registration request within specified timeout (should be greater than period from point 2)
|
||||||
|
then it automatically unregister particular node
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Node is also unregistered in Keycloak when it sends unregistration request, which is usually during node
|
||||||
|
shutdown or application undeployment. This may not work properly for forced shutdown when
|
||||||
|
undeployment listeners are not invoked, so here you need to rely on automatic unregistration from point 3 .
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Sending startup registrations and periodic re-registration is disabled by default, as it's main usecase is just
|
||||||
|
cluster deployment. In <literal>WEB-INF/keycloak.json</literal> of your application, you can specify:
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
"register-node-at-startup": true,
|
||||||
|
"register-node-period": 600,
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
which means that registration is sent at startup (accurately when 1st request is served by the application node)
|
||||||
|
and then it's resent each 10 minutes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In Keycloak admin console you can specify the maximum node re-registration timeout (makes sense to have it
|
||||||
|
bigger than <emphasis>register-node-period</emphasis> from adapter configuration for particular application). Also you
|
||||||
|
can manually add and remove cluster nodes in admin console, which is useful if you don't want to rely on adapter's
|
||||||
|
automatic registration or if you want to remove stale application nodes, which weren't unregistered
|
||||||
|
(for example due to forced shutdown).
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="refresh-token-each-req">
|
||||||
|
<title>Refresh token in each request</title>
|
||||||
|
<para>
|
||||||
|
By default, application adapter tries to refresh access token when it's expired (period can be specified as <link linkend='token-timeouts'>Access Token Lifespan</link>) .
|
||||||
|
However if you don't want to rely on the fact, that Keycloak is able to successfully propagate admin events like logout
|
||||||
|
to your application nodes, then you have possibility to configure adapter to refresh access token in each HTTP request.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In <literal>WEB-INF/keycloak.json</literal> you can configure:
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
"always-refresh-token": true
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that this has big performance impact. It's useful just if performance is not priority, but security is critical
|
||||||
|
and you can't rely on logout and push notBefore propagation from Keycloak to applications.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -33,7 +33,7 @@
|
||||||
in that it allow you to force a relogin after a set timeframe.
|
in that it allow you to force a relogin after a set timeframe.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section id="token-timeouts">
|
||||||
<title>Token Timeouts</title>
|
<title>Token Timeouts</title>
|
||||||
<para>
|
<para>
|
||||||
The <literal>Access Token Lifespan</literal> is how long an access token is valid for. An access token contains everything
|
The <literal>Access Token Lifespan</literal> is how long an access token is valid for. An access token contains everything
|
||||||
|
|
Loading…
Reference in a new issue