So this is my first time working with Spring so bear with me!
I am pretty sure the problem is that my set-up for DnPatterns and the group search base is incorrect.
There is an external AD I am trying to hook up to. Using ad explorer I've found an entry, below is the dn of the user and then the login in id they usually use to logIn
As listend in the profile of the user in the AD Explorer View
DN -> CN=LastName\, FirstName, OU=Users,OU=Calgary,DC=CORP,DC=DEPARTMENT,DC=com
Username & password User will provide on login:
UserName -> LastFirst5
Password -> Password
The path to reach the user info in the Directory Explorer is as shown
DC=CORP,DC=DEPARTMENT,DC=com -> OU=Calgary -> OU=Users -> CN=LastName,FirstName
This is my config set-up:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("DC=corp,DC=department,DC=com")
.groupSearchBase("OU=Users,OU=Calgary,DC=CORP,DC=Department,DC=com")
.contextSource()
.url("ldap://corp.Ad.com/")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
First the context source url should include the base DN for searching and/or authenticating users.
.contextSource()
.url('ldap://corp.Ad.com:389/DC=CORP,DC=DEPARTMENT,DC=com')
userDnPatterns()
is used to match the login name of a user as it appears in the RDN of your user entries - if it appears ! - the server then substitutes the login name entered by the user for the {0} placeholder, and from that recreates the user dn by appending the base dn from the LDAP url. The problem is that in your directory, a user dn is not built from its username but from its cn
attribute that is different so you can't have a match (LastName, FirstName ≠ LastFirst5
), hence you can't authenticate users with this method (but a correct pattern would look like cn={0},ou=Users
if username and cn were equivalent).
userSearchFilter()
on the other hand can be used to match the login name provided by the user using a regular search filter. Optionally userSearchBase()
can be used with it to set an optional branch rdn where user entries are located and from which to perform the search, if not specified the search includes your entire directory starting from the base dn of the LDAP url.
.and()
.userSearchBase('ou=Users,ou=Calgary')
.userSearchFilter('(sAMAccountName={0})')
Note that if you have users in other cities like OU=Users,OU=OtherCity,DC=...
, you will need another configuration in order to authenticate them without knowing from which city to start the search. In this case you would reset the search base to match all entries under the base dn and, since you only want users to be able to login, you would refine the filter
accordingly :
.and()
.userSearchBase('')
.userSearchFilter('(&(sAMAccountName={0})(objectClass=user)')
You don't need groupSearchBase()
without groupSearchFilter()
, and these 2 are needed only for authorization (to verify the user has a given role <=> is member of a given group).
To be able to search & match a user entry, the authentication request itself needs to connect and bind to the LDAP server, most servers don't accept anonymous bindings so you may need to set managerDn() and managerPassword() :
.contextSource()
.url('ldap://corp.Ad.com:389/DC=CORP,DC=DEPARTMENT,DC=com')
.managerDn('admin')
.managerPassword('password')
https://community.jaspersoft.com/documentation/jasperreports-server-authentication-cookbook/performing-ldap-user-search