Recently at work, I had to work on setting up a Spring application to do Active Directory authentication and use our internal permissions service. After much googling and playing around I finally figured out how to get it all working. I suspect this may not be the best way to do this, but it works.
Set this up in your config XML
1
2
3
4
5
6
7
8
9
10
| <!-- Connect to AD -->
<bean id="activeDirectoryAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor -arg value="YOURDOMAIN"></constructor>
<constructor -arg value="ldap://YOURSERVER"></constructor>
<property name="userDetailsContextMapper" ref="customDetailsMapper"></property>
<property name="convertSubErrorCodesToExceptions" value="true"></property>
</bean>
<!-- add in your permissions -->
<bean id="customDetailsMapper" class="Full path to CustomDetailsMapper class"></bean> |
<!-- Connect to AD -->
<bean id="activeDirectoryAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor -arg value="YOURDOMAIN"></constructor>
<constructor -arg value="ldap://YOURSERVER"></constructor>
<property name="userDetailsContextMapper" ref="customDetailsMapper"></property>
<property name="convertSubErrorCodesToExceptions" value="true"></property>
</bean>
<!-- add in your permissions -->
<bean id="customDetailsMapper" class="Full path to CustomDetailsMapper class"></bean>
Now, the CustomDetailsMapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| package mypackage;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
public class CustomUserDetailsMapper extends LdapUserDetailsMapper {
protected static Logger logger = Logger.getLogger("CustomUserDetailsMapper");
private static final Collection<string> DEFAULT_PERMS = Arrays.asList("login");
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection< ? extends GrantedAuthority> authorities) {
/**
* at this point, the user has permissions based on groups in LDAP/AD. If
* we used AD for permissions, this would be sufficient, but we want permissions
* from elsewhere so we need to modify the permissions/authorities
*/
logger.info(" old authorities: "+authorities);
UserDetails user = super.mapUserFromContext( ctx, username, getPermissions(username));
logger.info(" adjusted user: "+user);
return user;
}
/**
* gets permissions
*
* @param username the username to get permissions for
* @return a Set of permissions for the user
*/
private Set<grantedauthority> getPermissions(String username) {
Set</grantedauthority><grantedauthority> permissions = new HashSet</grantedauthority><grantedauthority>();
/**
* get your permissions here - however you need to
* then convert them to SimpleGrantedAuthority
*/
for (String perm : permissionsFromOtherSource) {
permissions.add(new SimpleGrantedAuthority(perm));
}
return permissions;
}
}
</grantedauthority></string> |
package mypackage;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
public class CustomUserDetailsMapper extends LdapUserDetailsMapper {
protected static Logger logger = Logger.getLogger("CustomUserDetailsMapper");
private static final Collection<string> DEFAULT_PERMS = Arrays.asList("login");
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection< ? extends GrantedAuthority> authorities) {
/**
* at this point, the user has permissions based on groups in LDAP/AD. If
* we used AD for permissions, this would be sufficient, but we want permissions
* from elsewhere so we need to modify the permissions/authorities
*/
logger.info(" old authorities: "+authorities);
UserDetails user = super.mapUserFromContext( ctx, username, getPermissions(username));
logger.info(" adjusted user: "+user);
return user;
}
/**
* gets permissions
*
* @param username the username to get permissions for
* @return a Set of permissions for the user
*/
private Set<grantedauthority> getPermissions(String username) {
Set</grantedauthority><grantedauthority> permissions = new HashSet</grantedauthority><grantedauthority>();
/**
* get your permissions here - however you need to
* then convert them to SimpleGrantedAuthority
*/
for (String perm : permissionsFromOtherSource) {
permissions.add(new SimpleGrantedAuthority(perm));
}
return permissions;
}
}
</grantedauthority></string>
NOTE: the blog’s java code formatter is messing this code up a bit (specifically the GrantedAuthority parts), but you should be able to get the gist of it. Basically, after the user is filled out from AD, we get a handle to it and we change the permissions on it.