eXo Platform 3.5

## Chapter 6. Authentication and Identity

## Predefined User Configuration

### Overview

To specify the initial Organization configuration, the content of 02portal.war:/WEB-INF/conf/organization/organization-configuration.xml should be edited. This file uses the portal XML configuration schema. It lists several configuration plugins.

### Plugin for adding users, groups and membership types

The plugin of type org.exoplatform.services.organization.OrganizationDatabaseInitializer is used to specify the list of membership types/groups/users to be created.

The checkDatabaseAlgorithm initialization parameter determines how the database update is performed.

If its value is set to entry, it means that each user, group and membership listed in the configuration is checked each time GateIn 3.2 is started. If the entry does not exist in the database yet, it is created. If the checkDatabaseAlgorithm parameter value is set to empty, the configuration data will be updated to the database only if the database is empty.

### Membership types

The predefined membership types are specified in the membershipType field of the OrganizationConfig plugin parameter.

### Note

See 02portal.war:/WEB-INF/conf/organization/organization-configuration.xml for the full content.

    <field name="membershipType">

      <collection type="java.util.ArrayList">

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$MembershipType">

            <field name="type">

              <string>member</string>

            </field>

            <field name="description">

              <string>member membership type</string>

            </field>

          </object>

        </value>

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$MembershipType">

            <field name="type">

              <string>owner</string>

            </field>

            <field name="description">

              <string>owner membership type</string>

            </field>

          </object>

         </value>

         <value>

           <object type="org.exoplatform.services.organization.OrganizationConfig$MembershipType">

             <field name="type">

               <string>validator</string>

             </field>

             <field name="description">

               <string>validator membership type</string>

             </field>

           </object>

         </value>

       </collection>

    </field>

### Groups

The predefined groups are specified in the group field of the OrganizationConfig plugin parameter.

    <field name="group">

      <collection type="java.util.ArrayList">

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$Group">

            <field name="name">

              <string>portal</string>

            </field>

            <field name="parentId">

              <string></string>

            </field>

            <field name="type">

              <string>hierachy</string>

            </field>

            <field name="description">

              <string>the /portal group</string>

            </field>

          </object>

        </value>

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$Group">

            <field name="name">

              <string>community</string>

            </field>

            <field name="parentId">

              <string>/portal</string>

            </field>

            <field name="type">

              <string>hierachy</string>

            </field>

            <field name="description">

              <string>the /portal/community group</string>

            </field>

          </object>

        </value>

        ...

      </collection>

    </field>

### Users

The predefined users are specified in the membershipType field of the OrganizationConfig plugin parameter.

    <field name="user">

      <collection type="java.util.ArrayList">

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$User">

            <field name="userName"><string>root</string></field>

            <field name="password"><string>exo</string></field>

            <field name="firstName"><string>root</string></field>

            <field name="lastName"><string>root</string></field>

            <field name="email"><string>exoadmin@localhost</string></field>

            <field name="groups"><string>member:/admin,member:/user,owner:/portal/admin</string></field>

          </object>

        </value>

        <value>

          <object type="org.exoplatform.services.organization.OrganizationConfig$User">

            <field name="userName"><string>exo</string></field>

            <field name="password"><string>exo</string></field>

            <field name="firstName"><string>site</string></field>

            <field name="lastName"><string>site</string></field>

            <field name="email"><string>exo@localhost</string></field>

            <field name="groups"><string>member:/user</string></field>

          </object>

        </value>

        ...

      </collection>

    </field>

### Plugin for monitoring user creation

The plugin of type org.exoplatform.services.organization.impl.NewUserEventListener specifies which groups all the newly created users should become members of. It specifies the groups and the memberships to use (while the group is just a set of users, a membership type represents a user's role within a group). It also specifies a list of users that should not be processed (i.e. administrative users like 'root').

### Note

The terms 'membership' and 'membership type' refer to the same thing, and are used interchangeably.

    <component-plugin>

      <name>new.user.event.listener</name>

      <set-method>addListenerPlugin</set-method>

      <type>org.exoplatform.services.organization.impl.NewUserEventListener</type>

      <description>this listener assign group and membership to a new created user</description>

      <init-params>

        <object-param>

          <name>configuration</name>

          <description>description</description>

          <object type="org.exoplatform.services.organization.impl.NewUserConfig">

            <field  name="group">

              <collection type="java.util.ArrayList">

                <value>

                  <object type="org.exoplatform.services.organization.impl.NewUserConfig$JoinGroup">

                    <field name="groupId"><string>/user</string></field>

                    <field name="membership"><string>member</string></field>

                  </object>

                </value>

              </collection>

            </field>

            <field  name="ignoredUser">

              <collection type="java.util.HashSet">

                <value><string>exo</string></value>

                <value><string>root</string></value>

                <value><string>company</string></value>

                <value><string>community</string></value>

              </collection>

            </field>

          </object>

        </object-param>

      </init-params>

    </component-plugin>

## Authentication Token Configuration

### What is Token Service?

Token Service is used in authentication.

The token system prevents user account information being sent in the clear text mode within inbound requests. This increases authentication security.

The token service allows administrators to create, delete, retrieve and clean tokens as required. The service also defines a validity period of any given token. The token becomes invalid once this period expires.

### Implement the Token Service API

All token services used in the GateIn 3.2 authentication must be implemented by subclassing an AbstractTokenService abstract class. The following AbstractTokenService methods represent the contract between authentication runtime, and a token service implementation.

            public Token getToken(String id) throws PathNotFoundException, RepositoryException;

            public Token deleteToken(String id) throws PathNotFoundException, RepositoryException;

            public String[] getAllTokens();

            public long getNumberTokens() throws Exception;

            public String createToken(Credentials credentials) throws IllegalArgumentException,NullPointerException;

            public Credentials validateToken(String tokenKey, boolean remove) throws NullPointerException;

### Configure token services

The token services configuration includes specifying the token validity period. The token service is configured as a portal component (in the portal scope, as opposed to the root scope - more about that in Foundations chapter).

In the example below, CookieTokenService is a subclass of AbstractTokenService, so it has a property which specifies the validity period of the token.

The token service will initialize this validity property by looking for an `init-param` named service.configuration.

This property must have three values.

    <component>

      <key>org.exoplatform.web.security.security.CookieTokenService</key>

      <type>org.exoplatform.web.security.security.CookieTokenService</type>

      <init-params>

        <values-param>

          <name>service.configuration</name>

          <value>jcr-token</value>

          <value>7</value>

          <value>DAY</value>

        </values-param>

      </init-params>

    </component>

| Service name
| Amount of time
| Unit of time

In this case, the service name is jcr-token and the token expiration time is one week.

GateIn 3.2 supports four time units:

1. `SECOND`

2. `MINUTE`

3. `HOUR`

4. `DAY`

## PicketLink IDM integration

GateIn 3.2 uses the PicketLink IDM component to keep the necessary identity information, such as users, groups, memberships. While legacy interfaces are still used (org.exoplatform.services.organization) for identity management, there is a wrapper implementation that delegates to the PicketLink IDM framework.

This section does not provide information about PicketLink IDM and its configuration. Please refer to the appropriate project documentation (http://jboss.org/picketlink/IDM.html) for further information.

### Note

It is important to fully understand the concepts behind this framework design before changing the default configuration.

The identity model represented in 'org.exoplatform.services.organization' interfaces and the one used in PicketLink IDM have some major differences.

The org.exoplatform.services.organization interface stores and manages information of users, groups or memberships, user profiles, relationships and retrieval. The management of org.exoplatform.services.organization interface is divided into many layers, such as model object, data access object and authentication.

For example: PicketLink IDM provides greater abstraction. It is possible for groups in IDM framework to form memberships with many parents (which requires recursive ID translation), while the GateIn model allows only pure tree-like membership structures.

Additionally, the GateIn membership concept needs to be translated into the IDM Role concept. Therefore, the PicketLink IDM model is used in a limited way. All these translations are applied by the integration layer.

### Configuration files

The main configuration file is idm-configuration.xml:

    <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"

                   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">

       <component>

            <key>org.exoplatform.services.organization.idm.PicketLinkIDMService</key>

          <type>org.exoplatform.services.organization.idm.PicketLinkIDMServiceImpl</type>

          <init-params>

             <value-param>

                <name>config</name>

                <value>war:/conf/organization/idm-config.xml</value>

             </value-param>

             <value-param>

                <name>portalRealm</name>

                <value>realm${container.name.suffix}</value>

             </value-param>

           </init-params>

       </component>

       <component>

          <key>org.exoplatform.services.organization.OrganizationService</key>

          <type>org.exoplatform.services.organization.idm.PicketLinkIDMOrganizationServiceImpl</type>

          <init-params>

          <object-param>

            <name>configuration</name>

            <object type="org.exoplatform.services.organization.idm.Config">

              <field name="useParentIdAsGroupType">

                <boolean>true</boolean>

              </field>

              <field name="forceMembershipOfMappedTypes">

                <boolean>true</boolean>

              </field>

              <field name="pathSeparator">

                <string>.</string>

              </field>

              <field name="rootGroupName">

                <string>GTN_ROOT_GROUP</string>

              </field>

              <field name="groupTypeMappings">

                <map type="java.util.HashMap">

                  <entry>

                    <key><string>/</string></key>

                    <value><string>root_type</string></value>

                  </entry>

                  <!-- Sample mapping -->

                  <!--

                  <entry>

                    <key><string>/platform/*</string></key>

                    <value><string>platform_type</string></value>

                  </entry>

                  <entry>

                    <key><string>/organization/*</string></key>

                    <value><string>organization_type</string></value>

                  </entry>

                  -->

                </map>

              </field>

              <field name="associationMembershipType">

                <string>member</string>

              </field>

              <field name="ignoreMappedMembershipType">

                <boolean>false</boolean>

              </field>

            </object>

          </object-param>

        </init-params>

       </component>

    </configuration>

| The org.exoplatform.services.organization.idm.PicketLinkIDMServiceImpl service has the following options: config (value-param) PicketLink IDM configuration file hibernate.properties (properties-param) A list of hibernate properties used to create SessionFactory that will be injected to JBoss Identity IDM configuration registry. hibernate.annotations A list of annotated classes that will be added to Hibernate configuration. hibernate.mappings A list of .xml files that will be added to the hibernate configuration as mapping files. jndiName (value-param) If the 'config' parameter is not provided, this parameter will be used to perform the JNDI lookup for IdentitySessionFactory. portalRealm (value-param) The realm name that should be used to obtain the proper IdentitySession. The default is 'PortalRealm'.
| The org.exoplatform.services.organization.idm.PicketLinkIDMOrganizationServiceImpl key is a main entrypoint implementing org.exoplatform.services.organization.OrganizationService and is dependant on org.exoplatform.services.organization.idm.PicketLinkIDMService org.exoplatform.services.organization.idm.PicketLinkIDMOrganizationServiceImpl service has the following options defined as fields of object-param of type org.exoplatform.services.organization.idm.Config: defaultGroupType The name of the PicketLink IDM GroupType that will be used to store groups. The default is 'GTN_GROUP_TYPE'. rootGroupName The name of the PicketLink IDM Group that will be used as a root parent. The default is 'GTN_ROOT_GROUP' passwordAsAttribute This parameter specifies if a password should be stored using the PicketLink IDM Credential object or as a plain attribute. The default value is set to false. useParentIdAsGroupType This parameter stores the parent ID path as a group type in PicketLink IDM for any IDs not mapped with a specific type in 'groupTypeMappings'. If this option is set to false, and no mappings are provided under 'groupTypeMappings', only one group with the given name can exist in the GateIn 3.2 group tree. pathSeparator When 'userParentIdAsGroupType' is set to true, this value will be used to replace all "/" characters in IDs. The "/" character is not allowed in the group type name in PicketLink IDM. associationMembershipType If this option is used, each Membership created with MembrshipType that is equal to the value specified here, will be stored in PicketLink IDM as the simple Group-User association. groupTypeMappings This parameter maps groups added with GateIn 3.2 API as children of a given group ID, and stores them with a given group type name in PicketLink IDM. If the parent ID ends with "/*", all child groups will have the mapped group type. Otherwises, only direct (first level) children will use this type. This can be leveraged by LDAP if the LDAP DN is configured in PicketLink IDM to only store a specific group type. This will then store the given branch in the GateIn 3.2 group tree, while all other groups will remain in the database. forceMembershipOfMappedTypes Groups stored in PicketLink IDM with a type mapped in 'groupTypeMappings' will automatically be members under the mapped parent. The Group relationships linked by the PicketLink IDM group association will not be necessary. This parameter can be set to false if all groups are added via GateIn 3.2 APIs. This may be useful with the LDAP configuration when being set to true, it will make every entry added to LDAP appear in GateIn 3.2. This, however, is not true for entries added via GateIn 3.2 management UI. ignoreMappedMembershipType If "associationMembershipType" option is used, and this option is set to true, Membership with MembershipType configured to be stored as PicketLink IDM association will not be stored as PicketLink IDM Role. Additionally, JBossIDMOrganizationServiceImpl uses those defaults to perform identity management operations. GateIn 3.2 User interface properties fields are persisted in JBoss Identity IDM using those attributes names: firstName, lastName, email, createdDate, lastLoginTime, organizationId, password (if password is configured to be stored as attribute). GateIn 3.2 Group interface properties fields are persisted in JBoss Identity IDM using those attributes names: label, description. GateIn 3.2 MembershipType interface properties fields are persisted in JBoss Identity IDM using those RoleType properties: description, owner, create_date, modified_date.

A sample PicketLink IDM configuration file is shown below. To understand all the options it contains, please refer to the PicketLink IDM Reference Guide.

    <jboss-identity xmlns="urn:jboss:identity:idm:config:v1_0_beta"

                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                    xsi:schemaLocation="urn:jboss:identity:idm:config:v1_0_alpha identity-config.xsd">

        <realms>

            <realm>

                <id>PortalRealm</id>

                <repository-id-ref>PortalRepository</repository-id-ref>

                <identity-type-mappings>

                    <user-mapping>USER</user-mapping>

                </identity-type-mappings>

            </realm>

        </realms>

        <repositories>

            <repository>

                <id>PortalRepository</id>

                <class>org.jboss.identity.idm.impl.repository.WrapperIdentityStoreRepository</class>

                <external-config/>

                <default-identity-store-id>HibernateStore</default-identity-store-id>

                <default-attribute-store-id>HibernateStore</default-attribute-store-id>

            </repository>

        </repositories>

        <stores>

            <attribute-stores/>

            <identity-stores>

                <identity-store>

                    <id>HibernateStore</id>

                    <class>org.jboss.identity.idm.impl.store.hibernate.HibernateIdentityStoreImpl</class>

                    <external-config/>

                    <supported-relationship-types>

                        <relationship-type>JBOSS_IDENTITY_MEMBERSHIP</relationship-type>

                        <relationship-type>JBOSS_IDENTITY_ROLE</relationship-type>

                    </supported-relationship-types>

                    <supported-identity-object-types>

                        <identity-object-type>

                            <name>USER</name>

                            <relationships/>

                            <credentials>

                                <credential-type>PASSWORD</credential-type>

                            </credentials>

                            <attributes/>

                            <options/>

                        </identity-object-type>

                    </supported-identity-object-types>

                    <options>

                        <option>

                            <name>hibernateSessionFactoryRegistryName</name>

                            <value>hibernateSessionFactory</value>

                        </option>

                        <option>

                            <name>allowNotDefinedIdentityObjectTypes</name>

                            <value>true</value>

                        </option>

                        <option>

                            <name>populateRelationshipTypes</name>

                            <value>true</value>

                        </option>

                        <option>

                            <name>populateIdentityObjectTypes</name>

                            <value>true</value>

                        </option>

                        <option>

                            <name>allowNotDefinedAttributes</name>

                            <value>true</value>

                        </option>

                        <option>

                            <name>isRealmAware</name>

                            <value>true</value>

                        </option>

                    </options>

                </identity-store>

            </identity-stores>

        </stores>

    </jboss-identity>

## Organization API

The exo.platform.services.organization package has five main components: user, user profile, group, membership type and membership. There is an additional component that serves as an entry point into Organization API - OrganizationService component that provides the handling functionality for the five components.

The User component contains basic information about the user, such as username, password, first name, last name, and email. The User Profile component contains extra information about a user, such as user's personal information, and business information. You can also add additional information about a user if your application requires it. The Group component contains a group graph. The Membership Type component contains a list of predefined membership types. Finally, the Membership component connects a User, a Group and a Membership Type.

A user can have one or more memberships within a group, for example: the user A can have two memberships: 'member' and 'admin' in the group /user. A user belongs to a group if he has at least one membership in that group.

Exposing the Organization API to developers who have access to the handler objects provided by the OrganizationService component. These handler objects are used to manage each of the five components, including UserHandler, UserProfileHandler, GroupHandler, MembershipTypeHandler, and MembershipHandler.

The five central API components are really designed like persistent entities, and handlers are really specified like data access objects (DAO).

Organization API simply describes a contract, meaning it is not a concrete implementation. The described components are interfaces, allowing different concrete implementations. Practically, it means that you can replace the existing implementation with a different one.

## Access User Profile

The following code retrieves the details for a logged-in user:

    // Alternative context: WebuiRequestContext context = WebuiRequestContext.getCurrentInstance() ;

    PortalRequestContext context = PortalRequestContext.getCurrentInstance() ;

    // Get the id of the user logged

    String userId = context.getRemoteUser();

    // Request the information from OrganizationService:

    OrganizationService orgService = getApplicationComponent(OrganizationService.class) ;

    if (userId != null)

      {

      User user = orgService.getUserHandler().findUserByName(userId) ;

      if (user != null)

      {

        String firstName = user.getFirstName();

        String lastName = user.getLastName();

        String email = user.getEmail();

      }

    }

Below are two alternatives for retrieving the Organization Service:

1.     OrganizationService service = (OrganizationService)

          ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(OrganizationService.class);

2.     OrganizationService service = (OrganizationService)

          PortalContainer.getInstance().getComponentInstanceOfType(OrganizationService.class);

## Single-Sign-On (SSO)

### Overview

GateIn 3.2 provides some forms of Single-Sign-On (SSO) as an integration and aggregation platform.

When logging into the portal, users gain access to many systems through portlets using a single identity. In many cases, the portal infrastructure must be integrated with other SSO enabled systems. There are many different Identity Management solutions available. In most cases, each SSO framework provides a unique way to plug into a Java EE application.

#### Prerequisites

In this tutorial, the SSO server is installed in a Tomcat installation. Tomcat can be obtained from http://tomcat.apache.org.

All the packages required for setup can be found in a zip file located at here. In this document, $GATEIN_SSO_HOME is called as the directory where the file is extracted.

It is recommended that you should not run any portal extensions that could override the data when manipulating the gatein.ear file directly.

Remove $JBOSS_HOME/server/default/deploy/gatein-sample-extension.ear and $JBOSS_HOME/server/default/deploy/gatein-sample-portal.ear which are packaged with GateIn 3.2 by default.

### Central Authentication Service (CAS)

This Single-Sign-On plugin enables the seamless integration between GateIn 3.2 and the CAS Single-Sign-On Framework. Details about CAS can be found here.

The integration consists of two steps: installing/configuring a CAS server and setting up the portal to use the CAS server.

#### CAS server

First, set up the server to authenticate against the portal login module. In this example, the CAS server is installed on Tomcat.

##### Obtaining CAS

CAS can be downloaded from http://www.jasig.org/cas/download. Tested version, which should work with these instructions is CAS 3.3.5, however other versions can also work without problems.

Extract the downloaded file into a suitable location. This location will be referred to as $CAS_HOME in the following instructions.

##### Modifying the CAS server

To configure the web archive as desired, the simplest way is to make the necessary changes directly in the CAS codebase.

### Note

To complete these instructions, and perform the final build step, you will need the Apache Maven 2. You can get it here.

First, change the default authentication handler with the one provided by GateIn 3.2.

The CAS Server Plugin makes secure authentication callbacks to a RESTful service installed on the remote GateIn 3.2 server to authenticate a user.

In order for the plugin to function correctly, it needs to be properly configured to connect to this service. This configuration is done via the cas.war/WEB-INF/deployerConfigContext.xml file.

1. Open CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml

2. Replace:

        <!--

         | Whereas CredentialsToPrincipalResolvers identify who it is some Credentials might authenticate,

         | AuthenticationHandlers actually authenticate credentials.  Here e declare the AuthenticationHandlers that

         | authenticate the Principals that the CredentialsToPrincipalResolvers identified.  CAS will try these handlers in turn

         | until it finds one that both supports the Credentials presented and succeeds in authenticating.

         +-->

        <property name="authenticationHandlers">

          <list>

            <!--

             | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating

             | a server side SSL certificate.

             +-->

            <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"

                  p:httpClient-ref="httpClient" />

            <!--

             | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS

             | into production.  The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials

             | where the username equals the password.  You will need to replace this with an AuthenticationHandler that implements your

             | local authentication strategy.  You might accomplish this by coding a new such handler and declaring

             | edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules.

             +-->

            <bean

               class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />

          </list>

        </property>

   With the following (Make sure to set the host, port and context with the values corresponding to your portal). Also available in GATEIN_SSO_HOME/cas/plugin/WEB-INF/deployerConfigContext.xml.

       <!--

        | Whereas CredentialsToPrincipalResolvers identify who it is some Credentials might authenticate,

        | AuthenticationHandlers actually authenticate credentials.  Here we declare the AuthenticationHandlers that

        | authenticate the Principals that the CredentialsToPrincipalResolvers identified.  CAS will try these handlers in turn

        | until it finds one that both supports the Credentials presented and succeeds in authenticating.

        +-->

        <property name="authenticationHandlers">

          <list>

            <!--

             | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating

             | a server side SSL certificate.

             +-->

            <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"

                  p:httpClient-ref="httpClient" />

            <!--

             | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS

             | into production.  The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials

             | where the username equals the password.  You will need to replace this with an AuthenticationHandler that implements your

             | local authentication strategy.  You might accomplish this by coding a new such handler and declaring

             | edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules.

             +-->

            <!-- Integrates with the Gatein Authentication Service to perform authentication -->

            <!--

             | Note: Modify the Plugin Configuration based on the actual information of a GateIn instance.

             | The instance can be anywhere on the internet...Not necessarily on localhost where CAS is running

             +-->

            <bean class="org.gatein.sso.cas.plugin.AuthenticationPlugin">

               <property name="gateInHost"><value>localhost</value></property>

               <property name="gateInPort"><value>8080</value></property>

               <property name="gateInContext"><value>portal</value></property>

            </bean>

          </list>

        </property>

3. Copy GATEIN_SSO_HOME/cas/plugin/WEB-INF/lib/sso-cas-plugin-<VERSION>.jar and GATEIN_SSO_HOME/cas/plugin/WEB-INF/lib/commons-httpclient-<VERSION>.jar into the CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/lib created directory.

4. Get an installation of Tomcat and extract it into a suitable location (which will be called TOMCAT_HOME for these instructions).

   Change the default port to avoid a conflict with the default GateIn 3.2 (for testing purposes). Edit TOMCAT_HOME/conf/server.xml and replace the 8080 port with 8888.

   ### Note

   If GateIn 3.2 is running on the same machine as Tomcat, other ports need to be changed in addition to 8080 to avoid port conflicts. They can be changed to any free port. For example, you can change admin port from 8005 to 8805, and AJP port from 8009 to 8809.

5. Go to CAS_HOME/cas-server-webapp and execute the command:

       mvn install

6. Copy CAS_HOME/cas-server-webapp/target/cas.war into TOMCAT_HOME/webapps.

   Tomcat should start and be accessible at http://localhost:8888/cas. At this stage, the login will not be available.

### Note

By default on logout the CAS server will display the CAS logout page with a link to return to the portal. To make the CAS server redirect to the portal page after a logout, modify the cas.war/WEB-INF/cas-servlet.xml to include the follow line :

            <bean id="logoutController" class="org.jasig.cas.web.LogoutController"
                      p:centralAuthenticationService-ref="centralAuthenticationService"
                      p:logoutView="casLogoutView"
                      p:warnCookieGenerator-ref="warnCookieGenerator"
                      p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"
                    p:followServiceRedirects="true"/>

#### Set up the CAS client

1. Copy all libraries from GATEIN_SSO_HOME/cas/gatein.ear/lib into JBOSS_HOME/server/default/deploy/gatein.ear/lib (Or in Tomcat, into $GATEIN_HOME/lib)

2. - In JBoss AS, edit gatein.ear/META-INF/gatein-jboss-beans.xml and uncomment on this section:

         <authentication>
           <login-module code="org.gatein.sso.agent.login.SSOLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
           <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
         </authentication>

   - In Tomcat, edit GATEIN_HOME/conf/jaas.conf, uncomment on this section and comment other parts:

         org.gatein.sso.agent.login.SSOLoginModule required;
         org.exoplatform.services.security.j2ee.TomcatLoginModule required
         portalContainerName=portal
         realmName=gatein-domain;

3. The installation can be tested at this point:

   1. Start (or restart) GateIn 3.2, and (assuming the CAS server on Tomcat is running) direct your browser to http://localhost:8888/cas.

   2. Login with the username root and the password gtn (or any account created through the portal).

#### Redirect to CAS

To utilize the Central Authentication Service, GateIn 3.2 needs to redirect all user authentication to the CAS server.

Information about where the CAS is hosted must be properly configured within the GateIn 3.2 instance. The required configuration is done by modifying three files:

- In the gatein.ear/web.war/groovy/groovy/webui/component/UIBannerPortlet.gtml file, modify the 'Sign In' link as follows:

      <!--
      <a class="Login" onclick="$signInAction"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>
      -->
      <a class="Login" href="/portal/sso"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>

- In the gatein.ear/web.war/groovy/portal/webui/component/UILogoPortlet.gtmpl file, modify the 'Sign In' link as follows:

      <!--
      <a onclick="$signInAction"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>
      -->
      <a href="/portal/sso"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>

- Replace the entire contents of gatein.ear/02portal.war/login/jsp/login.jsp with:

      <!-- HTML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
      <span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">script</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">type</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;text/javascript&quot;</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.location&nbsp;=&nbsp;'/portal/sso';</span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">script</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />

- Add the following filters at the top of the filter chain in gatein.ear/02portal.war/WEB-INF/web.xml:

      <filter>
         <filter-name>LoginRedirectFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.LoginRedirectFilter</filter-class>
         <init-param>
            <!-- This should point to your SSO authentication server -->
            <param-name>LOGIN_URL</param-name>
            <!-- If casRenewTicket param value of InitiateLoginServlet is: not specified or false -->
            <param-value>http://localhost:8888/cas/login?service=http://localhost:8080/portal/initiatessologin</param-value>
            <!-- If casRenewTicket param value of InitiateLoginServlet is : true -->
            <!-- <param-value>http://localhost:8888/cas/login? service=http://localhost:8080/portal/initiatessologin&amp;renew=true</param-value> -->
         </init-param>
      </filter>
      <filter>
         <filter-name>CASLogoutFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.CASLogoutFilter</filter-class>
         <init-param>
            <!-- This should point to your JOSSO authentication server -->
            <param-name>LOGOUT_URL</param-name>
            <param-value>http://localhost:8888/cas/logout</param-value>
         </init-param>
      </filter>
      <filter>
         <filter-name>InitiateLoginFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.InitiateLoginFilter</filter-class>
         <init-param>
            <param-name>ssoServerUrl</param-name>
            <param-value>http://localhost:8888/cas</param-value>
         </init-param>
         <init-param>
            <param-name>casRenewTicket</param-name>
            <param-value>false</param-value>
         </init-param>
         <init-param>
            <param-name>casServiceUrl</param-name>
            <param-value>http://localhost:8080/portal/initiatessologin</param-value>
         </init-param>
         <init-param>
            <param-name>loginUrl</param-name>
            <param-value>http://localhost:8080/portal/dologin</param-value>
         </init-param>
      </filter>

      <!-- Mapping the filters at the very top of the filter chain -->
      <filter-mapping>
         <filter-name>LoginRedirectFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>CASLogoutFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>InitiateLoginFilter</filter-name>
         <url-pattern>/initiatessologin</url-pattern>
      </filter-mapping>

Once these changes have been made, all links to the user authentication pages will redirect to the CAS centralized authentication form.

### JOSSO

This Single-Sign-On plugin enables the seamless integration between GateIn 3.2 and the JOSSO Single-Sign-On Framework. Details about JOSSO can be found here.

Setting up this integration consists of two steps: installing/configuring a JOSSO server, and setting up the portal to use the JOSSO server.

#### JOSSO server

This section describes how to set up the JOSSO server to authenticate against the GateIn 3.2 login module.

In this example, the JOSSO server will be installed on Tomcat.

##### Obtaining JOSSO

JOSSO can be downloaded from http://sourceforge.net/projects/josso/files/. Use the package that embeds Apache Tomcat.

Once downloaded, extract the package into what will be called JOSSO_HOME in this example.

### Warning

The steps described later are only correct in case of JOSSO v.1.8.1.

##### Modifying the JOSSO server

1. Copy the files from GATEIN_SSO_HOME/josso/plugin into the Tomcat directory (JOSSO_HOME).

   This action should replace or add the following files to the JOSSO_HOME/webapps/josso/WEB-INF/lib directory:

   - JOSSO_HOME/lib/josso-gateway-config.xml

   - JOSSO_HOME/lib/josso-gateway-gatein-stores.xml

   and

   - JOSSO_HOME/webapps/josso/WEB-INF/classes/gatein.properties

2. Edit TOMCAT_HOME/conf/server.xml and replace the 8080 port with 8888 to change the default Tomcat port and avoid a conflict with the default GateIn 3.2 port (for testing purposes).

   ### Port Conflicts

   If GateIn 3.2 is running on the same machine as Tomcat, other ports need to be changed in addition to 8080 to avoid port conflicts. They can be changed to any free port. For example, you can change the admin port from 8005 to 8805, and AJP port from 8009 to 8809.

3. Tomcat should now start and allow access to http://localhost:8888/josso/signon/login.do; but at this stage, login will not be available.

#### Set up the JOSSO client

1. Copy the library files from GATEIN_SSO_HOME/josso/gatein.ear/lib into gatein.ear/lib (or into GATEIN_HOME/lib if GateIn 3.2 is running in Tomcat)

2. Copy the file GATEIN_SSO_HOME/josso/gatein.ear/portal.war/WEB-INF/classes/josso-agent-config.xml into gatein.ear/02portal.war/WEB-INF/classes (or into GATEIN_HOME/webapps/portal.war/WEB-INF/classes, or GATEIN_HOME/conf if GateIn 3.2 is running in Tomcat)

3. - In JBoss AS, edit gatein.ear/META-INF/gatein-jboss-beans.xml and uncomment on this section:

         <authentication>
           <login-module code="org.gatein.sso.agent.login.SSOLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
           <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
         </authentication>

   - In Tomcat, edit GATEIN_HOME/conf/jaas.conf, uncomment on this section and comment other parts:

         org.gatein.sso.agent.login.SSOLoginModule required;
         org.exoplatform.services.security.j2ee.TomcatLoginModule requiredtm
         portalContainerName=portal
         realmName=gatein-domain;

4. The installation can be tested at this point.

   1. Start (or restart) GateIn 3.2, and (assuming the JOSSO server on Tomcat is running) direct your browser to http://localhost:8888/josso/signon/login.do.

   2. Login with the username root and the password gtn or any account created through the portal.

#### Set up the portal to redirect to JOSSO

The next part of the process redirects all user authentication to the JOSSO server.

Information about where the JOSSO server is hosted must be properly configured within the GateIn 3.2 instance. The required configuration is done by modifying four files:

- In the gatein.ear/web.war/groovy/groovy/webui/component/UIBannerPortlet.gtml file, modify the 'Sign In' link as follows:

      <!--
      <a class="Login" onclick="$signInAction"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>
      -->
      <a class="Login" href="/portal/sso"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>

- In the gatein.ear/web.war/groovy/portal/webui/component/UILogoPortlet.gtmpl file, modify the 'Sign In' link as follows:

      <!--
      <a onclick="$signInAction"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>
      -->
      <a href="/portal/sso"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>

- Replace the entire contents of gatein.ear/02portal.war/login/jsp/login.jsp with:

      <!-- HTML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
      <span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">script</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">type</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;text/javascript&quot;</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.location&nbsp;=&nbsp;'/portal/sso';</span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">script</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />

- Add the following filters at the top of the filter chain in gatein.ear/02portal.war/WEB-INF/web.xml:

      <filter>
         <filter-name>LoginRedirectFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.LoginRedirectFilter</filter-class>
         <init-param>
            <!-- This should point to your SSO authentication server -->
            <param-name>LOGIN_URL</param-name>
            <param-value>http://localhost:8888/josso/signon/login.do?josso_back_to=http://localhost:8080/portal/initiatessologin</param-value>
         </init-param>
      </filter>
      <filter>
         <filter-name>JOSSOLogoutFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.JOSSOLogoutFilter</filter-class>
         <init-param>
            <!-- This should point to your JOSSO authentication server -->
            <param-name>LOGOUT_URL</param-name>
            <param-value>http://localhost:8888/josso/signon/logout.do</param-value>
         </init-param>
      </filter>
      <filter>
         <filter-name>InitiateLoginFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.InitiateLoginFilter</filter-class>
         <init-param>
            <param-name>ssoServerUrl</param-name>
            <param-value>http://localhost:8888/josso/signon/login.do</param-value>
         </init-param>
         <init-param>
            <param-name>loginUrl</param-name>
            <param-value>http://localhost:8080/portal/dologin</param-value>
         </init-param>
      </filter>

      <!-- Mapping the filters at the very top of the filter chain -->
      <filter-mapping>
         <filter-name>LoginRedirectFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>JOSSOLogoutFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>InitiateLoginFilter</filter-name>
         <url-pattern>/initiatessologin</url-pattern>
      </filter-mapping>

From now on, all links redirecting to the user authentication pages will redirect to the JOSSO centralized authentication form.

### OpenSSO - The Open Web SSO project

This Single-Sign-On plugin enables the seamless integration between GateIn 3.2 and the OpenSSO Single Sign On Framework. Details about OpenSSO can be found here.

Setting up this integration consists of two steps: installing/configuring an OpenSSO server, and setting up the portal to use the OpenSSO server.

#### OpenSSO server

This section details the setup of OpenSSO server to authenticate against the GateIn 3.2 login module.

In this example, the OpenSSO server will be installed on Tomcat.

##### Obtaining OpenSSO

OpenSSO can be downloaded from http://download.oracle.com/otn/nt/middleware/11g/oracle_opensso_80U2.zip.

Once downloaded, extract the package into a suitable location. This location will be referred to as OPENSSO_HOME in this example.

### Note

There is also possibility to use OpenAM instead of OpenSSO server. OpenAM is free and integration steps with GateIn 3.2 and OpenAM are very similar as with OpenSSO. More info is here .

##### Modifying the OpenSSO server

To configure the web server as desired, it is simpler to directly modify the sources.

The first step is to add the GateIn 3.2 Authentication Plugin:

The plugin makes secure authentication callbacks to a RESTful service installed on the remote GateIn 3.2 server to authenticate a user.

In order for the plugin to function correctly, it needs to be properly configured to connect to this service. This configuration is done via the opensso.war/config/auth/default/AuthenticationPlugin.xml file.

1. Obtain a copy of Tomcat and extract it into a suitable location (this location will be referred to as TOMCAT_HOME in this example).

2. Change the default port to avoid a conflict with the default GateIn 3.2 port (for testing purposes) by editing TOMCAT_HOME/conf/server.xml and replacing the 8080 port with 8888.

   ### Note

   If GateIn 3.2 is running on the same machine as Tomcat, other ports need to be changed in addition to 8080 to avoid port conflicts. They can be changed to any free port. For example, you can change the admin port from 8005 to 8805, and AJP port from 8009 to 8809.

3. Ensure the TOMCAT_HOME/webapps/opensso/config/auth/default/AuthenticationPlugin.xml file looks like this:

       <?xml version='1.0' encoding="UTF-8"?>

       <!DOCTYPE ModuleProperties PUBLIC "=//iPlanet//Authentication Module Properties XML Interface 1.0 DTD//EN"

                 "jar://com/sun/identity/authentication/Auth_Module_Properties.dtd">

       <ModuleProperties moduleName="AuthenticationPlugin" version="1.0" >

         <Callbacks length="2" order="1" timeout="60"

                    header="GateIn OpenSSO Login" >

           <NameCallback>

             <Prompt>

               Username

             </Prompt>

           </NameCallback>

           <PasswordCallback echoPassword="false" >

             <Prompt>

               Password

             </Prompt>

           </PasswordCallback>

         </Callbacks>

       </ModuleProperties>

4. Copy GATEIN_SSO_HOME/opensso/plugin/WEB-INF/lib/sso-opensso-plugin-<VERSION>.jar, GATEIN_SSO_HOME/opensso/plugin/WEB-INF/lib/commons-httpclient-<VERSION>.jar, and GATEIN_SSO_HOME/opensso/plugin/WEB-INF/lib/commons-logging-<VERSION>.jar into the Tomcat directory at TOMCAT_HOME/webapps/opensso/WEB-INF/lib.

5. Copy GATEIN_SSO_HOME/opensso/plugin/WEB-INF/classes/gatein.properties into TOMCAT_HOME/webapps/opensso/WEB-INF/classes.

6. Tomcat should start and be able to access http://localhost:8888/opensso/UI/Login?realm=gatein. Login will not be available at this point.

Configure the "gatein" realm:

1. Direct your browser to http://localhost:8888/opensso.

2. Create the default configuration.

3. Login as amadmin and then go to the Configuration tab -> Authentication -> Core link -> add a new value and fill in the class name org.gatein.sso.opensso.plugin.AuthenticationPlugin. This step is really important. If not, AuthenticationPlugin is not available among other the OpenSSO authentication modules.

4. Go to the Access control tab and create the new realm called gatein.

5. Go to the "gatein" realm and click the Authentication tab. At the bottom of the Authentication chaining section, click ldapService. Here, change the selection from "Datastore", which is the default module in the authentication chain, to AuthenticationPlugin. This enables the authentication of "gatein" realm by using the GateIn REST service instead of the OpenSSO LDAP server.

6. Go to Advanced properties and change UserProfile from Required to Dynamic. This step is needed because GateIn 3.2 users are not in the OpenSSO Datastore (LDAP server), so their profiles can not be obtained if "Required" is active. By using "Dynamic", all new users are automatically created in the OpenSSO datastore after successful authentication.

7. Increase the user privileges to allow the REST access. Go to Access control -> Top level realm -> Privileges tab -> All authenticated users, and check the last two checkboxes:

   - Read and write access only for policy properties.

   - Read and write access to all realm and policy properties.

8. Repeat previous step with increasing privileges for gatein realm as well.

#### Set up the OpenSSO client.

1. Copy all libraries from GATEIN_SSO_HOME/opensso/gatein.ear/lib into JBOSS_HOME/server/default/deploy/gatein.ear/lib (Or, in Tomcat, into GATEIN_HOME/lib)

2. - In JBoss AS, edit gatein.ear/META-INF/gatein-jboss-beans.xml and uncomment on this section

         <authentication>
           <login-module code="org.gatein.sso.agent.login.SSOLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
           <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule" flag="required">
             <module-option name="portalContainerName">portal</module-option>
             <module-option name="realmName">gatein-domain</module-option>
           </login-module>
         </authentication>

   - If you are running GateIn 3.2 in Tomcat, edit $GATEIN_HOME/conf/jaas.conf, uncomment on this section and comment other parts:

         org.gatein.sso.agent.login.SSOLoginModule required;
         org.exoplatform.services.security.j2ee.TomcatLoginModule required
         portalContainerName=portal
         realmName=gatein-domain;

   At this point, the installation can be tested:

   1. Access GateIn 3.2 by going to http://localhost:8888/opensso/UI/Login?realm=gatein (assuming that the OpenSSO server using Tomcat is still running).

   2. Login with the username root and the password gtn or any account created through the portal.

#### Set up the portal to redirect to OpenSSO

The next part of the process is to redirect all user authentication to the OpenSSO server.

Information about where the OpenSSO server is hosted must be properly configured within the Enterprise Portal Platform instance. The required configuration is done by modifying three files:

- In the gatein.ear/web.war/groovy/groovy/webui/component/UIBannerPortlet.gtml file, modify the 'Sign In' link as follows:

      <!--
      <a class="Login" onclick="$signInAction"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>
      -->
      <a class="Login" href="/portal/sso"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>

- In the gatein.ear/web.war/groovy/portal/webui/component/UILogoPortlet.gtmpl file, modify the 'Sign In' link as follows:

      <!--
      <a onclick="$signInAction"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>
      -->
      <a href="/portal/sso"><%=_ctx.appRes("UILogoPortlet.action.signin")%></a>

- Replace the entire contents of gatein.ear/02portal.war/login/jsp/login.jsp with:

      <!-- HTML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
      <span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">script</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">type</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;text/javascript&quot;</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.location&nbsp;=&nbsp;'/portal/sso';</span><br />
      <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">script</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">head</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">body</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
      <span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">html</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />

- Add the following filters at the top of the filter chain in gatein.ear/02portal.war/WEB-INF/web.xml:

      <filter>
         <filter-name>LoginRedirectFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.LoginRedirectFilter</filter-class>
         <init-param>
            <!-- This should point to your SSO authentication server -->
            <param-name>LOGIN_URL</param-name>
            <param-value>http://localhost:8888/opensso/UI/Login?realm=gatein&amp;goto=http://localhost:8080/portal/initiatessologin</param-value>
         </init-param>
      </filter>
      <filter>
         <filter-name>OpenSSOLogoutFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.OpenSSOLogoutFilter</filter-class>
         <init-param>
            <!-- This should point to your SSO authentication server -->
            <param-name>LOGOUT_URL</param-name>
            <param-value>http://localhost:8888/opensso/UI/Logout</param-value>
         </init-param>
      </filter>
      <filter>
         <filter-name>InitiateLoginFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.InitiateLoginFilter</filter-class>
         <init-param>
            <param-name>ssoServerUrl</param-name>
            <param-value>http://localhost:8888/opensso</param-value>
         </init-param>
         <init-param>
            <param-name>loginUrl</param-name>
            <param-value>http://localhost:8080/portal/dologin</param-value>
         </init-param>
         <init-param>
            <param-name>ssoCookieName</param-name>
            <param-value>iPlanetDirectoryPro</param-value>
         </init-param>
      </filter>

      <!-- Mapping the filters at the very top of the filter chain -->
      <filter-mapping>
         <filter-name>LoginRedirectFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>OpenSSOLogoutFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
         <filter-name>InitiateLoginFilter</filter-name>
         <url-pattern>/initiatessologin</url-pattern>
      </filter-mapping>

From now on, all links redirecting to the user authentication pages will redirect to the OpenSSO centralized authentication form.

### SPNEGO

SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) is used to authenticate transparently through the web browser after the user has been authenticated when logging-in his session.

A typical use case is the following:

1. The user logs into the desktop, such as a Windows machine.

2. The desktop login is governed by the Active Directory domain.

3. Next, the user opens the browser (IE/Firefox) to access a web application (that uses JBoss Negotiation) hosted on JBoss EPP.

4. The Browser transfers the desktop sign-on information to the web application.

5. JBoss EAP/AS uses the background GSS messages with the Active Directory (or any Kerberos Server) to validate the Kerberos ticket from user.

6. The User has a seamless SSO into the web application.

#### SPNEGO Server Configuration

In this section, we will describe some necessary steps for setup Kerberos server on Linux. This server will then be used for SPNEGO authentication against GateIn 3.2

### Note

If you don't have Linux but you are using Windows and Active Directory domain, then these informations are not important for you and you may jump to the the section called “GateIn 3.2 Configuration” to see how to integrate SPNEGO with GateIn 3.2. Please note that Kerberos setup is also dependent on your Linux distribution and so steps can be slightly different in your environment.

1. Correct the setup of network on the machine. For example, if you are using the "server.local.network" domain as your machine where Kerberos and GateIn 3.2 are located, add the line containing the machine's IP address to the /etc/hosts file.

       192.168.1.88  server.local.network

   ### Note

   It is not recommended to use loopback addresses.

2. Install Kerberos with these packages: krb5-admin-server, krb5-kdc, krb5-config, krb5-user, krb5-clients, and krb5-rsh-server.

3. Edit the Kerberos configuration file at /etc/krb5.config, including:

   - Uncomment on these lines:

         default_tgs_enctypes = des3-hmac-sha1
         default_tkt_enctypes = des3-hmac-sha1
         permitted_enctypes = des3-hmac-sha1

   - Add local.network as a default realm and it is also added to the list of realms and remove the remains of realms. The content looks like:

         [libdefaults]
             default_realm = LOCAL.NETWORK

         # The following krb5.conf variables are only for MIT Kerberos.
             krb4_config = /etc/krb.conf
             krb4_realms = /etc/krb.realms
             kdc_timesync = 1
             ccache_type = 4
             forwardable = true
             proxiable = true

         # The following encryption type specification will be used by MIT Kerberos
         # if uncommented.  In general, the defaults in the MIT Kerberos code are
         # correct and overriding these specifications only serves to disable new
         # encryption types as they are added, creating interoperability problems.
         #
         # Thie only time when you might need to uncomment these lines and change
         # the enctypes is if you have local software that will break on ticket
         # caches containing ticket encryption types it doesn't know about (such as
         # old versions of Sun Java).

             default_tgs_enctypes = des3-hmac-sha1
             default_tkt_enctypes = des3-hmac-sha1
             permitted_enctypes = des3-hmac-sha1

         # The following libdefaults parameters are only for Heimdal Kerberos.
             v4_instance_resolve = false
             v4_name_convert = {
                 host = {
                     rcmd = host
                     ftp = ftp
                 }
                 plain = {
                     something = something-else
                 }
             }
             fcc-mit-ticketflags = true

         [realms]
             LOCAL.NETWORK = {
                 kdc = server.local.network
                 admin_server = server.local.network
             }

         [domain_realm]
             .local.network = LOCAL.NETWORK
             local.network = LOCAL.NETWORK

         [login]
             krb4_convert = true
             krb4_get_tickets = false

4. Edit the KDC configuraton file at /etc/krb5kdc/kdc.conf that looks like.

       [kdcdefaults]
           kdc_ports = 750,88

       [realms]
           LOCAL.NETWORK = {
               database_name = /home/gatein/krb5kdc/principal
               admin_keytab = FILE:/home/gatein/krb5kdc/kadm5.keytab
               acl_file = /home/gatein/krb5kdc/kadm5.acl
               key_stash_file = /home/gatein/krb5kdc/stash
               kdc_ports = 750,88
               max_life = 10h 0m 0s
               max_renewable_life = 7d 0h 0m 0s
               master_key_type = des3-hmac-sha1
               supported_enctypes = aes256-cts:normal arcfour-hmac:normal des3-hmac-sha1:normal des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3
               default_principal_flags = +preauth
           }

       [logging]
               kdc = FILE:/home/gatein/krb5logs/kdc.log
               admin_server = FILE:/home/gatein/krb5logs/kadmin.log

   - Create krb5kdc and krb5logs directory for Kerberos database as shown in the configuration file above.

   - Next, create a KDC database using the following command.

         sudo krb5_newrealm

   - Start the KDC and Kerberos admin servers using these commands:

         sudo /etc/init.d/krb5-kdc restart
         sudo /etc/init.d/krb-admin-server restart

5. Add Principals and create Keys.

   - Start an interactive 'kadmin' session and create the necessary Principals.

         sudo kadmin.local

   - Add the GateIn 3.2 machine and keytab file that need to be authenticated.

         addprinc -randkey HTTP/server.local.network@LOCAL.NETWORK
         ktadd HTTP/server.local.network@LOCAL.NETWORK

   - Add the default GateIn 3.2 user accounts and enter the password for each created user that will be authenticated.

         addprinc john
         addprinc demo
         addprinc root

6. Test your changed setup by using the command.

       kinit -A demo

   - If the setup works well, you are required to enter the password created for this user in Step 5. Without the -A, the kerberos ticket validation involved reverse DNS lookups, which can get very cumbersome to debug if your network's DNS setup is not great. This is a production level security feature, which is not necessary in this development setup. In production environment, it will be better to avoid -A option.

   - After successful login to Kerberos, you can see your Kerberos ticket when using this command.

         klist

   - If you want to logout and destroy your ticket, use this command.

         kdestroy

#### Clients

After performing all configurations above, you need to enable the Negotiate authentication of Firefox in client machines so that clients could be authenticated by GateIn 3.2 as follows:

1. Start Firefox, then enter the command: about:config into the address field.

2. Enter network.negotiate-auth and set the value as below:

       network.negotiate-auth.allow-proxies = true
       network.negotiate-auth.delegation-uris = .local.network
       network.negotiate-auth.gsslib (no-value)
       network.negotiate-auth.trusted-uris = .local.network
       network.negotiate-auth.using-native-gsslib = true

### Note

Consult documentation of your OS or web browser if using different browser than Firefox.

#### GateIn 3.2 Configuration

GateIn 3.2 uses JBoss Negotiation to enable SPNEGO-based desktop SSO for the portal. Here are the steps to integrate SPNEGO with GateIn 3.2.

1. Activate the Host authentication under the JBOSS_HOME/server/default/conf/login-config.xml file by adding the following host login module:

       <!-- SPNEGO domain -->
       <application-policy name="host">
         <authentication>
           <login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
             <module-option name="storeKey">true</module-option>
             <module-option name="useKeyTab">true</module-option>
             <module-option name="principal">HTTP/server.local.network@LOCAL.NETWORK</module-option>
             <module-option name="keyTab">/etc/krb5.keytab</module-option>
             <module-option name="doNotPrompt">true</module-option>
             <module-option name="debug">true</module-option>
           </login-module>
         </authentication>
        </application-policy>

   The 'keyTab' value should point to the keytab file that was generated by the kadmin kerberos tool. When using Kerberos on Linux, it should be value of parameter admin_keytab from kdc.conf file. See the the section called “SPNEGO Server Configuration” section for more details.

2. Extend the core authentication mechanisms to support SPNEGO under JBOSS_HOME/server/default/deployers/jbossweb.deployer/META-INF/war-deployers-jboss-beans.xml by adding the 'SPNEGO' authenticators property.

       <deployment xmlns="urn:jboss:bean-deployer:2.0">

       <property name="authenticators">

         <map class="java.util.Properties" keyClass="java.lang.String" valueClass="java.lang.String">

           <entry>

             <key>BASIC</key>

             <value>org.apache.catalina.authenticator.BasicAuthenticator</value>

           </entry>

           <entry>

             <key>CLIENT-CERT</key>

             <value>org.apache.catalina.authenticator.SSLAuthenticator</value>

           </entry>

           <entry>

             <key>DIGEST</key>

             <value>org.apache.catalina.authenticator.DigestAuthenticator</value>

           </entry>

           <entry>

             <key>FORM</key>

             <value>org.apache.catalina.authenticator.FormAuthenticator</value>

           </entry>

           <entry>

             <key>NONE</key>

             <value>org.apache.catalina.authenticator.NonLoginAuthenticator</value>

           </entry>

           <!-- Add this entry -->

           <entry>

             <key>SPNEGO</key>

               <value>org.gatein.sso.spnego.GateInNegotiationAuthenticator</value>

           </entry>

         </map>

       </property>

3. Add the GateIn SSO module binaries by copying GATEIN_SSO_HOME/spnego/gatein.ear/lib/sso-agent-VERSION.jar to the JBOSS_HOME/server/default/deploy/gatein.ear/lib directory. File GATEIN_SSO_HOME/spnego/gatein.ear/lib/spnego-VERSION.jar needs to be copied to the JBOSS_HOME/server/default/lib directory.

4. Download library `jboss-negotiation-2.0.4.GA` from location https://repository.jboss.org/nexus/content/groups/public/org/jboss/security/jboss-negotiation/2.0.4.GA/jboss-negotiation-2.0.4.GA.jar and copy this file to `JBOSS_HOME/server/default/lib` directory as well.

5. Modify the JBOSS_HOME/server/defaut/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml file as below:

       <deployment xmlns="urn:jboss:bean-deployer:2.0">

         <application-policy xmlns="urn:jboss:security-beans:1.0" name="gatein-form-auth-domain">

           <authentication>

             <login-module code="org.gatein.wci.security.WCILoginModule" flag="optional">

               <module-option name="portalContainerName">portal</module-option>

               <module-option name="realmName">gatein-domain</module-option>

             </login-module>

             <login-module code="org.exoplatform.services.security.jaas.SharedStateLoginModule" flag="required">

               <module-option name="portalContainerName">portal</module-option>

               <module-option name="realmName">gatein-domain</module-option>

             </login-module>

             <!-- Uncomment this part to check on each login if user is member of "/platform/users" group and if not

                  create such membership -->

             <!--

             <login-module code="org.exoplatform.services.organization.idm.CustomMembershipLoginModule" flag="required">

               <module-option name="portalContainerName">portal</module-option>

               <module-option name="realmName">gatein-domain</module-option>

               <module-option name="membershipType">member</module-option>

               <module-option name="groupId">/platform/users</module-option>

             </login-module>

             -->

             <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule" flag="required">

               <module-option name="portalContainerName">portal</module-option>

       <!-- logout needs to be performed from 'gatein-domain' as it is used for JaasSecurityManager. -->

               <module-option name="realmName">gatein-domain</module-option>

             </login-module>

           </authentication>

         </application-policy>

         <application-policy xmlns="urn:jboss:security-beans:1.0" name="gatein-domain">

           <authentication>

            <login-module

                code="org.gatein.sso.spnego.SPNEGOLoginModule"

                flag="requisite">

                <module-option name="password-stacking">useFirstPass</module-option>

                <module-option name="serverSecurityDomain">host</module-option>

            <module-option name="removeRealmFromPrincipal">true</module-option>

            <module-option name="usernamePasswordDomain">gatein-form-auth-domain</module-option>

             </login-module>

             <login-module

                code="org.gatein.sso.agent.login.SPNEGORolesModule"

                flag="required">

             <module-option name="password-stacking">useFirstPass</module-option>

             <module-option name="portalContainerName">portal</module-option>

             <module-option name="realmName">gatein-domain</module-option>

             </login-module>

          </authentication>

         </application-policy>

       </deployment>

   This activates SPNEGO LoginModules with fallback to FORM authentication. When SPNEGO is not available and it needs to fallback to FORM, it will use gatein-form-auth-domain security domain. More details below.

6. Modify JBOSS_HOME/server/default/deploy/gatein.ear/02portal.war/WEB-INF/web.xml as below.

       <!--    <login-config>

             <auth-method>FORM</auth-method>

             <realm-name>gatein-domain</realm-name>

               <form-login-config>

                 <form-login-page>/initiatelogin</form-login-page>

                   <form-error-page>/errorlogin</form-error-page>

             </form-login-config>

           </login-config>

       -->

           <login-config>

             <auth-method>SPNEGO</auth-method>

             <realm-name>SPNEGO</realm-name>

             <form-login-config>

                <form-login-page>/initiatelogin</form-login-page>

                <form-error-page>/errorlogin</form-error-page>

            </form-login-config>

           </login-config>

   This integrates SPNEGO support into the Portal web archive by switching the authentication mechanism from the default "FORM"-based to "SPNEGO"-based authentication. You can notice that SPNEGO part also contains element form-login-config, which is needed if you want to enable fallback to FORM based authentication. In this case, portal will try to authenticate user with his Kerberos ticket through SPNEGO. If user don't have Kerberos ticket, he will be redirected to FORM (GateIn 3.2 login screen). So first attempt is for login with SPNEGO and next attempt is for login with FORM, which is used only if login through SPNEGO is not successful (For example user don't have valid Kerberos ticket or his browser doesn't support SPNEGO with our Kerberos server).

   If you don't want fallback to FORM, you can disable form-login-config part and have only:

       <!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
       <span class="xml_plain"></span><br />
       <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">login-config</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">auth-method</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">SPNEGO</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">auth-method</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">realm-name</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">SPNEGO</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">realm-name</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_comment">&lt;!--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form-login-config&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form-login-page&gt;/initiatelogin&lt;/form-login-page&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form-error-page&gt;/errorlogin&lt;/form-error-page&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/form-login-config&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_comment">--&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">login-config</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
       <span class="xml_plain"></span><br />

   In this case user needs to authenticate through SPNEGO and if that fails, FORM is not shown but user has authentication error with HTTP code 401.

7. Integrate the request pre-processing needed for SPNEGO via filters by adding the following filters to the JBOSS_HOME/server/default/deploy/gatein.ear/02portal.war/WEB-INF/web.xml at the top of the Filter chain.

       <filter>
         <filter-name>LoginRedirectFilter</filter-name>
         <filter-class>org.gatein.sso.agent.filter.LoginRedirectFilter</filter-class>
         <init-param>
         <!-- This should point to your SSO authentication server -->
           <param-name>LOGIN_URL</param-name>
           <param-value>/portal/private/classic</param-value>
         </init-param>
       </filter>

       <filter>
        <filter-name>SPNEGOFilter</filter-name>
        <filter-class>org.gatein.sso.agent.filter.SPNEGOFilter</filter-class>
       </filter>

       <filter-mapping>
         <filter-name>LoginRedirectFilter</filter-name>
         <url-pattern>/*</url-pattern>
       </filter-mapping>

       <filter-mapping>
         <filter-name>SPNEGOFilter</filter-name>
         <url-pattern>/login</url-pattern>
       </filter-mapping>

8. In `JBOSS_HOME/server/default/deploy/gatein.ear/web.war/groovy/groovy/webui/component/UIBannerPortlet.gtml` file modify the 'Sign In' link as follows:

       <!--
       <a class="Login" onclick="$signInAction"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>
       -->
       <a class="Login" href="/portal/sso"><%=_ctx.appRes("UILoginForm.label.Signin")%></a>

9. Start the GateIn 3.2 portal using the command below.

       sudo ./run.sh -Djava.security.krb5.realm=LOCAL.NETWORK -Djava.security.krb5.kdc=server.local.network -c default -b server.local.network

10. Login to Kerberos with the command.

        kinit -A demo

    You should be able to click the 'Sign In' link on the GateIn 3.2 portal and the 'demo' user from the GateIn 3.2 portal should be automatically logged in.

11. Let's try to destroy kerberos ticket with command

        kdestroy

    Then try to login again. You will now be placed to login screen of GateIn 3.2 because you don't have active Kerberos ticket. You can login with predefined account and password "demo"/"gtn" .