Integrating with JBoss

Introduction

Ceptor is an Secure IT Infrastructure solution that protects portals and application servers, regardless of the communication type used, be it JSP, Servlets, EJB or other type of communication. Ceptor can provide Authentication and Authorization checking on all resources, as well as provide secure communication clients and servers.
Any number of web servers, application servers or other types of servers can be integrated, and used to create personalized content and session sharing between all applications, so users experience single signon with access (depending on authorization of course) to all applications available in your portal.
This document describes how to integrate Ceptor with the JBoss 7 Application Server and JBoss WildFly 8.

Installation

In the Ceptor distribution, you can find the required files in samples/integration/jboss. To install the Tomcat Realm, you will need to unzip CeptorJBOSS_module.zip in your JBoss modules directory – this will create the subdirectory dk/portalprotect/jboss/main with the following files:
CeptorAgent.jar- CeptorJBOSS.jar- JBoss specific integration codemodule.xml - JBOSS Module descriptor file ptserver.properties- Ceptor Agent configuration

To configure Ceptor Agent, you will also need to either set the system properties portalprotect.server.name/server.name to the name of the server, and portalprotect.config.servers/config.servers to the list of configuration servers, or you need to provide ptservers.properties in the classpath with these properties. The ptserver.properties file provided with the module contain the name "webserver1" and the list of config servers "localhost:21233" – you will need to change these settings according to your environment.
See more in Ceptor Users Guide.
Example:
Set JAVA_OPTS=-Dportalprotect.server.name=webserver1 –Dportalprotect.config.servers=localhost:21233
Now, you need to configure the JAAS LoginModule in your JBoss configuration file – here modify standalone/configuration/standalone.xml or whatever other file contains your domain configuration.
In the section for the subsystem jboss:domain:security, add the security domain "ceptor"

<security-domain name="ceptor">
  <authentication>
    <login-module code="dk.portalprotect.jboss.PPLoginModule" flag="required"/>
  </authentication>
</security-domain>


Example:

<subsystem xmlns="urn:jboss:domain:security:1.0">
  <security-domains>
    <security-domain name="other" cache-type="default">
      <authentication>
        <login-module code="Disabled" flag="required"/>
      </authentication>
    </security-domain>
    <security-domain name="ceptor">
      <authentication>
        <login-module code="dk.portalprotect.jboss.PPLoginModule" flag="required"/>
      </authentication>
    </security-domain>
  </security-domains>
</subsystem>



This will make the security domain "ceptor" available to your applications.

Webapp Configuration

For the user principal and groups to be available within JBoss, you will need to protect access to your webapp.
This is an example of how to configure web.xml to do just that.

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Default constraint</web-resource-name>
      <description>Default security constraints</description>
      <url-pattern>/*</url-pattern>
      <http-method>POST</http-method>
      <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
      <description>Default constraint</description>
      <role-name>pp_everyone</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>BASIC</auth-method>
  </login-config>
  <security-role>
    <description>All users going though PP</description>
    <role-name>pp_everyone</role-name>
  </security-role>
</web-app>

You will also need to create a JBoss specific configuration file, WEB-INF/jboss-web.xml with the following content:

<!DOCTYPE jboss-web PUBLIC"-//JBoss//DTD Web Application 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">
<jboss-web>
  <security-domain>java:/jaas/ceptor</security-domain>
  <valve>
    <class-name>dk.portalprotect.jboss.SessionIDValve</class-name>
  </valve>
</jboss-web>


This will tell JBoss to use the appropriate security realm, and to add the session ID valve (which is required to give Ceptor access to the Ceptor session cookie in the request)
Note that the <valve> tag has no effect in WildFly 8 – it uses a new non-tomcat webserver called undertow which at the time of writing does not yet support valves.Instead, you will need to create a file in your webapp called WEB-INF/classes/META-INF/io.undertow.servlet.ServletExtension with the following contents:

dk.portalprotect.jboss.undertow.ServletExtensionHandler 


This is all you need to be able to do J2EE security from within your webapp – the following is an example you can add to a .jsp page to try it out:

Current user: <%=request.getRemoteUser() %><br/>
User principal: <%=request.getUserPrincipal() %>
Auth type: <%=request.getAuthType() %><br/>
Has role pp_everyone: <%=request.isUserInRole("pp_everyone") %><br/>
Has role pp_identifiedusers: <%=request.isUserInRole("pp_identifiedusers") %><br/>
Has role pp_anonymous: <%=request.isUserInRole("pp_anonymous") %><br/>


You do not need to add all the roles you are checking against in your webapp to <security-role> tags in the web.xml.
The request.getRemoteUser() will be an empty string if the user is not authenticated, or it will contain the userid of the authenticated principal.Unfortunately it cannot be null for anonymous users, since it will cause EJB role checking for fail in JBOSS 7.1.1 which does not support null usernames.
Request.getUserPrincipal() will return an instance of the dk.portalprotect.jboss.PPPrincipal class which has a getName() method that returns the name of the authenticated user, and a getSessionID() method which returns the session ID. Its toString() method will return the session ID for unauthenticated users, and the users real userid for authenticated users.
The method request.isUserInRole() works for all user roles, but only if the user has been assigned the groups directly within his session upon login. It will not work if the users PP session does not have access to the list of the users groups.
You can also gain access to the Ceptor Agent API, by configuring your webapp to require the installed JBoss Ceptor Module, this is done by adding a META-INF/MANIFEST.MF file to your webapp like the following

Manifest-Version: 1.0
Created-By: Ceptor
Implementation-Title: Ceptor JBOSS Integration Test
Implementation-Version: 1.0
Implementation-Vendor-Id: dk.portalprotect
Implementation-Vendor: Ceptor
Dependencies: dk.portalprotect.jboss 


The important bits in this file, is the Dependencies line, which informs JBOSS to make the classes within Ceptor JBoss module available to the webapp.
The Ceptor distribution contains a test webapp with example configuration files in /samples/integration/jboss/test.war

Protecting Access to EJBs

The sample webapp in /samples/integration/jboss/test.war also contains a small EJB3 example – the source code can be found inside the .war file in WEB-INF/source.
Example TestEJB:

@Stateless(name="TestEJB")
@org.jboss.ejb3.annotation.SecurityDomain("ceptor")
public class TestEJB implements TestInterface {
  @RolesAllowed(value= {"pp_anonymous"})
  public int calcAnonymous(int a, int b) {
    return a+b;
  } 
  @RolesAllowed(value= {"pp_identifiedusers"})
  public int calcIdentified(int a, int b) {
    return a+b;
  }
} 


It contains a small EJB with 2 methods, both protected by the @RolesAllowed annotation, one allowing only anonymous users, and another allowing only identified users using the two special Ceptor roles that signify this.
The key to making this work, is either to specify the @org.jboss.ejb3.annotation.SecurityDomain("ceptor") annotation to point to the correct security domain, or to create a new file; WEB-INF/jboss-ejb3.xml with the following contents:

<?xml version="1.0"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd_http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0">
  <assembly-descriptor>
    <s:security>
      <ejb-name>*</ejb-name>
      <s:security-domain>ceptor</s:security-domain>
    </s:security>
  </assembly-descriptor>
</jboss:ejb-jar>


Note that this does NOT work with JBOSS 7.0.1, which does not seem to recognize the security-domain part of the jboss-ejb3.xml file. It requires JBOSS v7.1.x to work, and has been tested and verified on JBOSS 7.1.1.

© Ceptor ApS. All Rights Reserved.