TL;DR: Why does the LDAPLoginModule (apparently) not throw a FailedLoginException
when a user fails to be authenticated?
I have overridden the default "karaf" jaas realm in jboss fuse 6.2.[0|1]. My configuration has 2 modules:
org.apache.karaf.jaas.modules.ldap.LDAPLoginModule
to authenticate the user via an LDAP-to-Active-Directory linkMyCustomLoginModule extends AbstractKarafLoginModule
- a second module to check for locally-defined roles for an authentic user.The latter works fine. However, when the LDAPLoginModule fails to authenticate a user, they are still allowed to pass. This is the case no matter what combination of required/requisite and ordering I use for the 2 modules.
An example of the behavior:
I define my modules like:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd" >
. . .
<jaas:config . . . >
. . .
<jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule"
flags="requisite">
. . .
properties herein as commonly seen for ldap-ad
. . .
</jaas:module>
<jaas:module className="com.abc.xyz.MyCustomLoginModule"
flags="requisite">
. . . nothing shocking in here either . . .
</jaas:module>
</jaas:config>
</blueprint>
This blueprint file and the MyCustomLoginModule are within a bundle that has been added to a feature that, itself, has been added to the etc/org.apache.karaf.features.cfg
along with the associated remote mvn repo
"userX=admin"
into the flat-file that MyCustomLoginModule uses to assign roles.Logged output is like:
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Get the user DN.
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Bind user (authentication).
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Setting up SSL
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Set the security principal for CN=...
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Binding the user.
WARN | LDAPLoginModule | org.apache.karaf.jaas.modules | User userX authentication failed.
javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr:
DSID-0C0903D9, comment: AcceptSecurityContext error, data 52e, v2580]
^^ as expected, LDAP Authentication fails--as per the WARN message and the "52e" error code ^^
Alternatively, I can define a user=role mapping in my custom, local file, where the user does not even exist in our Active Directory.... something simple, like: admin=admin
. I then go through the same process. This time the LDAP module throws no Exceptions, but logs:
WARN | LDAPLoginModule | org.apache.karaf.jaas.modules | User admin not found in LDAP.
but yet again, execution continues and I am successfully logged into the hawtio web console, this time as "admin."
Lastly... Using a valid Active Directory user, but not one defined in my custom, local file, produces expected logging like:
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Get the user DN.
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Setting up SSL
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Looking for the user in LDAP with
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | base DN:XXXXXXXXXX
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | filter: (&(|(samAccountName=<valid-username>)(userPrincipalName=<valid-username>)(cn=<valid-username>))(objectClass=user))
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Found the user DN.
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Bind user (authentication).
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Setting up SSL
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Set the security principal for CN=<valid-username>,...
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Binding the user.
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | User <valid-username> successfully bound.
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Setting up SSL
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | Looking for the user roles in LDAP with
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | base DN:XXXXXXXX
DEBUG | LDAPLoginModule | org.apache.karaf.jaas.modules | filter: (uniqueMember=CN=<valid-username>)
WARN | Authenticator | io.hawt.hawtio-web | Login failed due User <valid-username> has no local roles defined
where that last line is because my module throws a FailedLoginException
if the user has no roles defined in the aforementioned custom file
I also noted that if the LDAPLoginModule's configuration is bad--e.g., a bad password is given for the system account that searches ldap for the user--then it DOES halt the login process, by throwing a FailedLoginExcpetion like:
WARN | Authenticator | io.hawt.hawtio-web | Login failed due Can't connect to
the LDAP server: [LDAP: error code 49 - 80090308: LdapErr:
DSID-0C0903D9, comment: AcceptSecurityContext error, data 52e, v2580]
note that this is logged by the Authenticator (not the LDAPLoginModule as above
...so at length, the question is -- why does the LDAPLoginModule (apparently) not throw a FailedLoginException
when a user fails to be authenticated? I'd think that this is what's needed--does anyone disagree? Is there some additional bit of configuration that the LDAPLoginModule needs in order to be effective?
Has anyone else had this issue with JBoss FUSE v6.2.1 or karaf v2.4? Were you able to resolve within that version? If not, was it resolved by up-leveling to a newer version of either?
Thanks, Hans
Though not an exact answer to the question asked, the following is an effective workaround.
Instead of using LDAPLoginModule directly, create a class that extends it and @Override the login() method--which returns a boolean... This boolean is set to false if the user being searched for does not exist, or has provided an incorrect password. Thus, simply call super.login() and if the result is false, then throw a FailedLoginException.