Stacking Login Modules


Sometimes no single login module meets your exact needs. Let's consider the case of using an external LDAP sever to provide user information. You would really consider this approach only if you needed to integrate with an existing LDAP-based user repository. But think about it for a second. Users and passwords map easily from a typical LDAP server, but how likely is it that the group and role information in an LDAP server will match up with the specific roles needed by your application? That rarely happens. To make matters worse, you might not be in control of the external LDAP server. It can be politically difficult to get your application-specific entries into the server.

That's not always the case, but it is certainly not uncommon to want to mix and match login modules. The case we just mentioned is a perfect example. You might have a user repository that lacks good role information. In that case, it would be nice to combine the LDAP login module validating users with the database login module providing role information.

How do I do that?

JBoss allows you to specify multiple login modules for a single security domain. It's like almost every other pluggable authentication system in that regard. The question is how the login modules interact. They can act cooperatively to authenticate the user, or they can work independently.

If you have multiple authentication repositories, you will want the authentication modules to work independently. Even if you have a companywide LDAP repository containing your users, you may need additional administrative user accounts that are specific to your application but that don't belong in your primary repository. A user would be in one repository or the other, and login should succeed if the user is found in either repository.

The following configuration accomplishes exactly that:

     <application-policy name="todo">         <authentication>             <login-module code="org.jboss.security.auth.spi.LdapLoginModule"                           flag="sufficient">                 <module-option name="java.naming.factory.initial">                     com.sun.jndi.ldap.LdapCtxFactory </module-option>                 <module-option name="java.naming.provider.url">                     ldap://localhost/                 </module-option>                 <module-option name="java.naming.security.authentication">                     simple                 </module-option>                 <module-option name="principalDNPrefix">uid= </module-option>                 <module-option name="principalDNSuffix">                     ,ou=People,o=jbossnotebook                 </module-option>                 <module-option name="rolesCtxDN">                     ou=Roles,o=jbossnotebook                 </module-option>                 <module-option name="uidAttributeID"> member </module-option>                 <module-option name="matchOnUserDN">true</module-option>                 <module-option name="roleAttributeID">cn</module-option>                 <module-option name="roleAttributeIsDN">false</module-option>             </login-module>             <login-module                code="org.jboss.security.auth.spi.DatabaseServerLoginModule"                flag="sufficient">                 <module-option name="dsJndiName">java:/DefaultDS</module-option>                 <module-option name="principalsQuery">                     select passwd from USERS where login=?                 </module-option>                 <module-option name="rolesQuery">                     select role, 'Roles' from USER_ROLES where login=?                 </module-option>             </login-module>         </authentication>     </application-policy> 

Because we marked each module as sufficient, JBoss requires only one of the modules to succeed. If we left the modules marked required, JBoss would have required both modules to succeed, which would happen only if the user were in both repositories.

But what if the two repositories aren't independent? Going back to the original premise of having users in an LDAP server supplemented by application-specific roles in a relational database, simple module stacking doesn't solve the problem on its own. For that, you need to use password stacking.

Password stacking allows modules to skip the actual authentication and to provide supplemental roles, only if an earlier module has already authenticated the user. The modules require the password-stacking option to useFirstPass for this to work.

Here is an example:

     <application-policy name="todo">         <authentication>             <login-module code="org.jboss.security.auth.spi.LdapLoginModule"                           flag="required">                 <module-option name="password-stacking">                    useFirstPass</module-option>                 <module-option name="java.naming.factory.initial">                     com.sun.jndi.ldap.LdapCtxFactory </module-option>                 <module-option name="java.naming.provider.url">                     ldap://localhost/                 </module-option>                 <module-option name="java.naming.security.authentication">                     simple                 </module-option>                 <module-option name="principalDNPrefix">                     uid=                 </module-option>                 <module-option name="principalDNSuffix">                     ,ou=People,o=jbossnotebook                 </module-option>             </login-module>             <login-module                code="org.jboss.security.auth.spi.DatabaseServerLoginModule"                flag="required">                 <module-option                    name="password-stacking">useFirstPass</module-option>                 <module-option name="dsJndiName">java:/DefaultDS</module-option>                 <module-option name="rolesQuery">                     select role, 'Roles' from USER_ROLES where login=?                 </module-option>             </login-module>         </authentication>     </application-policy> 

Both the LDAP login module and the database login module are marked required, and both have the password-stacking option set. Notice that the LDAP configuration omits the roles query information and the database server module omits the principals query. It is better to provide fallback queries even when they aren't used, but it isn't required.

What just happened?

You combined login modules to create more interesting authentication policies for your server. You can stack login modules to aggregate independent user repositories, or you can combine user repositories that provide partial information to create a complete policy for your application. The ability to combine login modules makes security configuration much more flexible.



JBoss. A Developer's Notebook
JBoss: A Developers Notebook
ISBN: 0596100078
EAN: 2147483647
Year: 2003
Pages: 106

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net