297 lines
No EOL
17 KiB
XML
297 lines
No EOL
17 KiB
XML
<!--
|
|
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
~ and other contributors as indicated by the @author tags.
|
|
~
|
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
~ you may not use this file except in compliance with the License.
|
|
~ You may obtain a copy of the License at
|
|
~
|
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
~
|
|
~ Unless required by applicable law or agreed to in writing, software
|
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
~ See the License for the specific language governing permissions and
|
|
~ limitations under the License.
|
|
-->
|
|
|
|
<chapter id="kerberos">
|
|
<title>Kerberos brokering</title>
|
|
<para>
|
|
Keycloak supports login with Kerberos ticket through SPNEGO. SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) is used
|
|
to authenticate transparently through the web browser after the user has been authenticated when logging-in his session.
|
|
For non-web cases or when ticket is not available during login, Keycloak also supports login with Kerberos username/password.
|
|
</para>
|
|
<para>
|
|
A typical use case for web authentication is the following:
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>
|
|
User logs into his desktop (Such as a Windows machine in Active Directory domain or Linux machine with Kerberos integration enabled).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
User then uses his browser (IE/Firefox/Chrome) to access a web application secured by Keycloak.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Application redirects to Keycloak login.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Keycloak sends HTML login screen together with status 401 and HTTP header <literal>WWW-Authenticate: Negotiate</literal>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
In case that browser has Kerberos ticket from desktop login, it transfers the desktop sign on information to the
|
|
Keycloak in header <literal>Authorization: Negotiate 'spnego-token'</literal> . Otherwise it just displays login screen.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Keycloak validates token from browser and authenticate user. It provisions user data from LDAP (in case of
|
|
LDAPFederationProvider with Kerberos authentication support) or let user to update his profile and prefill data
|
|
(in case of KerberosFederationProvider).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Keycloak returns back to the application. Communication between Keycloak and application happens through OpenID
|
|
Connect or SAML messages. The fact that Keycloak was authenticated through Kerberos is hidden from the application.
|
|
So Keycloak acts as broker to Kerberos/SPNEGO login.
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<para>
|
|
For setup there are 3 main parts:
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>
|
|
Setup and configuration of Kerberos server (KDC)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Setup and configuration of Keycloak server
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Setup and configuration of client machines
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<section>
|
|
<title>Setup of Kerberos server</title>
|
|
<para>
|
|
This is platform dependent. Exact steps depend on your OS and the Kerberos vendor you're going to use.
|
|
Consult Windows Active Directory, MIT Kerberos and your OS documentation for how exactly to setup and configure Kerberos server.
|
|
</para>
|
|
<para>
|
|
At least you will need to:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Add some user principals to your Kerberos database. You can also integrate your Kerberos with LDAP,
|
|
which means that user accounts will be provisioned from LDAP server.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Add service principal for "HTTP" service. For example if your Keycloak server will be running on
|
|
<literal>www.mydomain.org</literal> you may need to add principal <literal>HTTP/www.mydomain.org@MYDOMAIN.ORG</literal>
|
|
assuming that MYDOMAIN.ORG will be your Kerberos realm.
|
|
</para>
|
|
<para>
|
|
For example on MIT Kerberos you can run "kadmin" session. If you are on same machine where is MIT Kerberos, you can simply use command:
|
|
<programlisting><![CDATA[
|
|
sudo kadmin.local
|
|
]]></programlisting>
|
|
Then add HTTP principal and export his key to keytab file with the commands like:
|
|
<programlisting><![CDATA[
|
|
addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
]]></programlisting>
|
|
Keytab file <literal>/tmp/http.keytab</literal> will need to be accessible on the host where keycloak server will be running.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Setup and configuration of Keycloak server</title>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Install kerberos client. This is again platform dependent. If you are on Fedora, Ubuntu or RHEL, you can install package <literal>freeipa-client</literal>,
|
|
which contains Kerberos client and bunch of other stuff.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Configure kerberos client (on linux it's in file <literal>/etc/krb5.conf</literal> ). You need to put your Kerberos realm and at least
|
|
configure the Http domains your server will be running on. For the example realm MYDOMAIN.ORG you may configure <literal>domain_realm</literal> section like this:
|
|
<programlisting><![CDATA[
|
|
[domain_realm]
|
|
.mydomain.org = MYDOMAIN.ORG
|
|
mydomain.org = MYDOMAIN.ORG
|
|
]]></programlisting>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Export keytab file with HTTP principal and make sure the file is accessible to the process under which Keycloak
|
|
server is running. For production, it's ideal if it's readable just by this process and not by someone else.
|
|
For MIT Kerberos example above, we already exported keytab to <literal>/tmp/http.keytab</literal> . If your KDC and Keycloak
|
|
are running on same host, you have file already available.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Run Keycloak server and configure SPNEGO/Kerberos authentication in Keycloak admin console. Keycloak supports Kerberos authentication
|
|
through <link linkend='user_federation'>Federation provider SPI</link> . We have 2 federation providers with Kerberos authentication support:
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>Kerberos</term>
|
|
<listitem>
|
|
<para>
|
|
This provider is useful if you want to authenticate with Kerberos <literal>NOT</literal> backed by LDAP server.
|
|
In this case, users are usually created to Keycloak database after first successful SPNEGO/Kerberos login
|
|
and they may need to update profile after first login, as Kerberos protocol itself doesn't provision
|
|
any data like first name, last name or email.
|
|
</para>
|
|
<para>
|
|
You can also choose if users can authenticate with classic username/password. In this case, if user doesn't have SPNEGO ticket available,
|
|
Keycloak will display login screen and user can fill his Kerberos username and password on login screen. Username/password works also for non-web flows like
|
|
<link linkend='direct-access-grants'>Direct Access grants</link>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>LDAP</term>
|
|
<listitem>
|
|
<para>
|
|
This provider is useful if you want to authenticate with Kerberos backed by LDAP server.
|
|
In this case, data about users are provisioned from LDAP server after successful Kerberos authentication.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Finally you may need to check the Kerberos authenticator correctly configured. You can go to <literal>Authentication</literal> tab in
|
|
admin console and select <literal>Browser</literal> flow. Here you will see <literal>Kerberos</literal> authenticator, which is used by Keycloak for SPNEGO
|
|
handshake with client (exchange <literal>Negotiate</literal> header etc.). By default it's disabled, so Keycloak doesn't ask for Negotiate header, however once you
|
|
configured federation provider in previous step, it's automatically switched to <literal>ALTERNATIVE</literal>. So defacto you don't need to do anything, just
|
|
check that it's really switched to Alternative.
|
|
</para>
|
|
<para>
|
|
Alternative means that Keycloak tries to ask browser for Negotiate header, but if it's not available, it will continue on next authenticator (which usually means
|
|
displaying username/password form to user). You can switch to <literal>REQUIRED</literal> if you want to enforce login with
|
|
kerberos ticket and not allow fallback to username/password form.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Setup and configuration of client machines</title>
|
|
<para>
|
|
Clients need to install kerberos client and setup krb5.conf as described above. Additionally they need to enable SPNEGO login support in their browser.
|
|
See for example <ulink url="http://www.microhowto.info/howto/configure_firefox_to_authenticate_using_spnego_and_kerberos.html">this</ulink>
|
|
for more info about Firefox. URI <literal>.mydomain.org</literal> must be allowed in <literal>network.negotiate-auth.trusted-uris</literal> config option.
|
|
</para>
|
|
<para>
|
|
In windows domain, clients usually don't need to configure anything special as IE is already able to participate in SPNEGO authentication for the windows domain.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Example setups</title>
|
|
<para>
|
|
For easier testing with Kerberos, we provided some example setups to test.
|
|
</para>
|
|
<section>
|
|
<title>Keycloak and FreeIPA docker image</title>
|
|
<para>
|
|
Once you install <ulink url="https://www.docker.com/">docker</ulink>, you can run docker image with <ulink url="http://www.freeipa.org/">FreeIPA</ulink>
|
|
server installed. FreeIPA provides integrated security solution with MIT Kerberos and 389 LDAP server among other things . The image provides
|
|
also Keycloak server configured with LDAP Federation provider and enabled SPNEGO/Kerberos authentication against the FreeIPA server.
|
|
See details <ulink url="https://github.com/mposolda/keycloak-freeipa-docker/blob/master/README.md">here</ulink> .
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>ApacheDS testing Kerberos server</title>
|
|
<para>
|
|
For quick testing and unit tests, we use very simple <ulink url="http://directory.apache.org/apacheds/">ApacheDS</ulink> Kerberos server.
|
|
You need to build Keycloak from sources and then run Kerberos server with maven-exec-plugin from our testsuite. See details
|
|
<ulink url="https://github.com/keycloak/keycloak/blob/master/misc/Testsuite.md#kerberos-server">here</ulink> .
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Credential delegation</title>
|
|
<para>
|
|
One scenario supported by Kerberos 5 is credential delegation. In this case when user receives forwardable TGT and authenticates to the web server,
|
|
then web server might be able to reuse the ticket and forward it to another service secured by Kerberos (for example LDAP server or IMAP server).
|
|
</para>
|
|
<para>
|
|
The scenario is supported by Keycloak, but there is tricky thing that SPNEGO authentication is done by Keycloak server but
|
|
GSS credential will need to be used by your application. So you need to enable built-in <literal>gss delegation credential</literal> protocol mapper
|
|
in admin console for your application. This will cause that Keycloak will deserialize GSS credential and transmit it to the application
|
|
in access token. Application will need to deserialize it and use it for further GSS calls against other services. We have an example, which is showing it in details. It's in <literal>examples/kerberos</literal>
|
|
in the Keycloak example distribution or demo distribution download. You can also check the example sources directly <ulink url="https://github.com/keycloak/keycloak/blob/master/examples/kerberos">here</ulink> .
|
|
</para>
|
|
<para>
|
|
Once you deserialize the credential from the access token to the GSSCredential object, then GSSContext will need to
|
|
be created with this credential passed to the method <literal>GSSManager.createContext</literal> for example like this:
|
|
<programlisting><![CDATA[
|
|
GSSContext context = gssManager.createContext(serviceName, krb5Oid,
|
|
deserializedGssCredFromKeycloakAccessToken, GSSContext.DEFAULT_LIFETIME);
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Note that you also need to configure <literal>forwardable</literal> kerberos tickets in <literal>krb5.conf</literal> file
|
|
and add support for delegated credentials to your browser. For details, see the kerberos example from Keycloak examples set as mentioned above.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
Credential delegation has some security implications. So enable the protocol claim and support in browser just if you really need it.
|
|
It's highly recommended to use it together with HTTPS. See for example
|
|
<ulink url="http://www.microhowto.info/howto/configure_firefox_to_authenticate_using_spnego_and_kerberos.html#idp27072">this article</ulink>
|
|
for details.
|
|
</para>
|
|
</warning>
|
|
</section>
|
|
<section>
|
|
<title>Troubleshooting</title>
|
|
<para>
|
|
If you have issues, we recommend to enable more logging by:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Enable <literal>Debug</literal> flag in admin console for Kerberos or LDAP federation providers
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Enable TRACE logging for category <literal>org.keycloak</literal> in logging section of <literal>$WILDFLY_HOME/standalone/configuration/standalone.xml</literal>
|
|
to receive more info <literal>$WILDFLY_HOME/standalone/log/server.log</literal>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Add system properties <literal>-Dsun.security.krb5.debug=true</literal> and <literal>-Dsun.security.spnego.debug=true</literal>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
</chapter> |