Prerequisites
Before configuring JOSSO make sure you have installed the JDK 1.5 that can be downloaded from here.
The JAVA_HOME environment variable must be set to the JDK installation directory.
For Unix systems you can use :
$ export JAVA_HOME=/usr/local/jdk1.5.0_12
For Win32 systems you can use :
set JAVA_HOME=c:\jdk1.5.0_12
JOSSO requires a generic servlet container, in this case we will be using Jetty 6.1.7
Jetty can be downloaded from here
The JETTY_HOME environment variable must be set pointing to the installation directory of Jetty.
For Unix systems you can use :
$ export JETTY_HOME=/usr/product/jetty-6.1.7
For Win32 systems you can use :
set CATALINA_HOME=c:\jetty-6.1.7
Introduction
Since version 1.7 JOSSO provides support for Generic Servlet Containers. Because in this scenario JOSSO uses standard servlet API, it's not posible to inject user identity at container level. In this case JOSSO will provides a security context that can be used within the web application instead of invoking J2EE security API.
This HOW-TO will explain how to setup JOSSO 1.7 in Jetty 6.1.7. You will probably need to adapt this guide depending on your container specific configuration needs but the proces in general should not vary.
Building
Once the prerequisites are satisfied you can start building JOSSO by invoking the build script for your OS.
From the project root.
For Unix systems you should execute :
$ ./build.sh build-servlet war
For Win32 systems you should execute :
build.bat build-servlet war
If this procedure is succesfully executed you will find the following files in the ./build/josso-1.7 directory :
- josso.war
- josso-1.7.jar
- josso-common-1.7.jar
You will also find the generic-servlet plugin files in the ./build/josso-1.7/plugins directory :
- josso-servlet-plugin-all-1.7.jar
The josso.war file contains the server part of the Single Sign-On, while the josso-1.7.jar file contains the stubs needed to integrate the web infrastructure to the SSO authentication schemes. The josso-common-1.7.jar file contains the classes that are shared beteween the JOSSO infrastructure and the partner applications.
Installing
After succesfully compiling JOSSO you must install the core Jars for JOSSO to run in Jetty
For Unix systems you should execute :
$ mkdir $JETTY_HOME/webapps/josso
$ cd $JETTY_HOME/webapps/josso
$ jar xvf $JOSSO_HOME/build/josso-{josso-latest-version}/josso.war
For Win32 systems you should execute :
mkdir %JETTY_HOME%\webapps\josso
cd %JETTY_HOME%\webapps\josso
jar xvf %JOSSO_HOME%\build\josso-{josso-latest-version}\josso.war
This procedure must be done only once.
Setup
The Single Sign-On Gateway Configuration
The Single Sign-On Gateway is responsible of the centralized authentication of web users using the configured authentication scheme and credential store.
An authentication scheme is a security mechanisms used to verify user identity based on his credentials. Sample authentication schemes are username/password authentication or Certificate based authentication.
A credential is a piece of information bound to an individual that is presented to the verifier in an authentication transaction. Sample credentials are username/password pair and X.509 Certificates.
User credentials must be stored using some sort of persistence mechanism, so that credentials provided by the user in an authentication transaction can be checked. A Credential Store is where user credentials are located. Sample credential stores are database and LDAP.
One core feature of JOSSO is to allow to combine authentication schemes and credential stores using the Single Sign-On Gateway configuration file. This file must reside in the $JETTY_HOME/webapps/josso/WEB-INF/classes directory in order to be located by the Single Sign-On Gateway.
Lets have a look at an example Single Sign-On Gateway configuration file :
<?xml version="1.0" encoding="ISO-8859-1" ?> <domain> <name>SampleDomain</name> <type>web</type> <authenticator> <class>org.josso.auth.AuthenticatorImpl</class> <authentication-schemes> <!-- Basic Authentication Scheme --> <authentication-scheme> <name>basic-authentication</name> <class>org.josso.auth.scheme.UsernamePasswordAuthScheme</class> <!-- ========================================================= --> <!-- JDBC Credential Store --> <!-- ========================================================= --> <credential-store> <class> org.josso.gateway.identity.service.store.db.JDBCIdentityStore </class> <credentialsQueryString> SELECT login AS username , password AS password FROM josso_user WHERE login = ? </credentialsQueryString> <connectionName>SCOTT</connectionName> <connectionPassword>TIGER</connectionPassword> <connectionURL>jdbc:oracle:thin:@mydbhost:1521:mydb</connectionURL> <driverName>oracle.jdbc.driver.OracleDriver</driverName> </credential-store> <credential-store-key-adapter> <class> org.josso.gateway.identity.service.store.SimpleIdentityStoreKeyAdapter </class> </credential-store-key-adapter> </authentication-scheme> </authentication-schemes> </authenticator> <sso-identity-manager> <class>org.josso.gateway.identity.service.SSOIdentityManagerImpl</class> <!-- ========================================================= --> <!-- JDBC Identity Store --> <!-- ========================================================= --> <sso-identity-store> <class> org.josso.gateway.identity.service.store.db.JDBCIdentityStore </class> <userQueryString> SELECT login FROM josso_user WHERE login = ? </userQueryString> <rolesQueryString> SELECT josso_role.name FROM josso_role , josso_user_role , josso_user WHERE josso_user.login = ? AND josso_user.login = josso_user_role.login AND josso_role.name = josso_user_role.name </rolesQueryString> <connectionName>SCOTT</connectionName> <connectionPassword>TIGER</connectionPassword> <connectionURL>jdbc:oracle:thin:@mydbhost:1521:mydb</connectionURL> <driverName>oracle.jdbc.driver.OracleDriver</driverName> </sso-identity-store> <sso-identity-store-key-adapter> <class> org.josso.gateway.identity.service.store.SimpleIdentityStoreKeyAdapter </class> </sso-identity-store-key-adapter> </sso-identity-manager> <sso-session-manager> <class>org.josso.gateway.session.service.SSOSessionManagerImpl</class> <!-- Set the maximum time interval, in minutes, between client requests before the SSO Service will invalidate the session. A negative time indicates that the session should never time out. --> <maxInactiveInterval>1</maxInactiveInterval> <sso-session-store> <class> org.josso.gateway.session.service.store.MemorySessionStore </class> </sso-session-store> <sso-session-id-generator> <class> org.josso.gateway.session.service.SessionIdGeneratorImpl </class> <!-- The message digest algorithm to be used when generating session identifiers. This must be an algorithm supported by the java.security.MessageDigest class on your platform. In J2SE 1.4.2 you can check : Java Cryptography Architecture API Specification & Reference - Apendix A : Standard Names Values are : MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 --> <algorithm>MD5</algorithm> </sso-session-id-generator> </sso-session-manager> <sso-audit-manager> <class>org.josso.gateway.audit.service.SSOAuditManagerImpl</class> <handlers> <!-- This handler logs all audit trails using Log4J, under the given category --> <handler> <class>org.josso.gateway.audit.service.handler.LoggerAuditTrailHandler</class> <name>LoggerAuditTrailHandler</name> <category>org.josso.gateway.audit.SSO_AUDIT</category> </handler> </handlers> </sso-audit-manager> <!-- SSO Event Manager component --> <sso-event-manager> <class>org.josso.gateway.event.security.JMXSSOEventManagerImpl</class> <!-- JMX Name of the EventManager MBean that will send SSO Events as JMX Notifications The MBean will be registered by the MBeanComponentKeeper. --> <oname>josso:type=SSOEventManager</oname> </sso-event-manager> </domain>
josso-config.xml
The josso-config.xml file represents the master configuration file which is used to declare the concrete configuration files that will be used by JOSSO to customize its behaviour.
This file must reside in the $JETTY_HOME/webapps/josso/WEB-INF/classes directory in order to be located by the Single Sign-On Gateway.
Let's take a look at an example josso-config.xml file that will configure a JOSSO Single Sign-On Gateway :
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <hierarchicalXml fileName="josso-gateway-config.xml"/> </configuration>
Using this configuration JOSSO is told to import the josso-gateway-config.xml XML configuration file. Any configuration file referenced in the josso-config.xml file must reside in the same directory as the josso-config.xml which is $JETTY_HOME/webapps/josso/WEB-INF/classes.
Configuring the Authenticator
The Authenticator is the component responsible of realizing a concrete authentication scheme.
The authentication scheme to be implemented must be set in the class element, child of the authentication-schemes element. For username/password authentication scheme set it to org.josso.auth.scheme.UsernamePasswordAuthScheme.
Now you will need to tell the authenticator the persistence mechanism to be used for obtaining the user credentials when asserting his identity. You can configure this by setting the class element child of the credential-store element. For database persistence mechanism set it to org.josso.gateway.identity.service.store.db.JDBCIdentityStore.
Once you chose persistence mechanism to be used by the authenticator, you will need to tell the store how to obtain the username and password information from your specific store. In case of a JDBC credential store you must set the credentialsQueryString element value with the SQL SELECT query that will retrieve the username and password for a user.
In case of using the database persistence mechanism you will also need to set the specific values for the connectionName, connectionPassword, connectionURL and driverName elements.
Configuring the Identity Manager
The Identity Manager is the component responsible of authenticating the user using the configured authenticator and managing the authenticated user sessions.
The identity manager to be implemented must be set in the class element, child of the identity-manager element. To use the default Identity Manager set this element value to org.josso.gateway.identity.service.SSOIdentityManagerImpl.
Now you will need to tell the identity manager the persistence mechanism to be used for obtaining user and role information. You can configure this by setting the class element child of the sso-identity-store element. For database persistence mechanism set it to org.josso.gateway.identity.service.store.db.JDBCIdentityStore.
Once you set the persistence mechanism to be used by the identity manager, you will need to tell the identity store how to obtain the user and role information from your specific store. In case of a JDBC identity store you must set the userQueryString element value with the SQL SELECT query that will retrieve the username for a user given user. This username will then be used to retrieve the user's roles by executing the SQL SELECT query declared in the rolesQueryString.
In case of using the database persistence mechanism you will also need to set the specific values for the connectionName, connectionPassword, connectionURL and driverName elements.
Configuring the Session Manager
The Single Sign-On Session Manager is the component responsible of managing the lifecycle of an SSO User Session. On succesfull user authentication the Single Sign-On Gateway creates a new SSO Session using the Session Manager.
The concrete session manager to be instantiated, its store for persisting SSO sessions among other things can be configured but for most common uses the default configuration will do just fine.
Configuring the Audit Manager
The Single Sign-On Audit Manager is the component responsible for propagating auditing SSO events to the listening Audit Handlers. Audit Handlers can trap such events and act accordingly, such as disabling an account after several failed authentication attempts (In this example its probably best to extend the default Authenticator to verify the user account status on authentication request).
JOSSO provides a default handler which traces all SSO audit trails using the configured logger.
Custom audit managers and their handlers can be configured and used, but for most cases the default configuration will do just fine.
Configuring the Event Manager
The Single Sign-On Event Manager is the component responsible for propagating generic SSO events, such as information session lifecycle and authentication requests. You can add your own event listeners to act on behalf of any SSO event, such as an authentication failure. Even thought events are propagated through the JMX bus, your listeners do not have to deal with the JMX api since the underlying JOSSO event infrastructure will take care of this.
Custom event managers and their handlers can be configured and used, but for most cases the default configuration will do just fine.
Single Sign-On Agent Configuration
The main responsability of the Single Sign-On Agent is to check that a previosly user logged through the Single Sign-On Gateway is authorized to access a web context.
The Agent verifies this information by querying via SOAP the Single Sign-On Webservice infrastructure using a special cookie set by the Single Sign-On Gateway on authentication.
josso-config.xml
The josso-config.xml file represents the master configuration file which is used to declare the concrete configuration files that will be used by JOSSO to customize its behaviour.
This file must reside in the partner application WEB-INF/classes directory, for example $JETTY_HOME/webapps/partnerapp/WEB-INF/classes directory in order to be located by the Single Sign-On Agent Filter.
Let's take a look at an example josso-config.xml file that will configure a JOSSO Single Sign-On Agent :
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <hierarchicalXml fileName="josso-agent-config.xml"/> </configuration>
Using this configuration JOSSO is told to import the josso-agent-config.xml XML configuration file. Any configuration file referenced in the josso-config.xml file must reside in the same directory as the josso-config.xml which is $JETTY_HOME/webapps/josso/WEB-INF/classes as described above.
Protect the Web Applications
So first we will have protect a specific web application using the Single Sign-On Agent Filter. In our example, the partner application is partnerapp, this application is provided with JOSSO, you should configure your own application, following this steps.
Lets modify the partner application web descriptor file in the following way :
<?xml version="1.0" encoding="ISO-8859-1"?> <!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> <display-name>JOSSO Partner Application</display-name> <!-- Setup JOSSO Servlet Filter --> <filter> <filter-name>JOSSOGenericServletFilter</filter-name> <description>JOSSO Generic Servlet Container filter</description> <filter-class>org.josso.servlet.agent.GenericServletSSOAgentFilter</filter-class> </filter> <filter-mapping> <filter-name>JOSSOGenericServletFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list id="WelcomeFileList"> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
On each request sent by the user to the /partnerapp Web Context, the Single Sign-On Agent will intercept it, assert the Single Sign-On session and obtain the user data from the Single Sign-On Gateway.
In case the session is valid, the Single Sign-On Agent will set the security context to the request and pass it on to the web application listening for the Web Context.
Configure a JAAS Login Module
The Single Sign-On Agent uses JAAS (Java Authentication and Authorization Service). For each request the Single Sign-On Agent intercepts it delegates the SSO session authentication to the configured Single Sign-On Gateway Login Module. The Login Module validates the session and obtains the corresponding user and role information by invoking the gateway identity management webservices.
The Jetty JAAS module must be able to run the Single Sign-On Gateway Login module. To do this create a jaas.conf file in the $pwertnerapp/WEB-INF directory with the following content :
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd"> <Configure class="org.mortbay.jetty.webapp.WebAppContext"> <!-- Configure JAAS --> <Call class="java.lang.System" name="setProperty"> <Arg>java.security.auth.login.config</Arg> <Arg><SystemProperty name="jetty.home" default="." />/etc/login.conf</Arg> </Call> </Configure>
Configure the Agent
The Single Sign-On Agent Configuration must reside in the partnerapp/WEB-INF/classes directory and should be referenced by the josso-config.xml file as stated before.
Let's take a look at an example Single Sign-On Agent configuration file :
<?xml version="1.0" encoding="ISO-8859-1" ?> <agent> <class>org.josso.servlet.agent.GenericServletSSOAgent</class> <gatewayLoginUrl>http://localhost:8080/josso/signon/login.do</gatewayLoginUrl> <gatewayLogoutUrl>http://localhost:8080/josso/signon/logout.do</gatewayLogoutUrl> <sessionAccessMinInterval>1000</sessionAccessMinInterval> <service-locator> <class>org.josso.gateway.WebserviceGatewayServiceLocator</class> <endpoint>localhost:8080</endpoint> </service-locator> <partner-apps> <partner-app> <context>/partnerapp</context> </partner-app> </partner-apps> </agent>
Using this configuration you can set :
- The Gateway Login URL, where the Single Sign-On Agent will redirect the user on protected resource access request so that he can authenticate.
- The Gateway Logout URL, where the Single Sign-On Agent will redirect the user on logout request.
- Concrete Single Sign-On Agent to be instantiated
- The concrete Service Locator to be used to invoke the services of the Single Sign-On Gateway.
In this specific case, which is the default, is using SOAP over HTTP to invoke The Single Sign-On Gateway WebServices.
Its important to specify the endpoint configuration parameter which should contain the host and port information where the Single Sign-On WebServices are listening.
If the gateway and the agent are running in the same server this will be localhost and the port should be the port where Tomcat is listening for incoming HTTP requests.
Include JOSSO Agent
Now we have to inlcude JOSSO Agent plugin in our web application. Copy the josso-servlet-plugin-all-1.7.jar file from $JOSSO_HOME/build/josso-1.7/plugins to the partnerapp/WEB-INF/lib directory. This file contains all JOSSO Generic Servlet dependencies.
Deploying and Running
Now that the partner application is configured, you have to deploy it in your container, in our example, we will extract the partnerapp.war contents to $JETTY_HOME/webapps/partnerapp/ directory and start Jetty. If you want to use JOSSO partner application, you can build the partnerapp.war using JOSSO's build system:
For Unix Systems you can do
$ ./build.sh war-samples
For Win32 Systems you can do
build.bat war-samples
This will create a partnerapp.war file in the $JOSSO_HOME/build/josso-1.7/ directory. The file can then be extracted in $JETTY_HOME/webapps and configured as described in the Single Sign-On Agent Configuration section.
Once the partner application has been deploy and properly configured, we can start our container, jetty in this case:
For Unix Systems:
$ cd $JETTY_HOME/bin $ ./jetty.sh
For Win32 Systems:
cd %JETTY_HOME%\bin jetty.bat
Developer Notes
Because this agent works in a different way than the other JOSSO Agents, we cannot use standard J2EE Security application to configure application security constraints. In this scenario, access control is done by the developer using JOSSO Security context information.
Let's take a look at a JSP page that requires user to have role1 to view the page content:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="org.josso.agent.Constants" %> <%@ page import="org.josso.servlet.agent.JOSSOGenericServletUtil" %> <%@ page import="org.josso.servlet.agent.JOSSOSecurityContext" %> <% // Obtain a JOSSO security context instance, if none is found is because user has not been authenticated. JOSSOSecurityContext ctx = JOSSOGenericServletUtil.getSecurityContext(request); if (ctx == null) { // User has not been authenticated, ask him to login, this will trigger the login process, storing current URL and // redirecting user to JOSSO Gateway Login page : JOSSOGenericServletUtil.askForLogin(request, response); } else if (!ctx.isUserInRole("role1")) { // User has been authenticated but does not have role1, return a 403 FORBIDDEN error. response.sendError(HttpServletResponse.SC_FORBIDDEN); } // OK! User is authenticated and has role1 !! %> <html> <head><title>Simple JOSSO protected page</title></head> <body>This is a simple JSP that will only bee accesible if user has been authenticated and is in role <b>role1</b></body> </html>