I'm brand new to spring and I'm trying to figure out how to authenticate a user.
Currently, it looks like everything is set up correctly. When I use x-www-form-urlencoded, I can successfully log in. When using application/json, my application does not receive the emailAddress parameter.
I have been googling and checking SO, but I can't find anything related.
Here is my SecurityConfig.
package com.myapp.config;
import com.myapp.security.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.web.bind.annotation.RestController;
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("customUserDetailsService")
private UserDetailsService userDetailsService;
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
public void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
builder.authenticationProvider(this.authenticationProvider());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/").authenticated()
.and()
.formLogin().loginPage("/login").usernameParameter("emailAddress").passwordParameter("password")
.successHandler(new SimpleUrlAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout();
}
}
formLogin().loginPage("/login").usernameParameter("emailAddress").passwordParameter("password")
.successHandler(new SimpleUrlAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
In the above configure, a standard UsernamePasswordAuthenticationFilter is used to obtain username and password from request parameter. However, the standard filter do not parse parameters from your json string in the request.
You may try to create a custom UsernamePasswordAuthenticationFilter to obtain username and password from the your json string and apply your custom filter in configuration. However, unlike XML configuration that can use <custom-filter position="FORM_LOGIN_FILTER" ref="yourCustomFilter" />, you cannot replace the form login filter with your custom filter by Java Config.
As a workaround, you can try with follows:
Create a custom filter extends AbstractAuthenticationProcessingFilter to obtain the username and password from json string and put the parsed parameters into the request. The solution is to use HttpRequestWrapper class, which allow you to wrap one request with another. You can subclass that, and override the getParameter to return username and password which is parsed from json string. You can then pass the wrapped request to chain.doFilter.
Add the custom filter before the standard UsernamePasswordAuthenticationFilter with HttpSecurity#addFilterBefore(yourCustomFilter, UsernamePasswordAuthenticationFilter.class)
As the username and password is parsed from json string to the request parameter, the standard UsernamePasswordAuthenticationFilter should be able to perform authentication.
Related
I've tried to set the username and the password in the properties but didnt work
I'm trying to create a login and registration web app and I am stuck at this now
I was implementing the old way but it is deprecated so I saw this way, it is working but I cannot find a way to log in
package com.sample.security.config;
import com.sample.services.UserService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#AllArgsConstructor
#EnableWebSecurity
public class WebSecurityConfig {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider())
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/api/v*/registration**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin();
return http.build();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder);
return authProvider;
}
}
The DaoAuthenticationProvider in your example is the default, and so does not need to be published as a #Bean or configured manually as you have done with .authenticationProvider(...). If you want to use the BCryptPasswordEncoder instead of DelegatingPasswordEncoder, you can publish it as an #Bean and it will be picked up automatically, like so:
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Take a look at samples like our Username and Password sample for a minimal example of a basic Spring Security application that you can build from.
I've been following issues such as this one in order to figure out how to implement Authentication without WebSecurityConfigurerAdapter, but my code simply fails to work.
This is my SecurityConfig class:
package com.authentication.take.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import com.authentication.take.services.CustomUserDetailsService;
#Configuration
#EnableWebSecurity
public class SecurityConfig {
private final CustomUserDetailsService customUserDetailsService;
private final AuthenticationConfiguration configuration;
public SecurityConfig(CustomUserDetailsService customUserDetailsService,
AuthenticationConfiguration configuration) {
super();
this.customUserDetailsService = customUserDetailsService;
this.configuration = configuration;
}
#Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http)
throws Exception {
http
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/yolo/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
return http.build();
}
#Bean
AuthenticationManager authenticationManager() throws Exception {
return configuration.getAuthenticationManager();
}
void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(customUserDetailsService).passwordEncoder(getPasswordEncoder());
}
}
The problem I am getting is that the /login route is being overriden somehow, and cannot be found. Therefore, when I post data to /login, it isn't interpreted because there is no form in that location.
just add loginProcessingUrl()
....
http
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/yolo/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").permitAll().loginProcessingUrl("/login")//or any another url ,this url accept just post request
.and()
.logout().permitAll();
So i have created a Security Config where i defined the patterns that i want to be granted access to without logging in. And it is not working. In my mind either the file its self is not getting scanned(even though i set it so it would be using #ComponentScan tag in the main Spring application) or the code is faulty.
Here is the code :
package com.projects.AProj.security;
import com.projects.AProj.service.AccountUserDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import static com.projects.AProj.security.Permission.DATA_READ;
import static com.projects.AProj.security.Permission.DATA_WRITE;
#Configuration
#EnableWebSecurity
#AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
private final AccountUserDetailsService accountUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/","/**","/api/**")
.permitAll()
.antMatchers("/my-tree", "/my-tree/*")
.hasAnyAuthority(DATA_READ.getPermission_info(), DATA_WRITE.getPermission_info())
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.defaultSuccessUrl("/",true)
.and()
.logout()
.logoutSuccessUrl("/");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getDaoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider getDaoAuthenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider =
new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(accountUserDetailsService);
return daoAuthenticationProvider;
}
}
btw i would think that it would be helpful to note that the project it self has been acting a tad bit strange. I would get errors that the Repositories are not getting recognized, stuff like can't create bean with name "baseController", unsatisfied dependencies and those kinds of stuff.
Thanks.
I'm creating a spring application for a college project.
package com.sales.security;
import org.springframework.context.annotation.Bean;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/showProducts.html", "/showOrders.html", "/showCustomers.html","/newOrder.html","/addProduct.html","/addCustomer.html")
.authenticated()
.and()
.formLogin();
}
private static final String ENCODED_PASSWORD = "$2y$12$i4Cl5SZgrPFItSz/G5cvTObf0sqzHszwwKMZ4pQeUlElY1BR7KxdO"; //password is "user" encrypted using BCrypt
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user").password(ENCODED_PASSWORD).roles("USER");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I've taken the code from user TwiN at Java Spring Security - User.withDefaultPasswordEncoder() is deprecated?
I have changed the hash to be "user" and have confirmed it's definitely "user" using https://bcrypt-generator.com/
but no matter what now, the login page won't allow me to login and says that my login details are incorrect
here's what my application looks like after entering a username="user" and password ="user"
there are a lot of methods to implement security in spring i can't follow what you are doing but here's my github repo Spring Boot Security you can shange the branches to see diffrent ways to apply security, select the branche "in memory" its the semplest one.
Add below properties in application.properties
spring.security.user.name = user
spring.security.user.password = user
spring.security.user.roles = USER
OR
Add these to the current SecurityConfig class
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
I have a spring MVC application and a remote OAuth2 authorization server. Remote server should be used to log on to the web and mobile application and also to authorize micro services. OAuth2 server for authorization works and when I directly call path for obtain tokens, that request returns access and refresh token correctly.
My problem is that I cannot configure HttpSecurity in a class that extends WebSecurityConfigurerAdapter in the web application, in order to enable logging form to stay in application and send request to remote OAuth2 using the password grunt type. So the loginProcessingUrl() should not be default j_spring_security_check, rather the path to the authorization server. I could not achieve that using addFilterBefore() in the http configuration.
My AuthorizationServerConfigurerAdapter class on the Oauth2 server application in Spring Boot looks like this:
package com.mydomain.oauth2.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("acme")
.secret("acmesecret")
.accessTokenValiditySeconds(3600)
.scopes("read", "write")
.redirectUris("http://localhost:8080/login")
.authorizedGrantTypes("password", "refresh_token")
.autoApprove(true)
.resourceIds("resource");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception {
configurer.authenticationManager(authenticationManager);
configurer.userDetailsService(userDetailsService);
configurer.tokenStore(tokenStore);
}
}
My WebSecurityConfigurerAdapter class on a web application that was written in Spring not in Spring Boot looks like this:
import java.util.Arrays;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.humanbizz.web.security.UserInfoTokenServices;
#Configuration
#EnableWebSecurity
#EnableOAuth2Client
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
#Autowired
OAuth2ClientContext oauth2ClientContext;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login*", "/forgot-password*", "/signup**", "/signup/**", "/resources/**", "/403", "/storage/api/download/**", "/test/public/**").permitAll()
.antMatchers("/user**").anonymous()
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.exceptionHandling()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("?")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/")
.failureUrl("/login?error=true")
.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.logout().logoutSuccessUrl("/login").deleteCookies("JSESSIONID")
.and()
.addFilterBefore( myFilter(), BasicAuthenticationFilter.class);
}
private Filter myFilter() throws Exception{
OAuth2ClientAuthenticationProcessingFilter myFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
OAuth2RestTemplate myTemplate = new OAuth2RestTemplate(template(), oauth2ClientContext);
teodeskFilter.setRestTemplate(myTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices("http://localhost:9000/user", "acme");
tokenServices.setRestTemplate(myTemplate);
teodeskFilter.setTokenServices(tokenServices);
return myFilter;
}
#Bean
public OAuth2ProtectedResourceDetails template() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setClientId("acme");
details.setClientSecret("acmesecret");
details.setAccessTokenUri("http://localhost:9000/oauth/token"); details.setUserAuthorizationUri("http://localhost:9000/oauth/authorize");
details.setGrantType("password");
details.setScope(Arrays.asList("read"));
return details;
}
}
My question is how to configure filter to properly obtain token using form and password grunt type. Form is located on web application and should make request to remote auth server.The examples I have encountered are mostly related to Spring Boot or are solved by the fact that both Authorization Server and Resource Server were together on the same application.