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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With