
[[_jboss_adapter]]
{% if book.community %}
==== JBoss EAP/Wildfly Adapter
{% endif %}
{% if book.product %}
==== JBoss EAP Adapter
{% endif %}

To be able to secure WAR apps deployed on JBoss EAP {% if book.community %}, WildFly or JBoss AS{% endif %}, you must install and configure the
{{book.project.name}} adapter subsystem. You then have two options to secure your WARs.

You can provide an adapter config file in your WAR and change the auth-method to KEYCLOAK within web.xml.

Alternatively, you don't have to modify your WAR at all and you can secure it via the {{book.project.name}} adapter subsystem configuration in `standalone.xml`.
Both methods are described in this section.

[[_jboss_adapter_installation]]
===== Adapter Installation

Adapters are available as a separate archive and are also available as Maven artifacts.

{% if book.community %}
Install on Wildfly 9 or 10:

[source, subs="attributes"]
----
$ cd $WILDFLY_HOME
$ unzip keycloak-wildfly-adapter-dist-{{book.project.version}}.zip
----

Install on Wildfly 8:

[source, subs="attributes"]
----
$ cd $WILDFLY_HOME
$ unzip keycloak-wf8-adapter-dist-{{book.project.version}}.zip
----

Install on JBoss EAP 7:

[source, subs="attributes"]
----
$ cd $EAP_HOME
$ unzip keycloak-eap7-adapter-dist-{{book.project.version}}.zip
----

Install on JBoss EAP 6:

[source, subs="attributes"]
----
$ cd $EAP_HOME
$ unzip keycloak-eap6-adapter-dist-{{book.project.version}}.zip
----

Install on JBoss AS 7.1:

[source, subs="attributes"]
----
$ cd $JBOSS_HOME
$ unzip keycloak-as7-adapter-dist-{{book.project.version}}.zip
----
{% endif %}

{% if book.product %}
Install on JBoss EAP 7:

[source, subs="attributes"]
----
$ cd $EAP_HOME
$ unzip rh-sso-{{book.project.version}}-eap7-adapter.zip
----

Install on JBoss EAP 6:

[source, subs="attributes"]
----
$ cd $EAP_HOME
$ unzip rh-sso-{{book.project.version}}-eap6-adapter.zip
----
{% endif %}

This ZIP archive contains JBoss Modules specific to the {{book.project.name}} adapter. It also contains JBoss CLI scripts to install and configure the adapter.

Once the ZIP archive is extracted you have to enable the {{book.project.name}} subystem in the server configuration (i.e. `standalone.xml`). The easiest way to
do this is to use the supplied JBoss CLI scripts.

To install and configure the adapter, first start the server and then run the JBoss CLI installation script :

[source]
----
$ ./bin/jboss-cli.sh -c --file=adapter-install.cli
----

The script will add the required configuration to the server configuration file.

For JBoss EAP 7 {% if book.community %} and WildFly 9+{% endif %} there is also an offline CLI script that can be used to install the adapter while the server
is not running:

[source]
----
$ ./bin/jboss-cli.sh -c --file=adapter-install-offline.cli
----    

If you are planning to add it manually you need to add the extension and subsystem definition to the server configuration:

[source,xml]
----
<extensions>
    <extension module="org.keycloak.keycloak-adapter-subsystem"/>
    ...
</extensions>

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

If you need to be able to propagate the security context from the web tier to the EJB tier you also need to add the `keycloak` security domain:

[source,xml]
----
<subsystem xmlns="urn:jboss:domain:security:...">
    <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: 

[source]
----

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();
    }
}
----

===== Required Per WAR Configuration

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 <<fake/../java-adapter-config.adoc#_java_adapter_config,Java 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:

[source,xml]
----

<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>application</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>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-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>
        <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>
----        

===== Securing WARs via Adapter Subsystem

You do not have to modify your WAR to secure it with {{book.project.name}}. Instead you can externally secure it via the {{book.project.name}} Adapter 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 server configuration (i.e. `standalone.xml`) in the {{book.project.name}} subsystem definition.

[source,xml]
----
<extensions>
  <extension module="org.keycloak.keycloak-adapter-subsystem"/>
</extensions>

<profile>
  <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
     <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 `secure-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 <<fake/../java-adapter-config.adoc#_java_adapter_config,Java adapter configuration>>.

The exception is the `credential` element. 

To make it easier for you, you can go to the {{book.project.name}} Administration Console and go to the Client/Installation tab of the application this WAR is aligned with.
It provides an example XML file you can cut and paste. 

If you have multiple deployments secured by the same realm you can share the realm configuration in a separate element. For example:

[source,xml]
----
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
    <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>
----        
