include::../shared-doc/attributes.adoc[]

= ejb-security-jaas: Using the legacy JAAS security domains to secure JEE applications
:author: Stefan Guilhen
:level: Intermediate
:technologies: EJB, Security

[abstract]
The `ejb-security-jaas` quickstart demonstrates how legacy `JAAS` security domains can be used in conjunction with `Elytron`

:standalone-server-type: default
:archiveType: war
:includes-cli-scripts:
:restoreScriptName: restore-configuration.cli

== What is it?

The `ejb-security-jaas` quickstart demonstrates how legacy `JAAS`-based security domains can be used in conjunction with `WildFly Elytron` to secure JEE applications. The secured EJB component can be accessed indirectly using a web application and it can also be directly invoked by a remote client. This quickstart shows how {productNameFull} must be configured to support both scenarios using the legacy `JAAS` integration.

The following steps required to use the `JAAS` integration.

1. Specify a `JAAS` security domain in the legacy `security` subsystem.
2. Export an `Elytron`-compatible security realm that delegates to the legacy JAAS security domain.
3. Create a `security-domain` in the `elytron` subsystem that uses the exported realm.
4. Setup an `http-authentication-factory` in the `elytron` subsystem to handle the web requests.
5. Setup a `sasl-authentication-factory` in the `elytron` subsystem to handle the requests made by remote clients.
6. Add the `application-security-domain` mappings to both `ejb3` and `undertow` subsystems to enable `Elytron` security for the EJB3 and web components.

// System Requirements
include::../shared-doc/system-requirements.adoc[leveloffset=+1]
// Use of {jbossHomeName}
include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1]

[[create_the_properties_files_for_the_jaas_security_domain]]
== Create the Properties Files for the JAAS Security Domain

. Open a terminal and navigate to the {productName} server `configuration` directory:
+
[source,subs="+quotes,attributes+",options="nowrap"]
----
$ cd __{jbossHomeName}__/standalone/configuration/
----

. Create a file named `users.properties` and add the following username/password pair.
+
[source,options="nowrap"]
----
quickstartUser=quickstartPwd1!
----

. Create a file named `roles.properties` and add the following username/roles pair.
+
[source,options="nowrap"]
----
quickstartUser=guest
----

This concludes the configuration required by the legacy `JAAS` login module used in this quickstart.

// Back Up the {productName} Standalone Server Configuration
include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+1]
// Start the {productName} Standalone Server
include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1]

[[configure_the_server]]
== Configure the Server

You configure the security domain by running JBoss CLI commands. For your convenience, this quickstart batches the commands into a `configure-elytron-jaas.cli` script provided in the root directory of this quickstart.

. Before you begin, make sure you do the following:

* xref:back_up_standalone_server_configuration[Back up the {productName} standalone server configuration] as described above.
* xref:start_the_eap_standalone_server[Start the {productName} server with the standalone default profile] as described above.


. Review the `configure-elytron-jaas.cli` file in the root of this quickstart directory. This script adds the configuration that enables Elytron security for the quickstart components. Comments in the script describe the purpose of each block of commands.
. Open a new terminal, navigate to the root directory of this quickstart, and run the following command, replacing __{jbossHomeName}__ with the path to your server.
+
[source,subs="+quotes,attributes+",options="nowrap"]
----
$ __{jbossHomeName}__/bin/jboss-cli.sh --connect --file=configure-elytron-jaas.cli
----
+
NOTE: For Windows, use the `__{jbossHomeName}__\bin\jboss-cli.bat` script.

+
You should see the following result when you run the script.
+
[source,options="nowrap"]
----
The batch executed successfully
process-state: reload-required
----

. Stop the {productName} server.

== Review the Modified Server Configuration

After stopping the server, open the `__{jbossHomeName}__/standalone/configuration/standalone.xml` file and review the changes.

. The following `security-domain` was added to the legacy `security` subsystem.
+
[source,xml,options="nowrap"]
----
<security-domain name="quickstart-domain" cache-type="default">
    <authentication>
        <login-module code="Remoting" flag="optional">
            <module-option name="password-stacking" value="useFirstPass"/>
        </login-module>
        <login-module code="UsersRoles" flag="required">
            <module-option name="usersProperties" value="${jboss.server.config.dir}/users.properties"/>
            <module-option name="rolesProperties" value="${jboss.server.config.dir}/roles.properties"/>
            <module-option name="password-stacking" value="useFirstPass"/>
        </login-module>
    </authentication>
    <mapping>
        <mapping-module code="SimpleRoles" type="role">
            <module-option name="quickstartUser" value="admin"/>
        </mapping-module>
    </mapping>
</security-domain>
----
+
The `quickstart-domain` is used to authenticate and authorize users. The `Remoting` login module is added to properly authenticate requests made from remote clients. A `mapping-module` is added that can be used to provide an extra role (`admin`). It is used later on to show how the legacy role mappers can be enabled and disabled.

. The following `elytron-realm` was added to the legacy `security` subsystem.
+
[source,xml,options="nowrap"]
----
<elytron-integration>
    <security-realms>
        <elytron-realm name="LegacyRealm" legacy-jaas-config="quickstart-domain" apply-role-mappers="false"/>
    </security-realms>
</elytron-integration>
----
+
This block tells the `security` subsystem to export an `Elytron`-compatible realm called `LegacyRealm` that will delegate authentication and authorization decisions to the legacy `quickstart-domain`. Setting the `apply-role-mappers` attribute to `false` indicates to the exported realm that it should not use any role mappers defined in the legacy security domain.

. The following `security-domain` was added to the `elytron` subsystem.
+
[source,xml,options="nowrap"]
----
<security-domain name="LegacyDomain" default-realm="LegacyRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
    <realm name="LegacyRealm"/>
</security-domain>
----

. The following `http-authentication-factory` was added to the `elytron` subsystem.
+
[source,xml,options="nowrap"]
----
<http-authentication-factory name="quickstart-http-authentication" http-server-mechanism-factory="global" security-domain="LegacyDomain">
    <mechanism-configuration>
        <mechanism mechanism-name="BASIC">
            <mechanism-realm realm-name="Legacy Realm"/>
        </mechanism>
    </mechanism-configuration>
</http-authentication-factory>
----
+
It creates the HTTP authentication factory that will handle BASIC requests by delegating the security domain, which was created in the previous step.

. The following `application-security-domain` mapping was added to the `undertow` subsystem.
+
[source,xml,otions="nowrap"]
----
<application-security-domains>
    <application-security-domain name="legacy-domain" http-authentication-factory="quickstart-http-authentication"/>
</application-security-domains>
----
+
It tells the `undertow` subsystem to use the HTTP authentication factory, which was created in the previous step, for web applications that specify the security domain `legacy-domain` in their metadata. The quickstart application specifies this domain both for the web layer, in the `jboss-web.xml` file, and the EJB component, using annotation in the code.

. The following `sasl-authentication-factory` was added to the `elytron` subsystem.

+
[source,xml,options="nowrap"]
----
<sasl-authentication-factory name="quickstart-sasl-authentication" sasl-server-factory="configured" security-domain="LegacyDomain">
    <mechanism-configuration>
        <mechanism mechanism-name="PLAIN"/>
    </mechanism-configuration>
</sasl-authentication-factory>
----

. The `http-remoting-connector` in the `remoting` subsystem was updated to use the `sasl-authentication-factory`, which was created in the previous step.
+
[source,xml,options="nowrap"]
----
<http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm" sasl-authentication-factory="quickstart-sasl-authentication"/>
----
+
Authentication performed by the quickstart remote client is handled by this SASL authentication factory.

. Finally, the following `application-security-domain` mapping was added to the `ejb3` subsystem.
+
[source,xml,options="nowrap"]
----
<application-security-domains>
    <application-security-domain name="legacy-domain" security-domain="LegacyDomain"/>
</application-security-domains>
----
+
This mapping basically enables `Elytron` security for EJB3 applications that specify the security domain `legacy-domain` in their metadata (either via jboss-ejb3.xml or annotations). The quickstart application uses the `@SecurityDomain` annotation in the bean class to specify this security domain.

// Build and Deploy the Quickstart WAR
include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1]

[[access_the_application]]
== Access the Application

The application will be running at the following URL http://localhost:8080/{artifactId}/.

When you access the application, you are presented with a browser login challenge.

. If you attempt to login with a user name and password combination that has not been added to the server, the login challenge will be redisplayed.
. When you login successfully using `quickstartUser`/`quickstartPwd1!`, the browser displays the following security info:
+
[source,options="nowrap"]
----
Successfully called Secured EJB

Principal : quickstartUser
Remote User : quickstartUser
Has admin permission : false
Authentication Type : BASIC
----
+
NOTE: See xref:server_log_expected_warnings_and_errors[Server Log: Expected Warnings and Errors] for the expected exception you will see in the server log.

. The application can also be accessed directly by a remote client. Type the following command in the root directory of the quickstart:
+
[source,options="nowrap"]
----
$ mvn exec:exec
----
+
The remote client application runs and displays the results of calling the secured bean.
+
[source,options="nowrap"]
----
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Called secured bean, caller principal quickstartUser

Principal has admin permission: false
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
----

+
NOTE: See xref:server_log_expected_warnings_and_errors[Server Log: Expected Warnings and Errors] for the expected exception you will see in the server log.

. Next, change the exported realm so that it now uses the legacy role mappers as defined in the legacy `JAAS` security domain.
+
Make sure you are still in the root directory of this quickstart, and run the following command, replacing `__{jbossHomeName}__` with the path to your server.
+
[source,subs="+quotes,attributes+",options="nowrap"]
----
$ __{jbossHomeName}__/bin/jboss-cli.sh --connect --file=enable-role-mappers.cli
----
+
NOTE: For Windows, use the `__{jbossHomeName}__\bin\jboss-cli.bat` script.

+
You should see the following result when you run the script.
+
[source,options="nowrap"]
----
{
    "outcome" => "success",
    "response-headers" => {
        "operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}
----

. If you didn't close your web browser, re-load the quickstart application page. Otherwise open a new browser, point it to the
URL http://localhost:8080/{artifactId}/ and login with `quickstartUser/quickstartPwd1!`. It should now display a
page confirming the user now has the `admin` role that was provided by the legacy role mapper:
+
[source,options="nowrap"]
----
Successfully called Secured EJB

Principal : quickstartUser
Remote User : quickstartUser
Has admin permission : true
Authentication Type : BASIC
----
+
NOTE: This time you will not see the exception in the server log because `quickstartUser` is authorized for the `admin` role.

. The same result can be observed when re-running the remote client application:
+
[source,options="nowrap"]
----
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Called secured bean, caller principal quickstartUser
Principal has admin permission: true
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
----

+
NOTE: This time you will not see the exception in the server log because `quickstartUser` is authorized for the `admin` role.

[[server_log_expected_warnings_and_errors]]
== Server Log: Expected Warnings and Errors

When you initially test this quickstart, you will see the following exception in the server log when you log in using the application URL and when you run the `mvn exec:exec` command. This is because the `quickstartUser` does not yet have the `admin` role required by the `administrativeMethod()` method. You can ignore this exception.


[source,options="nowrap"]
----
ERROR [org.jboss.as.ejb3.invocation] (default task-1) WFLYEJB0034: EJB Invocation failed on component SecuredEJB for method public abstract boolean org.jboss.as.quickstarts.ejb_security_jaas.SecuredEJBRemote.administrativeMethod(): javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public abstract boolean org.jboss.as.quickstarts.ejb_security_jaas.SecuredEJBRemote.administrativeMethod() of bean: SecuredEJB is not allowed
	at org.jboss.as.ejb3.security.RolesAllowedInterceptor.processInvocation(RolesAllowedInterceptor.java:67)
	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	...
----

After you enable the legacy security domain role mappers in the exported realm, the `quickstartUser` will have `admin` role access and you will no longer see the exception in the server log.

// Undeploy the Quickstart
include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1]
// Restore the {productName} Standalone Server Configuration
include::../shared-doc/restore-standalone-server-configuration.adoc[leveloffset=+1]

// Additional information about this script
This script reverts the changes made to the `ejb3`, `elytron`, `security` and `undertow` subsystems. You should see the following result when you run the script.

[source,options="nowrap"]
----
The batch executed successfully
process-state: reload-required
----

//  Restore the {productName} Standalone Server Configuration Manually
include::../shared-doc/restore-standalone-server-configuration-manual.adoc[leveloffset=+2]

== Remove the Properties Files from the Server

After you are done with this quickstart, remember to remove the `users.properties` and `roles.properties` files from the
server configuration directory (`__{jbossHomeName}__/standalone/configuration/`).

// Run the Quickstart in Red Hat JBoss Developer Studio or Eclipse
include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1]

// Additional JBoss Developer Studio instructions
* Make sure you xref:create_the_properties_files_for_the_jaas_security_domain[Create the Properties Files for the JAAS Security Domain] as described above.
* Make sure you configure the server by running the JBoss CLI script as described above under xref:configure_the_server[Configure the Server]. Stop the server at the end of that step.
* To deploy the application to the {productName} server, right-click on the *{artifactId}* project and choose *Run As* -> *Run on Server*.
* You are presented with a browser login challenge. Enter the credentials as described above under xref:access_the_application[Access the Application] to see the running application. Note that *Has admin permission* is `false`.
* Leave the application running in JBoss Developer Studio. To configure the server to use the legacy role mappers, open a terminal, and run the `enable-role-mappers.cli` script as described above under xref:access_the_application[Access the Application].
* Go back to JBoss Developer Studio and click *Refresh the current page*. Note that *Has admin permission* is now `true`.
* To undeploy the project, right-click on the *{artifactId}* project and choose *Run As* -> *Maven build*. Enter `wildfly:undeploy` for the *Goals* and click *Run*.
* Make sure you xref:restore_the_server_configuration[restore the server configuration] when you have completed testing this quickstart.

// Debug the Application
include::../shared-doc/debug-the-application.adoc[leveloffset=+1]
