Securing a Classic WAR Application

The needed steps to secure your WAR application are:

  1. Declare needed security constraints in the /WEB-INF/web.xml file. You also need to declare login-config and all the roles inside security-role.

    For example:

    <?xml version="1.0" encoding="UTF-8"?>
    <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>
    
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>
    
        <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>
    
        <login-config>
            <auth-method>BASIC</auth-method>
            <realm-name>does-not-matter</realm-name>
        </login-config>
    
        <security-role>
            <role-name>admin</role-name>
        </security-role>
        <security-role>
            <role-name>user</role-name>
        </security-role>
    </web-app>
  2. Add the jetty-web.xml file with the authenticator to the /WEB-INF/jetty-web.xml file.

    For example:

    <?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>
  3. Add the /WEB-INF/keycloak.json file to your Keycloak configuration. The format of this configuration file is described in the Java Adapters Config section. It is also possible to make this file available externally as described below.

  4. Ensure your WAR application imports org.keycloak.adapters.jetty and maybe some more packages in the META-INF/MANIFEST.MF file, under the Import-Package header. Using maven-bundle-plugin in your project properly generates OSGI headers in manifest. Note that "*" resolution for the package does not import the org.keycloak.adapters.jetty package, since it is not used by the application or the Blueprint or Spring descriptor, but is rather used in the jetty-web.xml file.

    The list of the packages to import might look like this:

    org.keycloak.adapters.jetty;version="3.0.0.Final",
    org.keycloak.adapters;version="3.0.0.Final",
    org.keycloak.constants;version="3.0.0.Final",
    org.keycloak.util;version="3.0.0.Final",
    org.keycloak.*;version="3.0.0.Final",
    *;resolution:=optional
Configuring the External Adapter

If you do not want the keycloak.json adapter configuration file to be bundled inside your WAR application, but instead available externally and loaded based on naming conventions, use this configuration method.

To enable the functionality, add this section to your web.xml file:

<context-param>
    <param-name>keycloak.config.resolver</param-name>
    <param-value>org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver</param-value>
</context-param>

That component uses keycloak.config or karaf.etc java properties to search for a base folder to locate the configuration. Then inside one of those folders it searches for a file called <your_web_context>-keycloak.json.

So, for example, if your web application has context my-portal, then your adapter configuration is loaded from the $FUSE_HOME/etc/my-portal-keycloak.json file.