oli-ver oli-ver - 3 months ago 42
Apache Configuration Question

How can I search for ldap fields when using ActiveDirectoryRealm in Apache Shiro?

We use Apache Shiro to authenticate and authorize users using our active directory.

Authenticating the user and mapping groups works just fine using the following config:

adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.searchBase = "OU=MYORGANIZATION,DC=MYDOMAIN,DC=COM"
adRealm.groupRolesMap = "CN=SOMEREADGROUP":"read","CN=SOMEMODIFYGROUP":"modify","CN=SOMEADMINGROUP":"admin"
adRealm.url = ldaps://my.ad.url:636
adRealm.systemUsername= systemuser
adRealm.systemPassword= secret
adRealm.principalSuffix= @myorganization.mydomain.com


I can authenticate in Shiro using the following lines:

String user = "someuser";
String password = "somepassword";
Subject currentUser = SecurityUtils.getSubject ();
if (!currentUser.isAuthenticated ()){
UsernamePasswordToken token = new UsernamePasswordToken (user,
password);
token.setRememberMe (true);
currentUser.login (token);
}


We now want to get more user information from our ActiveDirectory. How can I do that using Apache Shiro? I was not able to find anything about it in the documentation.

In the source code of ActiveDirectoryRealm I found this line:

NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchCtls);


So the first part of the answer is clear: use the ldapContext to search something in it. But how can I retrieve the LdapContext?

Answer

It depends on what you are trying to do. Are you just trying to reuse the context to run a query for something other then authentication or authorization? Or are you trying to change the behavior of the query in the AD realm?

If the latter, you would need to extend the ActiveDirectoryRealm and override the queryForAuthorizationInfo() method.

Are you implementing something that is custom for your environment?

(updated)

A couple things: The realm has access to the LdapContext in the two touch points: queryForAuthenticationInfo() and queryForAuthorizationInfo(), so if you extend the AD realm or AbstractLdapRealm you should already have it. You could change the query to return other info and add the extra info to your Principal. Then you have access to that info directly from your Subject object.

Your realms, are not required to be singletons.

If you want to do some other sort of user management (email all users with a given role, create a user, etc). Then you could create a LdapContextFactory in your shiro.ini, and use the same instance for multiple objects.

[main]
...
ldapContextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory
ldapContextFactory.systemUsername = foobar
ldapContextFactory.systemPassword = barfoo

adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.ldapContextFactory = $ldapContextFactory
...

myObject = com.biz.myco.MyObject
myObject.ldapContextFactory = $ldapContextFactory

This would work well if myObject is interacting with other Shiro components, (responding to events, etc), but less so if you need access to it from another framework. You could work around this by some sort of static initialization that builds creates the ldapContextFactory, but in my opinion, this is where the sweet spot of using the shiro.ini ends, and where using Guice or Spring shines.

Comments