4.1.1. Login modules

So from WCI servlet API login, you are redirected to the JAAS authentication. GateIn Portal is using its own security domain named gatein-domain with a set of predefined login modules. Login module configuration for gatein-domain is in:

By default, you can see this login modules stack:


<security-domain name="gatein-domain" cache-type="default">
  <authentication>
    <login-module code="org.gatein.sso.integration.SSODelegateLoginModule" flag="required">
      <module-option name="enabled" value="${gatein.sso.login.module.enabled}" />
      <module-option name="delegateClassName" value="${gatein.sso.login.module.class}" />
      <module-option name="portalContainerName" value="portal" />
      <module-option name="realmName" value="gatein-domain" />
      <module-option name="password-stacking" value="useFirstPass" />
    </login-module>
    <login-module code="org.exoplatform.services.security.j2ee.JBossAS7LoginModule" flag="required">
      <module-option name="portalContainerName" value="portal"/>
      <module-option name="realmName" value="gatein-domain"/>
    </login-module>
  </authentication>
</security-domain>

You are free to add some new login modules or completely replace existing login modules with your own ones.

Authentication starts with invoke of the login method on each login module. After all login methods are invoked, the authentication is continued by invoke of the commit method on each login module. Both login and commit methods can throw LoginException. If it happens, then the whole authentication ends unsuccessfully, which in next turn invokes the abort method on each login module. By returning "false" from method login, you can ensure that login module is ignored. This is not specific to GateIn Portal but it is generic to JAAS. See here for more information about login modules.

Existing login modules

Here is brief description of existing login modules:

There is couple of other login modules, which are not active by default, but you can add them if you find them useful.

Configuration example with CustomMembershipLoginModule and disabled SSO:


<login-module code="org.exoplatform.web.security.InitSharedStateLoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
</login-module>
<login-module code="org.exoplatform.services.security.jaas.SharedStateLoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
</login-module>
<login-module code="org.exoplatform.services.organization.idm.CustomMembershipLoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
  <module-option name="membershipType" value="member" />
  <module-option name="groupId" value="/platform/users" />
</login-module>
<login-module code="org.exoplatform.services.security.j2ee.JBossAS7LoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
</login-module>

And now configuration example with enabled SSO:


<login-module code="org.gatein.sso.integration.SSODelegateLoginModule" flag="required">
  <module-option name="enabled" value="${gatein.sso.login.module.enabled}" />
  <module-option name="delegateClassName" value="${gatein.sso.login.module.class}" />
  <module-option name="portalContainerName" value="portal" />
  <module-option name="realmName" value="gatein-domain" />
  <module-option name="password-stacking" value="useFirstPass" />
</login-module>
<login-module code="org.exoplatform.services.organization.idm.CustomMembershipLoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
  <module-option name="membershipType" value="member" />
  <module-option name="groupId" value="/platform/users" />
</login-module>
<login-module code="org.exoplatform.services.security.j2ee.JBossAS7LoginModule" flag="required">
  <module-option name="portalContainerName" value="portal"/>
  <module-option name="realmName" value="gatein-domain"/>
</login-module>

Creating your own login module

Before creating your own login module, it is recommended you study source code of existing login modules to better understand the whole JAAS authentication process. You need to have good knowledge so that you can properly decide where your login module should be placed and if you need to replace some existing login modules or simply attach your own module to the existing chain.

There are actually two levels of authentication and the overall result of JAAS authentication should properly handle both these cases:

Authentication at application server level

Application server needs to properly recognize that the user is successfully logged and it has assigned his JAAS roles. Unfortunately this part is not standardized and is specific for each AS. For example in JBoss AS, you need to ensure that JAAS Subject has assigned principal with username (UserPrincipal) and also RolesPrincipal, which has name "Roles" and it contains a list of JAAS roles. This part is actually done in JbossLoginModule.commit(). In Tomcat, this flow is little different, which means Tomcat has it is own TomcatLoginModule.

After successful authentication, the user needs to be at least in JAAS role users because this role is declared in web.xml as you saw above. The JAAS roles are extracted by the special algorithm from GateIn Portal memberships. See below in section with RolesExtractor.

Authentication at Portal level

The login process needs to create a special object: org.exoplatform.services.security.Identity and register this object into IdentityRegistry component of GateIn Portal. This Identity object should encapsulate username of authenticated user, memberships of this user and JAAS roles. Identity object can be easily created with the Authenticator interface as shown below.

Authenticator and RolesExtractor

Authenticator is an important component in the authentication process. Actually the org.exoplatform.services.security.Authenticator interface looks like this:

public interface Authenticator
{

   /**
    * Authenticate user and return userId.
    *
    * @param credentials - list of users credentials (such as name/password, X509
    *          certificate etc)
    * @return userId
    */
   String validateUser(Credential[] credentials) throws LoginException, Exception;

   /**
    * @param userId.
    * @return Identity
    */
   Identity createIdentity(String userId) throws Exception;

}
            

The validateUser method is used to check whether given credentials (username and password) are really valid. So it performs real authentication. It returns the username if credentials are correct. Otherwise, LoginException is thrown.

The createIdentity method is used to create instance of the org.exoplatform.services.security.Identity object, which encapsulates all important information about single user like:

Default implementation of Authenticator is OrganizationAuthenticatorImpl, which is implementation based on OrganizationService.

You can override the default implementation of mentioned interfaces (Authenticator and RolesExtractor) if the default behavior is not suitable for your needs.

Copyright ©. All rights reserved. eXo Platform SAS
blog comments powered byDisqus