UserDetailsService creates circular dependency - java

I have a circular dependency forming on my WebSecurityCongfig. I have tracked it down to the UserDetailsService and once I remove it it builds but I cannot perform jwt filter because of it. The interesting part is that on my other services the exact same code works flawlessly.
package com.fain.events.events.security;
import commons.src.main.java.software.commons.config.filters.ExceptionHandlerFilter;
import lombok.RequiredArgsConstructor;
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.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
#SuppressWarnings("SpringJavaAutowiringInspection")
#RequiredArgsConstructor
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Lazy
private final UserDetailsService userDetailsServiceImpl;
#Lazy
private final JwtAuthenticationEntryPoint unauthorizedHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.authorizeRequests()
.antMatchers(
"/favicon.ico",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/v2/api-docs",
"/swagger-resources/**",
"/healthcheck",
"/webjars/**",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/*.html")
.permitAll()
.antMatchers(
HttpMethod.POST,
"/api/auth/register",
"/api/auth/socialMedia",
"/api/auth/login",
"/api/auth/refreshToken",
"/api/auth/forgotPassword",
"/api/auth/resetPassword",
"/api/auth/facebook/login",
"/api/auth/resendRegistrationEmail",
"/api/auth/facebook/forwardLogin",
"/api/auth/google/login",
"/api/auth/validateTwoFactorAuthenticationCode",
"/api/auth/activateAccount",
"/api/auth/confirmAccount",
"/api/auth/validateToken",
"/api/auth/generateToken",
"/api/auth/confirmEmail",
"/resetPassword",
"/Callback/**")
.permitAll()
.antMatchers(HttpMethod.PATCH,"/api/users/{\\d+}/give-role/{\\d+}", "/api/users/{\\d+}/remove-role/{\\d+}").permitAll()
.antMatchers(
HttpMethod.GET,
"/resetPassword",
"/images/**",
"/settings/**",
"/confirmEmail",
"/api/location/**",
"/api/auth/facebook/login")
.permitAll()
.antMatchers(
HttpMethod.GET,
"/api/users/{\\d+}",
"/api/users/profiles"
).access(("isAuthenticated() or hasIpAddress('127.0.0.1')"))
.antMatchers(HttpMethod.OPTIONS)
.permitAll()
.anyRequest()
.authenticated()
.and()
// And filter other requests to check the presence of JWT in header
.addFilterBefore(
authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new ExceptionHandlerFilter(), JwtTokenVerificationFilter.class);
}
#Autowired
public void configureAuthentication(#Lazy AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsServiceImpl)
.passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
public JwtTokenVerificationFilter authenticationTokenFilterBean() throws Exception {
JwtTokenVerificationFilter authenticationTokenFilter = new JwtTokenVerificationFilter();
authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationTokenFilter;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
#Lazy
#Override
public UserDetailsService userDetailsService() {
return super.userDetailsService();
}
}
Here is the circular dependency error

Related

Authenticating without WebSecurityConfigurerAdapter

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();

Spring Security always returns 403 forbidden in Postman

I'm trying to configure Spring Security authorization but I'm getting 403 (forbidden) for each Postman request.
I checked the other questions but nothing works. Can anyone who got this problem and resolved it share what I need to do to fix it?
I want to add an authorization to make /authenticate accessible for all users, /registeradmin, /registersimpleuser and /listallusers only for the admin role.
I'm getting 403 even in /authenticate which is configured as permit all.
Spring Security config class:
package com.project.encheres.security.configuration;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import com.project.encheres.repository.UserRepository;
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class })
#Configuration
#EnableWebSecurity
#Component
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserRepository userRepo;
#Autowired
UserDetailsService userDetailsService;
public SecurityConfiguration(UserRepository userRepo) {
this.userRepo = userRepo;
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/user/registersimpleuser").permitAll();
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/authenticate").permitAll()
.antMatchers(HttpMethod.GET, "localhost:8070/user/listallusers").hasAuthority("ADMIN");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
public BCryptPasswordEncoder gePasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/user/registersimpleuser").permitAll();
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/authenticate").permitAll()
.antMatchers(HttpMethod.GET, "localhost:8070/user/listallusers").hasAuthority("ADMIN");
http
.csrf().disable();
}
Just added http.csrf().disable(); in the end of the method.
this will describe why your code was not working earlier

PreAuthorize does not work in spring security

Why #PreAuthorize doesn't work? It does not throw any exceptions or errors. I have been struggling with this task for several days. I've tried many options but It doesn't work.
I will be very grateful to anyone who can help solve this problem.
SecurityConfig.java
package com.testpreauthorize.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/")
.and()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.and()
.csrf().disable();
}
}
HomeController.java
package com.testpreauthorize.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
#Controller
public class HomeController {
#GetMapping(value = "/")
public String home () {
return "/home";
}
#PreAuthorize("isAuthenticated()")
#GetMapping(value = "/user")
public String user () {
return "/user";
}
#GetMapping(value = "/login")
public String loginGet () {
return "/login";
}
#PostMapping(value = "/login")
public String loginPost () {
return "redirect:/user";
}
}

Sending POST on /login spring security with postman

I'm struggling with log into my application with postman. I'm using spring security with simple configuration:
package main.configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
public WebSecurityConfiguration(#Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/createUser").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
#Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(HttpMethod.POST, "/createUser")
.antMatchers(HttpMethod.POST, "/login");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I'm sending POST request on /loginso that I could log in, but all the time I get:
photo from postman
Could you tell me what I'm doing wrong here? How am I supposed to log in and oparte on postman normally? What is interesting if I try to get page within my browser, I'm asked for credentials and then I'm succesfully logged in.
I want to access my other pages which are protected and test them using POSTMAN.
Here is the answer, lack of httpBasic()
Conf class:
package main.configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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.HttpStatusEntryPoint;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
public WebSecurityConfiguration(#Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/createUser").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll().and().httpBasic();
http.csrf().disable();
}
#Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(HttpMethod.POST, "/createUser");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
In that case can you please change below as of now and take it from there ?
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password(passwordEncoder().encode("user1Pass")).roles("POSTMAN");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/success.html", true) // example page where request need to be redirected when login is sucessful.
.and()
.logout()
.deleteCookies("JSESSIONID");
}
Try above username and password using in memory implementation first and then configure databaseservice later.
Create success.html and you should see the same after login attempt
If you want to test internal URL's through POSTMAN without authentication/ authorization then comment .anyRequest().authenticated() during testing.

How to wire authentication with Spring Boot

I am following the documentation from Spring.io to setup user authentication using Spring Boot.
Here are the files in question:
MvcConfig.java
package com.*********.*******;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class MvcConfig implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
WebSecurityConfig.java
package com.*********.*******;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
How can I eliminate the home.html file and wire it so that localhost:808 takes the user directly to the login which, if successful, brings them to the hello.html file?
If I change the default controller to the following code, then it just enters a loop of the login page because the login takes you to the previous page you were trying to access. How can I instead have it send the user to hello.html?
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("login");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
I apologize if this post is worded poorly. If there is anything I can add for clarity, please don't hesitate to ask and I will make any corrections.
Remove the line .antMatchers("/", "/home").permitAll() so all urls are protected and redirected to login.
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}

Categories

Resources