Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring LdapAuthentication and Load roles from local database

I have Spring Security configured to authenticate against LDAP server.

<security:authentication-manager >
    <security:ldap-authentication-provider user-dn-pattern="uid={0}" />

</security:authentication-manager>

After authentication I want to load roles from local database for the same user. How can I load local database roles using "ldap-authentication-provider"?

If I add the second authentication provider as below:

<security:authentication-manager >
    <security:ldap-authentication-provider user-dn-pattern="uid={0}" />
            <security:authentication-provider ref="daoAuthenticationProvider" />
</security:authentication-manager>

daoAuthenticationProvider added, but Spring does not use the second provider when first auth provider authenticates the user. Only if the first auth provider fails to authenticate it goes next in the list.

So basically look like we have to customize

<security:ldap-authentication-provider user-dn-pattern="uid={0}" />

to load ROLEs from local database.

Any suggestions? How should this be implemented?

like image 479
user2072797 Avatar asked May 09 '13 19:05

user2072797


1 Answers

An authentication provider must deliver a fully populated authentication token on successfull authentication, so it's not possible to use one provider to check the user's credentials, and another one to assign authorities (roles) to it.

You can however customize an ldap auth provider to fetch user roles from database instead of the default behaviour (searching for the user's groups in ldap). The LdapAuthenticationProvider has two strategies injected: one that performs the authentication itself (LdapAuthenticator), and another one that fetches the user's authorities (LdapAuthoritiesPopulator). You can achieve your requirements if you supply an LdapAuthoritiesPopulator implementation that loads roles from database. In case you already have a UserDetailsService working against the database, you can easily integrate that by wrapping it in a UserDetailsServiceLdapAuthoritiesPopulator and injecting it in the LdapAuthenticationProvider.

Since this configuration is rather uncommon, the security xml namespace doesn't provide tags/attributes to set it up, but the raw bean config isn't too complicated. Here is the outline:

1) I suppose you have an ldap-server somewhere in your config. It's important to assign and id to it, which will allow us to reference it later.

<security:ldap-server url="..." id="ldapServer" .../>

2) From the authentication-manager section, you will only refer to the customized provider:

<security:authentication-manager>
    <security:authentication-provider ref="customLdapAuthProvider"/>
</security:authentication-manager>

3) Now, the essential part:

<bean id="customLdapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg name="authenticator">
        <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <constructor-arg name="contextSource" ref="ldapServer"/>
            <property name="userDnPatterns">
                <list>
                    <value>uid={0}</value>
                </list>
            </property>
        </bean>
    </constructor-arg>
    <constructor-arg name="authoritiesPopulator">
        <bean class="org.springframework.security.ldap.authentication.UserDetailsServiceLdapAuthoritiesPopulator">
            <constructor-arg name="userService" ref="userService"/>
        </bean>
    </constructor-arg>
</bean>

The authenticator is basically the same as the one that would be created by the namespace config. (Note the contextSource attribute referencing the ldap server.)

The authoritiesPopulator is a simple wrapper around your userService implementation which is supposed to be defined somewhere in your config.

like image 79
zagyi Avatar answered Oct 23 '22 12:10

zagyi