239 lines
14 KiB
Text
239 lines
14 KiB
Text
[[_kerberos]]
|
|
|
|
=== Kerberos
|
|
|
|
{project_name} supports login with a Kerberos ticket through the SPNEGO protocol.
|
|
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, {project_name} also supports login with Kerberos username/password.
|
|
|
|
A typical use case for web authentication is the following:
|
|
|
|
. User logs into his desktop (Such as a Windows machine in Active Directory domain or Linux machine with Kerberos integration enabled).
|
|
. User then uses his browser (IE/Firefox/Chrome) to access a web application secured by {project_name}.
|
|
. Application redirects to {project_name} login.
|
|
. {project_name} renders HTML login screen together with status 401 and HTTP header `WWW-Authenticate: Negotiate`
|
|
. In case that the browser has Kerberos ticket from desktop login, it transfers the desktop sign on information to the {project_name}
|
|
in header `Authorization: Negotiate 'spnego-token'` . Otherwise it just displays the login screen.
|
|
. {project_name} validates token from the browser and authenticates the 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).
|
|
. {project_name} returns back to the application.
|
|
Communication between {project_name} and application happens through OpenID Connect or SAML messages.
|
|
The fact that {project_name} was authenticated through Kerberos is hidden from the application.
|
|
So {project_name} acts as broker to Kerberos/SPNEGO login.
|
|
|
|
For setup there are 3 main parts:
|
|
|
|
. Setup and configuration of Kerberos server (KDC)
|
|
. Setup and configuration of {project_name} server
|
|
. Setup and configuration of client machines
|
|
|
|
==== Setup of Kerberos server
|
|
|
|
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.
|
|
|
|
At least you will need to:
|
|
|
|
* 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.
|
|
* Add service principal for "HTTP" service.
|
|
For example if your {project_name} server will be running on `www.mydomain.org` you may need to add principal `HTTP/www.mydomain.org@MYDOMAIN.ORG`
|
|
assuming that MYDOMAIN.ORG will be your Kerberos realm.
|
|
+
|
|
For example on MIT Kerberos you can run a "kadmin" session.
|
|
If you are on the same machine where is MIT Kerberos, you can simply use the command:
|
|
|
|
[source]
|
|
----
|
|
sudo kadmin.local
|
|
----
|
|
Then add HTTP principal and export his key to a keytab file with the commands like:
|
|
|
|
[source]
|
|
----
|
|
|
|
addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
----
|
|
|
|
The Keytab file `/tmp/http.keytab` will need to be accessible on the host where {project_name} server will be running.
|
|
|
|
==== Setup and configuration of {project_name} server
|
|
|
|
You need to install a kerberos client on your machine. This is also platform dependent.
|
|
If you are on Fedora, Ubuntu or RHEL, you can install the package `freeipa-client`, which contains a Kerberos client and several other utilities.
|
|
Configure the kerberos client (on Linux it's in file `/etc/krb5.conf` ). 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 the `domain_realm` section like this:
|
|
|
|
[source]
|
|
----
|
|
[domain_realm]
|
|
.mydomain.org = MYDOMAIN.ORG
|
|
mydomain.org = MYDOMAIN.ORG
|
|
----
|
|
|
|
Next you need to export the keytab file with the HTTP principal and make sure the file is accessible to the process under which {project_name} server is running.
|
|
For production, it's ideal if it's readable just by this process and not by someone else.
|
|
For the MIT Kerberos example above, we already exported keytab to `/tmp/http.keytab` . If your KDC and {project_name} are running on same host,
|
|
you have that file already available.
|
|
|
|
===== Enable SPNEGO Processing
|
|
|
|
{project_name} does not have the SPNEGO protocol support turned on by default. So, you have to go to the <<_authentication-flows, browser flow>>
|
|
and enable `Kerberos`.
|
|
|
|
.Browser Flow
|
|
image:{project_images}/browser-flow.png[]
|
|
|
|
Switch the `Kerberos` requirement from _disabled_ to either _alternative_ or _required_. _Alternative_ basically means that Kerberos is optional. If
|
|
the user's browser hasn't been configured to work with SPNEGO/Kerberos, then {project_name} will fall back to the regular login screens. If you set the requirement
|
|
to _required_ then all users must have Kerberos enabled for their browser.
|
|
|
|
===== Configure Kerberos User Storage Federation Provider
|
|
|
|
Now that the SPNEGO protocol is turned on at the authentication server, you'll need to configure how {project_name} interprets the Kerberos ticket.
|
|
This is done through <<_user-storage-federation,User Storage Federation>>. We have 2 different federation providers with Kerberos authentication support.
|
|
|
|
If you want to authenticate with Kerberos backed by an LDAP server, you have to first configure the <<_ldap, LDAP Federation Provider>>.
|
|
If you look at the configuration page for your LDAP provider you'll see a `Kerberos Integration` section.
|
|
|
|
.LDAP Kerberos Integration
|
|
image:{project_images}/ldap-kerberos.png[]
|
|
|
|
Turning on the switch `Allow Kerberos authentication` will make {project_name} use the Kerberos principal to lookup information about the user so that it can
|
|
be imported into the {project_name} environment.
|
|
|
|
If your Kerberos solution is not backed by an LDAP server, you have to use the `Kerberos` User Storage Federation Provider. Go to the `User Federation`
|
|
left menu item and select `Kerberos` from the `Add provider` select box.
|
|
|
|
.Kerberos User Storage Provider
|
|
image:{project_images}/kerberos-provider.png[]
|
|
|
|
This provider parses the Kerberos ticket for simple principal information and does a small import into the local {project_name} database.
|
|
User profile information like first name, last name, and email are not provisioned.
|
|
|
|
==== Setup and configuration of client machines
|
|
|
|
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 link:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_applications_for_sso[configuring Firefox for Kerberos] if you are using that browser.
|
|
URI `.mydomain.org` must be allowed in the `network.negotiate-auth.trusted-uris` config option.
|
|
|
|
In a 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.
|
|
|
|
ifeval::[{project_community}==true]
|
|
==== Example setups
|
|
|
|
For easier testing with Kerberos, we provided some example setups to test.
|
|
|
|
===== {project_name} and FreeIPA docker image
|
|
|
|
Once you install https://www.docker.com/[docker], you can run docker image with FreeIPA server installed.
|
|
FreeIPA provides integrated security solution with MIT Kerberos and 389 LDAP server among other things . The image provides also {project_name}
|
|
server configured with LDAP Federation provider and enabled SPNEGO/Kerberos authentication against the FreeIPA server.
|
|
See details https://github.com/mposolda/keycloak-freeipa-docker/blob/master/README.md[here] .
|
|
|
|
===== ApacheDS testing Kerberos server
|
|
|
|
For quick testing and unit tests, we use a very simple http://directory.apache.org/apacheds/[ApacheDS] Kerberos server.
|
|
You need to build {project_name} from sources and then run the Kerberos server with maven-exec-plugin from our testsuite.
|
|
See details https://github.com/keycloak/keycloak/blob/master/docs/tests.md#kerberos-server[here] .
|
|
endif::[]
|
|
|
|
==== Credential Delegation
|
|
|
|
Kerberos 5 supports the concept of credential delegation. In this scenario, your applications may want access to the Kerberos ticket so that
|
|
they can re-use it to interact with other services secured by Kerberos. Since the SPNEGO protocol is processed in the {project_name} server,
|
|
you have to propagate the GSS credential to your application
|
|
within the OpenID Connect token claim or a SAML assertion attribute that is transmitted to your application from the {project_name} server.
|
|
To have this claim inserted into the token or assertion, each application will need to enable the built-in protocol mapper called `gss delegation credential`.
|
|
This is enabled in the `Mappers` tab of the application's
|
|
client page. See <<_protocol-mappers, Protocol Mappers>> chapter for more details.
|
|
|
|
Applications will need to deserialize the claim it receives from {project_name} before it can use it to make GSS calls against other services.
|
|
Once you deserialize the credential from the access token to the GSSCredential object, the GSSContext will need to be created with this credential
|
|
passed to the method `GSSManager.createContext` for example like this:
|
|
|
|
[source,java]
|
|
----
|
|
// Obtain accessToken in your application.
|
|
KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) servletReq.getUserPrincipal();
|
|
AccessToken accessToken = keycloakPrincipal.getKeycloakSecurityContext().getToken();
|
|
|
|
// Retrieve kerberos credential from accessToken and deserialize it
|
|
String serializedGssCredential = (String) accessToken.getOtherClaims().
|
|
get(org.keycloak.common.constants.KerberosConstants.GSS_DELEGATION_CREDENTIAL);
|
|
|
|
GSSCredential deserializedGssCredential = org.keycloak.common.util.KerberosSerializationUtils.
|
|
deserializeCredential(serializedGssCredential);
|
|
|
|
// Create GSSContext to call other kerberos-secured services
|
|
GSSContext context = gssManager.createContext(serviceName, krb5Oid,
|
|
deserializedGssCredential, GSSContext.DEFAULT_LIFETIME);
|
|
----
|
|
|
|
ifeval::[{project_community}==true]
|
|
We have an example, that shows this in detail.
|
|
It's in `examples/kerberos` in the {project_name} example distribution or demo distribution download.
|
|
You can also check the example sources directly https://github.com/keycloak/keycloak/tree/master/examples/kerberos[here] .
|
|
endif::[]
|
|
|
|
|
|
Note that you also need to configure `forwardable` kerberos tickets in `krb5.conf` file and add support for delegated credentials to your browser.
|
|
|
|
WARNING: Credential delegation has some security implications so only use it if you really need it.
|
|
It's highly recommended to use it together with HTTPS.
|
|
See for example https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_applications_for_sso[this article] for more details.
|
|
|
|
==== Cross-realm trust
|
|
|
|
In the Kerberos V5 protocol, the `realm` is a set of Kerberos principals defined in the Kerberos database (typically LDAP server).
|
|
The Kerberos protocol has a concept of cross-realm trust. For example, if there are 2 kerberos realms A and B, the cross-realm trust
|
|
will allow the users from realm A to access resources (services) of realm B. This means that realm B trusts the realm A.
|
|
|
|
.Kerberos cross-realm trust
|
|
image:images/kerberos-trust-basic.png[]
|
|
|
|
|
|
The {project_name} server has support for cross-realm trust. There are few things which need to be done to achieve this:
|
|
|
|
* Configure the Kerberos servers for the cross-realm trust. This step is dependent on the concrete Kerberos server implementations used.
|
|
In general, it is needed to add the Kerberos principal `krbtgt/B@A` to both Kerberos databases of realm A and B. It is needed that
|
|
this principal has same keys on both Kerberos realms. This is usually achieved when the principals have same password, key version number
|
|
and there are same ciphers used in both realms. It is recommended to consult the Kerberos server documentation for more details.
|
|
|
|
NOTE: The cross-realm trust is unidirectional by default. If you want bidirectional trust to have realm A also trust realm B,
|
|
you must also add the principal `krbtgt/A@B` to both Kerberos databases. However, trust is transitive by default. If realm B
|
|
trusts realm A and realm C trusts realm B, then realm C automatically trusts realm A without a need to have principal `krbtgt/C@A`
|
|
available. Some additional configuration (for example `capaths`) may be needed to configure on Kerberos client side, so that
|
|
the clients are able to find the trust path. Consult the Kerberos documentation for more details.
|
|
|
|
|
|
* Configure {project_name} server
|
|
|
|
** If you use an LDAP storage provider with Kerberos support, you need to configure the server principal for realm B as in this
|
|
example: `HTTP/mydomain.com@B`. The LDAP server must be able to find the users from realm A if you want users from realm A to
|
|
successfully authenticate to {project_name}, as {project_name} server must be able to do SPNEGO flow and then find the users.
|
|
For example, kerberos principal user `john@A` must be available as a user in the LDAP under an LDAP DN
|
|
such as `uid=john,ou=People,dc=example,dc=com`. If you want both users from realm A and B to authenticate, you need to ensure
|
|
that LDAP is able to find users from both realms A and B. We want to improve this limitation in future versions, so you can
|
|
potentially create more separate LDAP providers for separate realms and ensure that SPNEGO works for both of them.
|
|
|
|
** If you use a Kerberos user storage provider (typically the Kerberos without LDAP integration), you need to configure the
|
|
server principal as `HTTP/mydomain.com@B` and users from both Kerberos realms A and B should be able to authenticate.
|
|
|
|
WARNING: For the Kerberos user storage provider, it is recommended that there are no conflicting users among kerberos realms. If
|
|
conflicting users exist, they will be mapped to the same {project_name} user. This is also something, which we want to improve in
|
|
future versions and provide some more flexible mappings from Kerberos principals to {project_name} usernames.
|
|
|
|
==== Troubleshooting
|
|
|
|
If you have issues, we recommend that you enable additional logging to debug the problem:
|
|
|
|
* Enable `Debug` flag in admin console for Kerberos or LDAP federation providers
|
|
* Enable TRACE logging for category `org.keycloak` in logging section of `standalone/configuration/standalone.xml` to receive more info `standalone/log/server.log`
|
|
* Add system properties `-Dsun.security.krb5.debug=true` and `-Dsun.security.spnego.debug=true`
|
|
|