JBoss.orgCommunity Documentation

Chapter 8. Adapters

8.1. General Adapter Config
8.2. JBoss/Wildfly Adapter
8.2.1. Adapter Installation
8.2.2. Required Per WAR Configuration
8.2.3. Securing WARs via Keycloak Subsystem
8.3. Tomcat 6, 7 and 8 Adapters
8.3.1. Adapter Installation
8.3.2. Required Per WAR Configuration
8.4. Jetty 9.x Adapters
8.4.1. Adapter Installation
8.4.2. Required Per WAR Configuration
8.5. Jetty 8.1.x Adapter
8.5.1. Adapter Installation
8.5.2. Required Per WAR Configuration
8.6. JBoss Fuse and Apache Karaf Adapter
8.7. Javascript Adapter
8.7.1. Session status iframe
8.7.2. Older browsers
8.7.3. JavaScript Adapter reference
8.8. Spring Boot Adapter
8.8.1. Adapter Installation
8.8.2. Required Spring Boot Adapter Configuration
8.9. Installed Applications
8.9.1. http://localhost
8.9.2. urn:ietf:wg:oauth:2.0:oob
8.10. Logout
8.11. Multi Tenancy
8.12. JAAS plugin

Keycloak can secure a wide variety of application types. This section defines which application types are supported and how to configure and install them so that you can use Keycloak to secure your applications.

Each adapter supported by Keycloak can be configured by a simple JSON text file. This is what one might look like:

{
  "realm" : "demo",
  "resource" : "customer-portal",
  "realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB",
  "auth-server-url" : "https://localhost:8443/auth",
  "ssl-required" : "external",
  "use-resource-role-mappings" : false,
  "enable-cors" : true,
  "cors-max-age" : 1000,
  "cors-allowed-methods" : "POST, PUT, DELETE, GET",
  "bearer-only" : false,
  "enable-basic-auth" : false,
  "expose-token" : true,
   "credentials" : {
      "secret" : "234234-234234-234234"
   },

   "connection-pool-size" : 20,
   "disable-trust-manager": false,
   "allow-any-hostname" : false,
   "truststore" : "path/to/truststore.jks",
   "truststore-password" : "geheim",
   "client-keystore" : "path/to/client-keystore.jks",
   "client-keystore-password" : "geheim",
   "client-key-password" : "geheim"
}

Some of these configuration switches may be adapter specific and some are common across all adapters. For Java adapters you can use ${...} enclosure as System property replacement. For example ${jboss.server.config.dir}. Also, you can obtain a template for this config file from the admin console. Go to the realm and select the application you want a template for. Go to the Installation tab and this will provide you with a template that includes the public key of the realm.

Here is a description of each item:

realm

Name of the realm representing the users of your distributed applications and services. This is REQUIRED.

resource

Username of the application. Each application has a username that is used when the application connects with the Keycloak server to turn an access code into an access token (part of the OAuth 2.0 protocol). This is REQUIRED.

realm-public-key

PEM format of public key. You can obtain this from the administration console. This is REQUIRED.

auth-server-url

The base URL of the Keycloak Server. All other Keycloak pages and REST services are derived from this. It is usually of the form https://host:port/auth This is REQUIRED.

ssl-required

Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS. This is OPTIONAL. The default value is external meaning that HTTPS is required by default for external requests. Valid values are 'all', 'external' and 'none'.

use-resource-role-mappings

If set to true, the adapter will look inside the token for application level role mappings for the user. If false, it will look at the realm level for user role mappings. This is OPTIONAL. The default value is false.

public-client

If set to true, the adapter will not send credentials for the client to Keycloak. The default value is false.

enable-cors

This enables CORS support. It will handle CORS preflight requests. It will also look into the access token to determine valid origins. This is OPTIONAL. The default value is false.

cors-max-age

If CORS is enabled, this sets the value of the Access-Control-Max-Age header. This is OPTIONAL. If not set, this header is not returned in CORS responses.

cors-allowed-methods

If CORS is enabled, this sets the value of the Access-Control-Allow-Methods header. This should be a comma-separated string. This is OPTIONAL. If not set, this header is not returned in CORS responses.

cors-allowed-headers

If CORS is enabled, this sets the value of the Access-Control-Allow-Headers header. This should be a comma-separated string. This is OPTIONAL. If not set, this header is not returned in CORS responses.

bearer-only

This tells the adapter to only do bearer token authentication. That is, it will not do OAuth 2.0 redirects, but only accept bearer tokens through the Authorization header. This is OPTIONAL. The default value is false.

enable-basic-auth

This tells the adapter to also support basic authentication. If this option is enabled, then secret must also be provided. This is OPTIONAL. The default value is false.

expose-token

If true, an authenticated browser client (via a Javascript HTTP invocation) can obtain the signed access token via the URL root/k_query_bearer_token. This is OPTIONAL. The default value is false.

credentials

Specify the credentials of the application. This is an object notation where the key is the credential type and the value is the value of the credential type. Currently only password is supported. This is REQUIRED.

connection-pool-size

Adapters will make separate HTTP invocations to the Keycloak Server to turn an access code into an access token. This config option defines how many connections to the Keycloak Server should be pooled. This is OPTIONAL. The default value is 20.

disable-trust-manager

If the Keycloak Server requires HTTPS and this config option is set to true you do not have to specify a truststore. While convenient, this setting is not recommended as you will not be verifying the host name of the Keycloak Server. This is OPTIONAL. The default value is false.

allow-any-hostname

If the Keycloak Server requires HTTPS and this config option is set to true the Keycloak Server's certificate is validated via the truststore, but host name validation is not done. This is not a recommended. This seting may be useful in test environments This is OPTIONAL. The default value is false.

truststore

This setting is for Java adapters. The value is the file path to a Java keystore file. If you prefix the path with classpath:, then the truststore will be obtained from the deployment's classpath instead. Used for outgoing HTTPS communications to the Keycloak server. Client making HTTPS requests need a way to verify the host of the server they are talking to. This is what the trustore does. The keystore contains one or more trusted host certificates or certificate authorities. You can create this truststore by extracting the public certificate of the Keycloak server's SSL keystore. This is OPTIONAL if ssl-required is none or disable-trust-manager is true.

truststore-password

Password for the truststore keystore. This is REQUIRED if truststore is set.

client-keystore

Not supported yet, but we will support in future versions. This setting is for Java adapters. This is the file path to a Java keystore file. This keystore contains client certificate for two-way SSL when the adapter makes HTTPS requests to the Keycloak server. This is OPTIONAL.

client-keystore-password

Not supported yet, but we will support in future versions. Password for the client keystore. This is REQUIRED if client-keystore is set.

client-key-password

Not supported yet, but we will support in future versions. Password for the client's key. This is REQUIRED if client-keystore is set.

auth-server-url-for-backend-requests

Alternative location of auth-server-url used just for backend requests. It must be absolute URI. Useful especially in cluster (see Relative URI Optimization) or if you would like to use https for browser requests but stick with http for backend requests etc.

always-refresh-token

If true, Keycloak will refresh token in every request. More info in Refresh token in each request .

register-node-at-startup

If true, then adapter will send registration request to Keycloak. It's false by default and useful just in cluster (See Registration of application nodes to Keycloak)

register-node-period

Period for re-registration adapter to Keycloak. Useful in cluster. See Registration of application nodes to Keycloak for details.

token-store

Possible values are session and cookie. Default is session, which means that adapter stores account info in HTTP Session. Alternative cookie means storage of info in cookie. See Stateless token store for details.

principal-attribute

OpenID Connection ID Token attribute to populate the UserPrincipal name with. If token attribute is null, defaults to sub. Possible values are sub, preferred_username, email, name, nickname, given_name, family_name.

To be able to secure WAR apps deployed on JBoss AS 7.1.1, JBoss EAP 6.x, or Wildfly, you must install and configure the Keycloak Subsystem. You then have two options to secure your WARs. You can provide a keycloak config file in your WAR and change the auth-method to KEYCLOAK within web.xml. Alternatively, you don't have to crack open your WARs at all and can apply Keycloak via the Keycloak Subsystem configuration in standalone.xml. Both methods are described in this section.

Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on the Keycloak download site. They are also available as a maven artifact.

Install on Wildfly:

$ cd $WILDFLY_HOME
$ unzip keycloak-wildfly-adapter-dist.zip

Install on JBoss EAP 6.x:

$ cd $JBOSS_HOME
$ unzip keycloak-eap6-adapter-dist.zip

Install on JBoss AS 7.1.1:

$ cd $JBOSS_HOME
$ unzip keycloak-as7-adapter-dist.zip

This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro.

After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration: domain.xml or standalone.xml.

<server xmlns="urn:jboss:domain:1.4">

    <extensions>
        <extension module="org.keycloak.keycloak-subsystem"/>
          ...
    </extensions>

    <profile>
        <subsystem xmlns="urn:jboss:domain:keycloak:1.0"/>
         ...
    </profile>

Note

For AS7, the extension module is org.keycloak.keycloak-as7-sybsystem.

Finally, you must specify a shared keycloak security domain. This security domain should be used with EJBs and other components when you need the security context created in the secured web tier to be propagated to the EJBs (other EE component) you are invoking. Otherwise this configuration is optional.

<server xmlns="urn:jboss:domain:1.4">
 <subsystem xmlns="urn:jboss:domain:security:1.2">
    <security-domains>
...
      <security-domain name="keycloak">
         <authentication>
           <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
                         flag="required"/>
          </authentication>
      </security-domain>
    </security-domains>

For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want to annotate it with the @SecurityDomain annotation as follows:

import org.jboss.ejb3.annotation.SecurityDomain;
import org.jboss.resteasy.annotations.cache.NoCache;

import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.ArrayList;
import java.util.List;

@Path("customers")
@Stateless
@SecurityDomain("keycloak")
public class CustomerService {

    @EJB
    CustomerDB db;

    @GET
    @Produces("application/json")
    @NoCache
    @RolesAllowed("db_user")
    public List<String> getCustomers() {
        return db.getCustomers();
    }
}

We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain annotation when you want to propagate a keycloak security context to the EJB tier.

This section describes how to secure a WAR directly by adding config and editing files within your WAR package.

The first thing you must do is create a keycloak.json adapter config file within the WEB-INF directory of your WAR. The format of this config file is describe in the general adapter configuration section.

Next you must set the auth-method to KEYCLOAK in web.xml. You also have to use standard servlet security to specify role-base constraints on your URLs. Here's an example pulled from one of the examples that comes distributed with Keycloak.


<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

	<module-name>customer-portal</module-name>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admins</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Customers</web-resource-name>
            <url-pattern>/customers/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>KEYCLOAK</auth-method>
        <realm-name>this is ignored currently/realm-name>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
</web-app>

You do not have to crack open a WAR to secure it with Keycloak. Alternatively, you can externally secure it via the Keycloak Subsystem. While you don't have to specify KEYCLOAK as an auth-method, you still have to define the security-constraints in web.xml. You do not, however, have to create a WEB-INF/keycloak.json file. This metadata is instead defined within XML in your server's domain.xml or standalone.xml subsystem configuration section.

<server xmlns="urn:jboss:domain:1.4">

  <profile>
    <subsystem xmlns="urn:jboss:domain:keycloak:1.0">
       <secure-deployment name="WAR MODULE NAME.war">
          <realm>demo</realm>
          <realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA</realm-public-key>
          <auth-server-url>http://localhost:8081/auth</auth-server-url>
          <ssl-required>external</ssl-required>
          <resource>customer-portal</resource>
          <credential name="secret">password</credential>
       </secure-deployment>
    </subsystem>
  </profile>

The security-deployment name attribute identifies the WAR you want to secure. Its value is the module-name defined in web.xml with .war appended. The rest of the configuration corresponds pretty much one to one with the keycloak.json configuration options defined in general adapter configuration. The exception is the credential element.

To make it easier for you, you can go to the Keycloak Adminstration Console and go to the Application/Installation tab of the application this WAR is aligned with. It provides an example XML file you can cut and paste.

There is an additional convenience format for this XML if you have multiple WARs you are deployment that are secured by the same domain. This format allows you to define common configuration items in one place under the realm element.

<subsystem xmlns="urn:jboss:domain:keycloak:1.0">
    <realm name="demo">
        <realm-public-key>MIGfMA0GCSqGSIb3DQEBA</realm-public-key>
        <auth-server-url>http://localhost:8080/auth</auth-server-url>
        <ssl-required>external</ssl-required>
    </realm>
    <secure-deployment name="customer-portal.war">
        <realm>demo</realm>
        <resource>customer-portal</resource>
        <credential name="secret">password</credential>
    </secure-deployment>
    <secure-deployment name="product-portal.war">
        <realm>demo</realm>
        <resource>product-portal</resource>
        <credential name="secret">password</credential>
    </secure-deployment>
    <secure-deployment name="database.war">
        <realm>demo</realm>
        <resource>database-service</resource>
        <bearer-only>true</bearer-only>
    </secure-deployment>
</subsystem>

            

To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 adapter into your Tomcat installation. You then have to provide some extra configuration in each WAR you deploy to Tomcat. Let's go over these steps.

This section describes how to secure a WAR directly by adding config and editing files within your WAR package.

The first thing you must do is create a META-INF/context.xml file in your WAR package. This is a Tomcat specific config file and you must define a Keycloak specific Valve.


<Context path="/your-context-path">
    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
</Context>
        

Next you must create a keycloak.json adapter config file within the WEB-INF directory of your WAR. The format of this config file is describe in the general adapter configuration section.

Finally you must specify both a login-config and use standard servlet security to specify role-base constraints on your URLs. Here's an example:


<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

	<module-name>customer-portal</module-name>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Customers</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>this is ignored currently/realm-name>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
</web-app>

Keycloak has a separate adapter for Jetty 9.1.x and Jetty 9.2.x that you will have to install into your Jetty installation. You then have to provide some extra configuration in each WAR you deploy to Jetty. Let's go over these steps.

This section describes how to secure a WAR directly by adding config and editing files within your WAR package.

The first thing you must do is create a WEB-INF/jetty-web.xml file in your WAR package. This is a Jetty specific config file and you must define a Keycloak specific authenticator within it.


<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Get name="securityHandler">
        <Set name="authenticator">
            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
            </New>
        </Set>
    </Get>
</Configure>
        

Next you must create a keycloak.json adapter config file within the WEB-INF directory of your WAR. The format of this config file is describe in the general adapter configuration section.

Warning

The Jetty 9.1.x adapter will not be able to find the keycloak.json file. You will have to define all adapter settings within the jetty-web.xml file as described below.

Instead of using keycloak.json, you can define everything within the jetty-web.xml. You'll just have to figure out how the json settings match to the org.keycloak.representations.adapters.config.AdapterConfig class.


<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Get name="securityHandler">
    <Set name="authenticator">
        <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
            <Set name="adapterConfig">
                <New class="org.keycloak.representations.adapters.config.AdapterConfig">
                    <Set name="realm">tomcat</Set>
                    <Set name="resource">customer-portal</Set>
                    <Set name="authServerUrl">http://localhost:8081/auth</Set>
                    <Set name="sslRequired">external</Set>
                    <Set name="credentials">
                        <Map>
                            <Entry>
                                <Item>secret</Item>
                                <Item>password</Item>
                            </Entry>
                        </Map>
                    </Set>
                    <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4</Set>
                </New>
            </Set>
        </New>
    </Set>
  </Get>
</Configure>

You do not have to crack open your WAR to secure it with keycloak. Instead create the jetty-web.xml file in your webapps directory with the name of yourwar.xml. Jetty should pick it up. In this mode, you'll have to declare keycloak.json configuration directly within the xml file.

Finally you must specify both a login-config and use standard servlet security to specify role-base constraints on your URLs. Here's an example:


<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

	<module-name>customer-portal</module-name>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Customers</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>this is ignored currently</realm-name>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
</web-app>

Keycloak has a separate adapter for Jetty 8.1.x that you will have to install into your Jetty installation. You then have to provide some extra configuration in each WAR you deploy to Jetty. Let's go over these steps.

Currently Keycloak supports securing your web applications running inside JBoss Fuse or Apache Karaf . It leverages Jetty 8 adapter as both JBoss Fuse 6.1 and Apache Karaf 3 are bundled with Jetty 8.1 server under the covers and Jetty is used for running various kinds of web applications.

What is supported for Fuse/Karaf is:

The best place to start is look at Fuse demo bundled as part of Keycloak examples in directory examples/fuse .

The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications. This library is referencable directly from the keycloak server. You can also download the adapter from Keycloak's download site if you want a static copy of this library. It works in the same way as other application adapters except that your browser is driving the OAuth redirect protocol rather than the server.

The disadvantage of using this approach is that you have a non-confidential, public client. This makes it more important that you register valid redirect URLs and make sure your domain name is secured.

To use this adapter, you must first configure an application (or client) through the Keycloak Admin Console. You should select public for the Client Type field. As public clients can't be verified with a client secret you are required to configure one or more valid redirect uris as well. Once you've configured the application click on the Installation tab and download the keycloak.json file. This file should be hosted in your web-server at the same root as your HTML pages. Alternatively you can either specify the URL for this file, or manually configure the adapter.

Next you have to initialize the adapter in your application. An example on how to do this is shown below.

<head>
    <script src="http://<keycloak server>/auth/js/keycloak.js"></script>
    <script>
        var keycloak = Keycloak();
        keycloak.init().success(function(authenticated) {
            alert(authenticated ? 'authenticated' : 'not authenticated');
        }).error(function() {
            alert('failed to initialize');
        });
    </script>
</head>

To specify the location of the keycloak.json file:

var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'));

Or finally to manually configure the adapter:

var keycloak = Keycloak({
    url: 'http://keycloak-server/auth',
    realm: 'myrealm',
    clientId: 'myapp'
});

You can also pass login-required or check-sso to the init function. Login required will redirect to the login form on the server, while check-sso will redirect to the auth server to check if the user is already logged in to the realm. For example:

keycloak.init({ onLoad: 'login-required' })

After you login, your application will be able to make REST calls using bearer token authentication. Here's an example pulled from the customer-portal-js example that comes with the distribution.

<script>
    var loadData = function () {
        document.getElementById('username').innerText = keycloak.username;

        var url = 'http://localhost:8080/database/customers';

        var req = new XMLHttpRequest();
        req.open('GET', url, true);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);

        req.onreadystatechange = function () {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    var users = JSON.parse(req.responseText);
                    var html = '';
                    for (var i = 0; i < users.length; i++) {
                        html += '<p>' + users[i] + '</p>';
                    }
                    document.getElementById('customers').innerHTML = html;
                    console.log('finished loading data');
                }
            }
        }

        req.send();
    };

    var loadFailure = function () {
        document.getElementById('customers').innerHTML = '<b>Failed to load data.  Check console log</b>';

    };

    var reloadData = function () {
        keycloak.updateToken().success(loadData).error(loadFailure);
    }
</script>

<button onclick="loadData()">Submit</button>

The loadData() method builds an HTTP request setting the Authorization header to a bearer token. The keycloak.token points to the access token the browser obtained when it logged you in. The loadFailure() method is invoked on a failure. The reloadData() function calls keycloak.onValidAccessToken() passing in the loadData() and loadFailure() callbacks. The keycloak.onValidAcessToken() method checks to see if the access token hasn't expired. If it hasn't, and your oauth login returned a refresh token, this method will refresh the access token. Finally, if successful, it will invoke the success callback, which in this case is the loadData() method.

To refresh the token if it's expired call the updateToken method. This method returns a promise object which can be used to invoke a function on success or failure. This method can be used to wrap functions that should only be called with a valid token. For example the following method will refresh the token if it expires within 30 seconds, and then invoke the specified function. If the token is valid for more than 30 seconds it will just call the specified function.

keycloak.updateToken(30).success(function() {
    // send request with valid token
}).error(function() {
    alert('failed to refresh token');
);

To be able to secure Spring Boot apps you must add the Keycloak Spring Boot adapter JAR to your app. You then have to provide some extra configuration via normal Spring Boot configuration (application.properties). Let's go over these steps.

Keycloak provides two special redirect uris for installed applications.

There are multiple ways you can logout from a web application. For Java EE servlet containers, you can call HttpServletRequest.logout(). For any other browser application, you can point the browser at the url http://auth-server/auth/realms/{realm-name}/tokens/logout?redirect_uri=encodedRedirectUri. This will log you out if you have an SSO session with your browser.

Multi Tenancy, in our context, means that one single target application (WAR) can be secured by a single (or clustered) Keycloak server, authenticating its users against different realms. In practice, this means that one application needs to use different keycloak.json files. For this case, there are two possible solutions:

  • The same WAR file deployed under two different names, each with its own Keycloak configuration (probably via the Keycloak Subsystem). This scenario is suitable when the number of realms is known in advance or when there's a dynamic provision of application instances. One example would be a service provider that dynamically creates servers/deployments for their clients, like a PaaS.
  • A WAR file deployed once (possibly in a cluster), that decides which realm to authenticate against based on the request parameters. This scenario is suitable when there are an undefined number of realms. One example would be a SaaS provider that have only one deployment (perhaps in a cluster) serving several companies, differentiating between clients based on the hostname (client1.acme.com, client2.acme.com) or path (/app/client1/, /app/client2/) or even via a special HTTP Header.

This chapter of the reference guide focus on this second scenario.

Keycloak provides an extension point for applications that need to evaluate the realm on a request basis. During the authentication and authorization phase of the incoming request, Keycloak queries the application via this extension point and expects the application to return a complete representation of the realm. With this, Keycloak then proceeds the authentication and authorization process, accepting or refusing the request based on the incoming credentials and on the returned realm. For this scenario, an application needs to:

  • Add a context parameter to the web.xml, named keycloak.config.resolver. The value of this property should be the fully qualified name of the class extending org.keycloak.adapters.KeycloakConfigResolver.
  • A concrete implementation of org.keycloak.adapters.KeycloakConfigResolver. Keycloak will call the resolve(org.keycloak.adapters.HttpFacade.Request) method and expects a complete org.keycloak.adapters.KeycloakDeployment in response. Note that Keycloak will call this for every request, so, take the usual performance precautions.

An implementation of this feature can be found in the examples.

It's generally not needed to use JAAS for most of the applications, especially if they are HTTP based, but directly choose one of our adapters. However some applications and systems may still rely on pure legacy JAAS solution. Keycloak provides couple of login modules to help with such use cases. Some login modules provided by Keycloak are:

org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule

This login module allows to authenticate with username/password from Keycloak database. It's using Direct Access Grants Keycloak endpoint to validate on Keycloak side if provided username/password is valid. It's useful especially for non-web based systems, which need to rely on JAAS and want to use Keycloak credentials, but can't use classic browser based authentication flow due to their non-web nature. Example of such application could be messaging application or SSH system.

org.keycloak.adapters.jaas.BearerTokenLoginModule

This login module allows to authenticate with Keycloak access token passed to it through CallbackHandler as password. It may be useful for example in case, when you have Keycloak access token from classic web based authentication flow and your web application then needs to talk to external non-web based system, which rely on JAAS. For example to JMS/messaging system.

Both login modules have configuration property keycloak-config-file where you need to provide location of keycloak.json configuration file. It could be either provided from filesystem or from classpath (in that case you may need value like classpath:/folder-on-classpath/keycloak.json ).

Second property role-principal-class allows to specify alternative class for Role principals attached to JAAS Subject. Default value for Role principal is org.keycloak.adapters.jaas.RolePrincipal . Note that class should have constructor with single String argument.