I'm trying to learn spring and create a web site where the authentication will be down via login page with angular passed to spring which needs to use ldap to authenticate. I figured I'd start on Spring site and walk through there guide but it seems to use deprecated code and it has an error.
I've been through several stackoverflow topics and google search but I'm not finding what I need.
src/main/java/hello/WebSecurityConfig.java
package hello;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#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("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
}
The problem is ".passwordEncoder(new LdapShaPasswordEncoder()) .passwordAttribute("userPassword")" LdapShaPasswordEncoder is deprecated and so it either what .passwordEncoder takes or the PasswordEncoder being returned by LdapShaPasswordEncoder. I have tried the BCrypt example I found on stack using BCryptPasswordEncoder but I still get an error from .passwordEncoder that it's not the correct PasswordEncoder org.springframework.security.authentication.encoding.PasswordEncoder vs org.springframework.security.crypto.password.PasswordEncoder
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("userPassword");
}
Related
I am using spring security to try and authenticate (and eventually authorize) using a client certificate. I already got it to authenticate using httpBasic.
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/status", "/configure")
.access("hasRole('ADMIN')")
.antMatchers(HttpMethod.GET, "/**")
.permitAll()
.anyRequest()
.denyAll()
.and().x509()
.x509AuthenticationFilter(new AuthenticationFilter())
// .and().httpBasic()
.and()
.csrf().disable()
;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("dashboard.xxxx.yyy.zzz")
.password("{noop}password").roles("ADMIN");
}
}
I added a custom authentication filter so that I could toss in some logging, and both methods are returning null.
import java.security.cert.X509Certificate;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
public class AuthenticationFilter extends X509AuthenticationFilter {
private static Logger LOG = LogManager.getLogger(AuthenticationFilter.class);
public Object getPreAuthenticatedCredentials(HttpServletRequest request) {
LOG.info("" + super.getPreAuthenticatedCredentials(request));
return super.getPreAuthenticatedCredentials(request);
}
public Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
LOG.info("" + super.getPreAuthenticatedPrincipal(request));
return super.getPreAuthenticatedPrincipal(request);
}
}
Here is my tomcat server.xml connector.
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="/opt/tomcat9/conf/dashboard.p12"
keystorePass="************" clientAuth="false"
sslProtocol="TLS" alias="dashboard"
sslEnabledProtocols="TLSv1.2"/>
Any ideas what I might be missing, or just doing incorrectly?
I am sending the client certificate via curl using --key and --cert. The --trace - option shows no errors.
Completely unrelated to Spring security.
The solution was to configure the server.xml to ask for the certificate.
<SSLHostConfig protocols="TLSv1.2" certificateVerification="required">
I have this HTTP config and some restful API to test login and register in the database but it always got "Unauthorized". But I disabled it? Why? pls, help.
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.anonymous().authorities("ROLE_ANONYMOUS")
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/**").permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/**");
}
}
I added this #SpringBootApplication(exclude = {SecurityAutoConfiguration.class }) to main void then the issue resolve.
I've been given the following LDAP configuration I need to use for authentication. How does this translate into Java code?
ext ldap over SSL
ext.secure.adapter.ConnectionURL=ldap://ext_host:999
encrypted.ext.secure.adapter.UserName=CN=Administrator,CN=Users,DC=ext-pre,DC=corp-pre,DC=com
encrypted.ext.secure.adapter.Password=HelloWorld1
corp ldap over SSL
corp.secure.adapter.ConnectionURL=ldap://corp_host:888
encrypted.corp.secure.adapter.UserName=CN=Administrator,CN=Users,DC=corp-pre,DC=com
encrypted.corp.secure.adapter.Password=HelloWorld1
Does the below code look right?
package com.company.boot;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Configuration
protected static class AuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://ext_host:999/CN=Administrator,CN=Users,DC=ext-pre,DC=corp-pre,DC=com");
}
}
}
The above code only accommodates one ConnectionURL. How do I included the other ConnectionURL?
Just add it twice with different URL's. First it will authenticate against ldap://ext_host:999and on not finding will check in ldap://corp_host:888
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://ext_host:999/CN=Administrator,CN=Users,DC=ext-pre,DC=corp-pre,DC=com");
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://corp_host:888/CN=Administrator,CN=Users,DC=corp-pre,DC=com");
}
We would like to apply Oauth2 based security for the Rest Controllers while the rest of the application will have Spring Security. Will that be possible? Can you provide any examples please?
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
Thank you in advance.
Yes it's possible. Here the example template configuration code is given. Please change the required configs to your need. The key is to define Sub static classes of configuration with different order. Here i have considered any requests which is orginating from \api as a REST API call.
I have not checked the code by compiling it.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Order(1)
#Configuration
public static class ApiWebSecurityConfig extends OAuth2ServerConfigurerAdapter{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the OAuth
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.apply(new OAuth2ServerConfigurer())
.tokenStore(new InMemoryTokenStore())
.resourceId(applicationName);
}
}
}
#Order(2)
#Configuration
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the Normal authentication
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //HTTP with Disable CSRF
.authorizeRequests() //Authorize Request Configuration
.anyRequest().authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login").permitAll()
.and() //Logout Form configuration
.logout().permitAll();
}
}
}
My current java security config looks as follows:
#Configuration
#EnableWebSecurity
public class RootConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("tester").password("passwd").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
When I perform a GET request using a browser, I'll get an error 403.
I would expect to get a browser popup asking me for a username / password.
What might be the problem?
UPDATE: This is fixed in Spring Security 3.2.0.RC1+
This is a bug in the Security Java Configuration that will be resolved for the next release. I have created SEC-2198 to track it. For now, a work around is to use something like the following:
#Bean
public BasicAuthenticationEntryPoint entryPoint() {
BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
basicAuthEntryPoint.setRealmName("My Realm");
return basicAuthEntryPoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(entryPoint())
.and()
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
PS: Thanks for giving Spring Security Java Configuration a try! Keep the feedback up :)
With Spring Security 4.2.3 and probably before you can simply use this configuration:
#Configuration
#EnableWebSecurity
public class CommonWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Autowired
public void dlcmlUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("tom").password("111").roles("USER");
}
}