I am using Spring Security(basic authentication) + LDAP authentication which works well with embedded test ldif but not with my domain LDAP. However, I can use a LDAP browser/edit tool to search my account using the same filter(SamAccountName=napo)
#Override
public void addServiceAuthenticationManager(AuthenticationManagerBuilder authBuilder) throws Exception {
authBuilder
.ldapAuthentication()
.ldapAuthoritiesPopulator(ldapAppAuthoritiesPopulator())
.userSearchBase("OU=Users,DC=napo,DC=com")
.userSearchFilter("(SamAccountName={0})")
.contextSource()
.root("dc=napo,dc=com")
.managerDn("admin#napo.com")
.managerPassword("XXX")
.url("ldap://ldap.napo.com/OU=Users,dc=napo,dc=com");
The error message is: LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT)
The userSearchBase is relative to root. Remove DC=napo,DC=com from userSearchBase.
Related
I want to build a spring cloud infrastructure with several oauth2 resource servers supporting multiple identity provider (like google, facebook, github, ....) and also one self implemented authorization mechanism.
Oauth2 Resource Server example
Security config
#Configuration
#EnableWebSecurity
#EnableResourceServer
public class Oauth2ResourceServerConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated();
}
}
application.yml
security:
oauth2:
resource:
user-info-uri: https://api.github.com/user
As you can see this example is using github as identity provider and its working fine.
Oauth2 Authorization Server example:
Config
#Configuration
#EnableAuthorizationServer
public class Oauth2AuthorizationServerConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Override
public void init(final AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("{noop}user").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("USER", "ADMIN");
}
#Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
}
application.yml
security:
oauth2:
client:
client-id: user
client-secret: user
authorized-grant-types: password,client_credentials,authorization_code,refresh_token
scope: read,write
I can change my oauth2 resource server to use the authorization server:
security:
oauth2:
resource:
#user-info-uri: https://api.github.com/user
user-info-uri: http://${AUTH_HOST:localhost}:${AUTH_PORT:9000}/user
And it works just fine.
But what do I have to do if I now want to use both of them, github and my own authorization server?
Do I simply need a different configuration in my Oauth2 resource server to provide multiple user-info-uri or do I have to do more?
Can I extend my own authorization service to support github & co?
I would prefer not to use Auth0 and Co because I really dont like to outsource the most important part of my application: security. Even though I would like to try it. But I could not find any working example so far for auth0 + spring cloud gateway + token authentication for all underlying services.
I am trying to migrate spring security to latest version (spring security 5.2.2 and Cloud OAuth2). As #EnableOAuth2Client is in maintenance mode now, I am trying to use http.oauth2Login() with customization for success handler. Following is my security class -
#Configuration
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login().successHandler(new SimpleUrlAuthenticationSuccessHandler("<url to redirect>"));
}
}
I have registered client with name as 'custom'. Following is the flow in the browser -
http://localhost:9000/oauth2/authorization/custom -> IDP's login page and successful login -> Get Authorization code on URL http://localhost:9000/login/oauth2/code/custom -> it again goes to http://localhost:9000/oauth2/authorization/custom and infinite loop. Successhandler is not invoked. Also, I don't see access token generation in logs.
I have tried many things in last two days like tweaking security config etc but nothing works.
Any help is appreciated.
The problem was with user info endpoint. My IDP has not exposed user info endpoint while it is mandatory in spring oauth2 where the request was failing. I needed to override the default OAuth2UserService implementation to resolve the issue.
I am trying to integrate LDAP authentication for my Spring MVC app. The users are successfully able to log in, if I set the contextSource to a dummy user DN and respective password.
What I want to do is to be able to bind the ldap connection without using the dummy user.
Here's the code of what works -
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**").permitAll()
.antMatchers("/","/login**").permitAll()
.antMatchers("/home_vm","/details/**").authenticated()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/home_vm", true)
.and()
.logout()
.permitAll();
http.headers().httpStrictTransportSecurity();
}
#Configuration
#Profile({"default", "opt_ad_auth"})
protected static class ActiveDirectoryAuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {
#Value("${app.ldap.url}")
private String ldapURL;
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURL);
contextSource.setUserDn("cn=Dummy User,cn=Users,dc=somecompany,dc=com");
contextSource.setPassword("mypassword");
contextSource.setReferral("follow");
contextSource.afterPropertiesSet();
auth.ldapAuthentication()
.userSearchFilter("(sAMAccountName={0})")
.contextSource(contextSource)
;
}
}
}
Now I have tried to remove the hardcoded userDn and password (updated init())-
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchFilter("(sAMAccountName={0})")
.contextSource()
.url(ldapURL)
;
}
}
The app starts fine, but I get exception - "a successful bind must be completed on the connection".
Stacktrace -
org.springframework.security.authentication.InternalAuthenticationServiceException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1
[UPDATE] I have modified the init method to the following to more closely follow the spring tutorial(https://spring.io/guides/gs/authenticating-ldap/) -
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userDnPatterns("sAMAccountName={0}")
.contextSource().url(ldapURL)
;
}
I don't get the before-mentioned bind exception, but still not able to authenticate. Bad credentials.
You need to do this in two steps:
Bind to LDAP as an administrative user that has enough privileges to search the tree and find the user via whatever unique information you have about him.
Rebind to LDAP as the found user's DN using the supplied password.
Disconnect.
If all that succeeds, the username existed and the password was correct. If there was any failure you should treat it as a loging failure. Specifically, you should not tell the user whether it was the username not being found or the password being incorrect that was the reason for the failure: this is an information leak to an attacer.
You can authenticate with LDAP in 2 forms:
You can make a bind with the complete DN of the user (full path in the LDAP tree) and the password.
Or you can bind to LDAP as a superuser that can search on all the LDAP tree. The LDAP authenticator finds the user DN and compare the user password with the password in the user entry.
In your first code you use the second system. You need a user that can bind on the LDAP and find the user entry.
If you want user the second system, you must supply the complete DN of the user entry not the uid only.
Using Spring Security
Basic authentication setup works against some hardcoded username passwords as shown here:
http://thoughtfulsoftware.wordpress.com/2013/12/08/adding-security-to-spring-guides-rest-service/
So trying to extend it to use LDAP.
Completed the set up for LDAP authentication with our LDAP server
Now when I try to call my rest service through REST Console plug-in an authorization window keeps on popping up for username password. If I cancel it authorization fails, not sure where I am going wrong
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
#Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder
.ldapAuthentication()
.userSearchFilter("(uid={0})").userSearchBase("ou=people,dc=zzz,dc=xxxx,dc=yyy")
.groupRoleAttribute("cn").groupSearchFilter("(member={0})")
//.userDnPatterns("uid={0},ou=people")
//.groupSearchBase("ou=groups")
.contextSource().url("ldaps://ldap.xxxx.yyy:636/cn=cw-grpreader,ou=people,dc=xxx,dc=xxxx,dc=xxx")
.managerDn("cn=xx-xxr,ou=people,dc=med,dc=xxxx,dc=xxx")
.managerPassword("#$%^^");
}
This is one way I tried which give the recurring authentication popup
if I cancel the popup I get
HTTP Status 401 - [LDAP: error code 49 - NDS error: failed authentication (-669)]; error even if the credentials are correct
Link to some tutorial will be really helpful
This is due to httpbasic authentication that you have set up. Spring boot generates a random password thats shown on console which you could use.
To disable that pop-up simply add this to your application.properties file.
security.basic.enabled: false
I am pretty new to Spring Security land. I am using programmatic configuration of Spring Security with servletApi() which is pretty neat.
Here is the configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.securityContext().and()
.servletApi().and()
.authorizeUrls()
.antMatchers("/login").permitAll()
.antMatchers("/").permitAll()
.antMatchers("/**").authenticated();
}
I am using http servlet api login I am not using any filter for this.
In case a unauthorised request, ExceptionTranslationFilter uses Http403EntryForbiddenEntryPoint to return 403 forbidden status.
In my scenario:
If user does not authenticated, a 401 status code should return.
If user authenticated but not authorised, a 403 status code should return.
But default configuration creates 403 status for both case.
Here are my questions:
Why is the default entry point is Http403EntryForbiddenEntryPoint? It can be 401?
If I change Http403EntryForbiddenEntryPoint to Http401EntryForbiddenEntryPoint, does It create a problem?
Thanks