LdapLoginModule for web app auth
stevemaring Sep 23, 2011 10:34 AMI'm having trouble getting my web-app to authenticate properly with my security-domain in JBoss AS 6.1.0.Final.
My web.xml is configured for:
{code:xml}
<security-constraint>
<web-resource-collection>
<web-resource-name>Everything</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<!-- need to be an ActiveDirectory "memberOf" one of these ... -->
<role-name>Development</role-name>
<role-name>Helpdesk</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>My Realm</realm-name>
</login-config>
<security-role>
<role-name>Development</role-name>
</security-role>
<security-role>
<role-name>Helpdesk</role-name>
</security-role>
{code}
and my jboss-web.xml has:
{code:xml}
<jboss-web>
<context-root>/myApp</context-root>
<security-domain>java:/jaas/XADSRealm</security-domain>
</jboss-web>
{code}
JNDIView in the jmx-console has confirm existence of that name under the "java: Namespace":
+- jaas (class: javax.naming.Context)
| +- XADSRealm (class: org.jboss.security.plugins.SecurityDomainContext)
The security domain is configured in my login-config.xml like this:
{code:xml}
<application-policy name="XADSRealm" extends="other">
<authentication>
<login-module code="org.jboss.security.ClientLoginModule" flag="required" >
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required" >
<module-option name="java.naming.provider.url">ldap://10.175.3.200:389/</module-option>
<module-option name="rolesCtxDN">DC=sample,DC=com</module-option>
<module-option name="matchOnUserDN">false</module-option>
<module-option name="principalDNPrefix">sAMAccountName=</module-option>
<module-option name="principalDNSuffix">,DC=sample,DC=com</module-option>
<module-option name="uidAttributeID">sAMAccountName</module-option>
<module-option name="roleAttributeID">memberOf</module-option>
<module-option name="roleAttributeIsDN">true</module-option>
<module-option name="roleNameAttributeID">name</module-option>
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
<login-module
code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
<module-option name="userName">username</module-option>
<module-option name="password">574e4454d95c79174f1f41ab21df8598de921bc</module-option>
<module-option name="managedConnectionFactoryName">jboss.jca:service=XATxCM,name=myXADS</module-option>
</login-module>
</authentication>
</application-policy>
{code}
However, whenever I start the web app and try to log in, my server says:
ERROR [org.jboss.security.auth.spi.UsersRolesLoginModule] Failed to load users/passwords/role files: java.io.IOException: No properties file: users.properties or defaults: defaultUsers.properties found
Which is the sort of thing I would expect to see if no authenticating login module was present, and it was trying to use the default.
I've been doing a great deal of RTFMing, but I haven't been able to figure out what I'm missing. I have TRACE enabled for security, but it is not telling me anything interesting.
In the larger scheme of things, I want the LdapLoginModule to handle the authentication and roles for the web app, and for the principal to be available in ThreadLocal when a DB connection is pulled out of the pool for a requesting EJB.
In my xa-datasource, I have defined a valid-connection-checker-class-name which overrides org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker like this:
{code}
@Override
public SQLException isValidConnection(Connection conn) {
super.isValidConnection(conn);
Principal currentPrincipal = null;
try {
currentPrincipal = SecurityAssociation.getPrincipal();
} catch (SecurityException se) {
log.error("policy does not seem to have RuntimePermission(\"org.jboss.security.SecurityAssociation.getPrincipalInfo\")",se);
return new SQLException("policy does not seem to have RuntimePermission(\"org.jboss.security.SecurityAssociation.getPrincipalInfo\")",se);
}
if (currentPrincipal == null) {
log.error("Principal info not found in ThreadLocal");
return new SQLException("Principal info not found in ThreadLocal");
}
String clientId = currentPrincipal.getName();
OracleConnection oracleConnection = (OracleConnection) conn;
String metrics[] = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = clientId;
try {
oracleConnection.setEndToEndMetrics(metrics, (short) 0);
} catch (SQLException se) {
log.error("unable to set clientId " + clientId + " on Oracle connection",se);
return new SQLException("unable to set clientId " + clientId + " on Oracle connection",se);
}
return null;
}
{code}
So, I need the principal, as authenticated via the LdapLoginModule, to be available when an EJB asks for a connection from the pool. The purpose here is for auditing, so that we know exactly who used the GUI to change data in the database.
-Steve Maring
Tampa, FL