1

I followed this article and configured my application to authenticate via LDAP (that's working perfectly). Now I'm using in application just 3 roles and I would like to create mapping for them.

So I implemented interface GrantedAuthoritiesMapper

@Component
public class MyAuthorityMapper implements GrantedAuthoritiesMapper {

    @Autowired
    private MyAuthorityConfig authoritiesConfig;

    @Override
    public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> collection) {
        Set<MyAuthority> roles = EnumSet.noneOf(MyAuthority.class);

        for (GrantedAuthority g : collection) {
            for (String role : authoritiesConfig.getAuthoritiesMap().keySet()) {
                if (Arrays.asList(authoritiesConfig.getAuthoritiesMap().get(role).split(",")).contains(g.getAuthority())) {
                    roles.add(MyAuthority.valueOf(role));
                }
            }
        }
        return roles;
    }
}

Here is role populator

@Component
@ConfigurationProperties(prefix = "auth.role.mapping")
public class MyAuthorityConfig {

    private Map<String, String> authroritiesMap = new HashMap<String, String>();

    public Map<String, String> getAuthoritiesMap() {
        return this.authroritiesMap;
    }
}

and application-dev.properties

auth.role.mapping.ROLE_COMPETENCE_CENTER=ROLECC
auth.role.mapping.ROLE_OPERATIONS=ROLEOPS,ROLEPAR
auth.role.mapping.ROLE_ADMINISTRATOR=ROLEADM,ROLESUPUSR

Now MyAuhtorityConfig contains only empty map. Is it possible to use @ConfigurationProperties like I'm using it here? I can't find how to populate map with it. Or is there issue with profile specific properties file?

In WebSecurityConfig I have method for LDAP config but I don't know how/where to inject MyAuthorityMapper or if it's even possible without using ActiveDirectoryLdapAuthenticationProvider

private void configureLdap(AuthenticationManagerBuilder auth) throws Exception {
        DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(env.getProperty("auth.ldap.urls"));
        contextSource.setUserDn(env.getProperty("auth.ldap.user"));
        contextSource.setPassword(env.getProperty("auth.ldap.password"));
        contextSource.setReferral("follow");
        contextSource.afterPropertiesSet();

        auth.ldapAuthentication()
                .userSearchBase(env.getProperty("auth.ldap.user.search.base"))
                .userSearchFilter(env.getProperty("auth.ldap.user.search.filter"))
                .groupSearchBase(env.getProperty("auth.ldap.group.search.base"))
                .groupSearchFilter(env.getProperty("auth.ldap.group.search.filter"))
                .groupRoleAttribute(env.getProperty("auth.ldap.group.search.attribute"))
                .contextSource(contextSource)
                ;
    }
Community
  • 1
  • 1
bilak
  • 4,526
  • 3
  • 35
  • 75

1 Answers1

0

Ok so for first issue with @ConfigurationProperties there is fix like this:

@Component
@ConfigurationProperties(prefix = "auth.role")
public class MyAuthorityConfig {

    private Map<String, String> mapping = new HashMap<String, String>();

    public Map<String, String> getMapping() {
        return this.mapping;
    }
}

@ConfigurationProperties look for prefix auth.role in properties and then get the mapping part which should be the name of property in my class.

For second issue I found solution with UserDetailsContextMapper

@Component(value = "myUserDetailsContextMapper")
public class MyUserDetailsContextMapper implements UserDetailsContextMapper {

    private static final Logger log = LoggerFactory.getLogger(MyUserDetailsContextMapper.class);

    @Autowired
    private MyAuthorityConfig authoritiesConfig;

    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
        log.debug("mapUserFromContext start");
        List<GrantedAuthority> mappedAuthorities = new ArrayList<>();

        for (GrantedAuthority g : authorities) {
            for (String role : authoritiesConfig.getMapping().keySet()) {
                if (Arrays.asList(authoritiesConfig.getMapping().get(role).split(","))
                        .contains(g.getAuthority().startsWith("ROLE_") ? g.getAuthority().substring("ROLE_".length()) : g.getAuthority())) {
                    log.debug("Mapping from LDAP role {} to application role {} for user {}", g.getAuthority(), role, username);
                    mappedAuthorities.add(MyAuthority.valueOf(role));
                }
            }
        }

        return new User(username, "", mappedAuthorities);
    }

    @Override
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {

    }
}

I'm not sure if returning just new User(username, "", mappedAuthorities); is ok (I must test it properly with locked/disabled users) but for now it works.

bilak
  • 4,526
  • 3
  • 35
  • 75