POST operation on /logout and getting No mapping for GET /login - spring

I'm trying to perform logout so I send POST on /logout but what I get is:
{
"timestamp": 1590427554418,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/login"
}
I'm using POSTMAN. Despite having error logout perform correclly, because I cannot make any actions on other endpoints when I'm not logged.
The point is when code is uploaded on the server I got timeout:
I thought it might be somehow related.
WebSecurityConfiguration
package odd.jobs.configuration;
import odd.jobs.configuration.authentication.JsonObjectAuthenticationFilter;
import odd.jobs.configuration.authentication.RestAuthenticationFailureHandler;
import odd.jobs.configuration.authentication.RestAuthenticationSuccessHandler;
import odd.jobs.services.user.UserCrudService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.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;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.Collections;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserCrudService userService;
private final RestAuthenticationSuccessHandler authenticationSuccessHandler;
private final RestAuthenticationFailureHandler authenticationFailureHandler;
#Autowired
public WebSecurityConfiguration(UserCrudService userService, RestAuthenticationSuccessHandler authenticationSuccessHandler, RestAuthenticationFailureHandler authenticationFailureHandler) {
this.userService = userService;
this.authenticationSuccessHandler = authenticationSuccessHandler;
this.authenticationFailureHandler = authenticationFailureHandler;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll();
http.cors();
}
#Bean
public JsonObjectAuthenticationFilter authenticationFilter() throws Exception {
JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
filter.setAuthenticationFailureHandler(authenticationFailureHandler);
filter.setAuthenticationManager(super.authenticationManagerBean());
return filter;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.unmodifiableList(Arrays.asList("*")));
configuration.setAllowedMethods(Collections.unmodifiableList(Arrays.asList("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH")));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(Collections.unmodifiableList(Arrays.asList("Authorization", "Cache-Control", "Content-Type")));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}

It seems you used postman but with wrong method type as postman exception implies
Please change postman HTTP method from GET to POST from here :
Hope it should work!

If you want to use POST /logout, configure Spring Security with new AntPathRequestMatcher("/logout", "POST") instead of new AntPathRequestMatcher("/logout") (GET is used by default)

Related

Register api is resposing 403 forbidden but csrf is disabled in spring boot

I am creating backend app and testing as well. my register url is resposing 403 forbidden but csrf is disabled. I can't fix this problem. Please help me P
Here is my configuration
package uz.renessans.configuration;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import uz.renessans.entity.user.UserRepository;
import uz.renessans.security.JwtFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#RequiredArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final JwtFilter jwtFilter;
private final UserRepository userRepository;
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService = username ->
userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException(username));
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
String[] OPEN_URLS = {
"/api/v1/register/**",
"/swagger-ui/**",
"/api/v1/login"
};
http
.csrf()
.disable()
.httpBasic()
.disable()
.authorizeRequests()
.antMatchers(
"/api/v1/register/**",
"/swagger-ui/**",
"/api/v1/login"
)
.permitAll()
.anyRequest()
.authenticated();
// .permitAll();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Here is my jwt filter class:
package uz.renessans.security;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import uz.renessans.entity.user.User;
import uz.renessans.entity.user.UserRepository;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
#Component
#RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {
private final JwtProvider jwtProvider;
private final UserRepository userRepository;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.startsWith("Bearer") && authorization.length() > 7) {
authorization = authorization.substring(7);
String username = jwtProvider.getPhoneNumber(authorization);
if (username != null) {
Optional<User> optionalUser = userRepository.findByUsername(username);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = null;
if (optionalUser.isPresent()) {
usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(optionalUser.get(), null, optionalUser.get().getAuthorities());
}
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
Here is my register api
public HttpEntity<?> register(RegisterDto dto, Role role) {
if (userRepository.existsByUsername(dto.getUsername()))
return new ResponseEntity<>(new ApiResponse("Username already exists", false), HttpStatus.CONFLICT);
if (!dto.getPassword().equals(dto.getRePassword()))
return new ResponseEntity<>(new ApiResponse("Password must match", false), HttpStatus.CONFLICT);
User user = new User();
user.setRole(role);
user.setUsername(dto.getUsername());
user.setPassword(passwordEncoder.encode(dto.getPassword()));
user.setFullName(dto.getFullName());
User savedUser = userRepository.save(user);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
savedUser.getUsername(), savedUser.getPassword());
authenticationManager.authenticate(authenticationToken);
String token = jwtProvider.generateToken(savedUser.getUsername(), savedUser.getRole());
Response response = Response.builder().token(token).role(role.toString()).build();
return new ResponseEntity<>(new ApiResponse("Registered Successfully", true, response), HttpStatus.OK);
}

How to only check for Authentication by "Bearer" header in Spring Boot using Spring Security?

I want to authenticate a server. I want to make sure the user is giving a header key, I am not checking for login or anything.
I want the header key to check with my hardcoded one,
If its equal pass it,
Else no
I wrote two filters.
SecurityConfig.java
package com.company.framework.filter;
import javax.servlet.http.HttpServletResponse;
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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
public class SecurityConfig{
#Autowired private AuthFilter filtet;
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
System.out.println("reaching here3 ");
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/open/**").permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error here")
)
.and()
.sessionManagement()
.and()
.httpBasic().disable();
http
.addFilter(filtet);
return http.build();
}
}
Authfilter.java
package com.company.framework.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
#Component
public class AuthFilter extends OncePerRequestFilter{
#Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
System.out.println("here ");
System.out.println(authHeader+"1");
if (authHeader != null && authHeader.length() == 0 && authHeader.startsWith("Bearer ")) {
String jwt = authHeader.substring(7);
System.out.println(authHeader+"2");
if (jwt == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token in Bearer Header");
} else {
String rev = "bfrek";
if (jwt.equals(rev)) {
response.setStatus(200);
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token");
}
}
}
filterChain.doFilter(request, response);
}
}
But, after all days of try and error, I am still getting 401 unauthorised.
I have seen articles telling how to connect it with users database but I just want to check for header token and pass it through. (Using filter)
Edit 1:
Now after reading many articles and documentation, I understand that there are 15 filters, But how do I make sure that the system just checks for my header key and ignore everything else.
Seems you missed overriding the configure method of WebSecurityConfigurerAdapter class. This is the main logic to override the default spring security logic. This is the main problem i guess. try to extend that class(WebSecurityConfigurerAdapter) and override that method(configure) in SecurityConfig.java.
SecurityConfig.java
package com.company.framework.filter;
import javax.servlet.http.HttpServletResponse;
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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurer{
#Autowired private AuthFilter filtet;
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
System.out.println("reaching here3 ");
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/open/**").permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error here")
)
.and()
.sessionManagement()
.and()
.httpBasic().disable();
http.addFilter(filtet);
return http.build();
}
}

Spring Security work with Chrome but allow GET from Postman without authorization

i have problem with my spring security implemntation.
I have some basic configuration of UserDetails and UserDetailsService.I've done some Endpoints and some Security Configuration with WebSecurityConfigurerAdapter.
Everything works fine on chrome - if you try to access an secured endpoint security cofniugration redirects you to login form and after login redirects you to yours /api.
But in postman when sending even GET request authorization not working and you can fetch reposonse with all data that sould be availabe only for admin or after authorization.
Here is my Security Configuration
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.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.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableWebSecurity
#EnableTransactionManagement
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
AuthenticationSuccessHandler successHandler;
#Autowired
UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http./*sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).
and().*/
authorizeRequests()
.antMatchers("/api/players").hasAnyRole("ADMIN")
.antMatchers("/api/organizers").hasAnyRole("ADMIN")
.antMatchers("/api/events").permitAll()
.antMatchers("/h2-console/**").permitAll()
.and()
.formLogin()
.successHandler(successHandler)
.permitAll()
.and()
.logout()
.permitAll()
/*.and()
.csrf().disable()*/;
}
#Bean
public PasswordEncoder getPasswordEncoder() {return NoOpPasswordEncoder.getInstance();}
}
and configuration for sample GET endpoint
#RestController
#RequestMapping(value="/api",produces = MediaType.APPLICATION_JSON_VALUE)
#RequiredArgsConstructor
public class UserViewRestContoller {
#NonNull
private final UserQuery query;
#GetMapping(value="/players")
#PreAuthorize("hasRole('ADMIN')")
List<PlayerView> getPlayers() {
return query.listPlayers();
}
#GetMapping(value="players/{userId}",produces = MediaType.APPLICATION_JSON_VALUE)
#PreAuthorize("#userId == authentication.principal.userId or hasRole('ADMIN')")
PlayerDetails getPlayer(#PathVariable UUID userId){
return query.getPlayerDetails(userId);
}
So in browser accesing /api/players you will see
and in POSTMAN
Did you enable global method security?
#EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true)
Also I don't see any JWT token implementation in the code. How are you getting admin role and authorize it. Where do you get Admin role?
I have found the problem, it was the definition of antMatchers:
.antMatchers("/api/players")
It only secures /api/players not /api/players/ and /api/players/**.
The proper ant matchers should be:
.antMatchers("/api/players/**").hasAnyRole("ADMIN")

Spring security : I tried to test http://localhost:8080/login Post method and I redirected to the same path for login again

I have created account with spring security , I have test the functionality with Postman and my frontend it's works good, then I try to login and every time I redirected to login , it's like a problem of authorization
from frontend I get this error:
Access to XMLHttpRequest at 'http://192.168.43.216:8080/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This my WebSecurityConfig.java
package com.pi.MinuteBrico.security.config;
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.bcrypt.BCryptPasswordEncoder;
import com.pi.MinuteBrico.services.AppUserService;
#Configuration
//#AllArgsConstructor
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final AppUserService appUserService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurityConfig(AppUserService appUserService,
BCryptPasswordEncoder bCryptPasswordEncoder) {
super();
this.appUserService = appUserService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/registration/**"/*,SecurityConstraint.ROLE_ALL_AUTHENTICATED_USE*/)
.permitAll()
.anyRequest()
.authenticated().and()
.formLogin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider =
new DaoAuthenticationProvider();
provider.setPasswordEncoder(bCryptPasswordEncoder);
provider.setUserDetailsService(appUserService);
return provider;
}
}
**This what Happen when I try to test Post method for login http://localhost:8080/login on postman **
[![enter image description here][1]][1]
The cors (Cross Origin Resource Sharing) filter is added in your spring security configuration when you add http.cors(). This means only from same origin request will be servered. To add cross origin request to be served you need to add configuration for that. Add below bean to your SecurityConfiguration. For more deails check the link
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://localhost:300")); //URLs you want to allow
configuration.setAllowedMethods(Arrays.asList("GET","POST")); //methods you want to allow
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}

Spring-boot 2.0 session issue when request is coming from different host

So I have updated my application from spring-boot 1.5 to spring-boot 2.0. I was able to login properly with spring-boot 1.5 version when the request was coming from any host, but now the problem with Spring boot 2.0 is only requests from same host is working, but request coming from different host their session is getting changed. Below is the spring security config I have in spring-boot 2.0 whic is causing the issue.
package com.s4m.digiid.config;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import com.s4m.digiid.handler.CustomAccessDeniedHandler;
import com.s4m.digiid.handler.CustomAuthFailureHandler;
import com.s4m.digiid.handler.LoginHandler;
import com.s4m.digiid.handler.LogoutHandler;
import com.s4m.digiid.service.impl.AuthenticationService;
import com.s4m.digiid.util.ApiConstants;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#EnableJpaRepositories(basePackages = "com.s4m.digiid.repository")
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private LogoutHandler logoutHandler;
#Autowired
private LoginHandler loginHandler;
#Autowired
private CustomAuthFailureHandler customAuthFailure;
#Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
#Autowired
private AuthenticationService authService;
#Value("${maximum.sessions}")
private Integer maxSessions;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authService)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
private FindByIndexNameSessionRepository<? extends Session> sessionRepository;
#Bean
public SpringSessionBackedSessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
}
#Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(ApiConstants.SWAGGER_DOC_API, ApiConstants.SWAGGER_CONFIG_UI, ApiConstants.SWAGGER_RESOURCES,
ApiConstants.SWAGGER_CONFIG, ApiConstants.SWAGGER_HTML_UI, ApiConstants.WEB_JARS, ApiConstants.FAVICON).permitAll()
.and().formLogin().successHandler(loginHandler).failureHandler(customAuthFailure)
.and().logout()
.logoutUrl("/appLogout")
.logoutSuccessHandler(logoutHandler)
.and().exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.and().csrf().disable()
.cors().and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.sessionManagement().maximumSessions(maxSessions).sessionRegistry(sessionRegistry()).maxSessionsPreventsLogin(false);
}
#Bean
public AuthenticationFilter authenticationFilter() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationFailureHandler(customAuthFailure);
filter.setAuthenticationSuccessHandler(loginHandler);
return filter;
}
#Bean
public CorsConfigurationSource corsConfigurationSource()
{
List<String> allowedClients = Arrays.asList(env.getProperty("digiid.allowed.clients").split(","));
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(allowedClients);
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
configuration.setMaxAge(Long.parseLong("3600"));
configuration.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization,X-Auth-Token"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Below is the code in spring-boot 1.5 which is working fine.
package com.s4m.digiid.config;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import com.s4m.digiid.handler.CustomAccessDeniedHandler;
import com.s4m.digiid.handler.CustomAuthFailureHandler;
import com.s4m.digiid.handler.LoginHandler;
import com.s4m.digiid.handler.LogoutHandler;
import com.s4m.digiid.service.impl.AuthenticationService;
import com.s4m.digiid.util.ApiConstants;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#EnableRedisHttpSession
#EnableJpaRepositories(basePackages = "com.s4m.digiid.repository")
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private LogoutHandler logoutHandler;
#Autowired
private LoginHandler loginHandler;
#Autowired
private CustomAuthFailureHandler customAuthFailure;
#Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
#Autowired
private AuthenticationService authService;
#Autowired
private SpringSessionBackedSessionRegistry sessionRegistry;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authService)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(ApiConstants.SWAGGER_DOC_API, ApiConstants.SWAGGER_CONFIG_UI, ApiConstants.SWAGGER_RESOURCES,
ApiConstants.SWAGGER_CONFIG, ApiConstants.SWAGGER_HTML_UI, ApiConstants.WEB_JARS, ApiConstants.FAVICON).permitAll()
.and().formLogin().successHandler(loginHandler).failureHandler(customAuthFailure)
.and().logout()
.logoutUrl("/appLogout")
.logoutSuccessHandler(logoutHandler)
.and().exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.and().csrf().disable()
.cors().and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry).maxSessionsPreventsLogin(false);
}
#Bean
public AuthenticationFilter authenticationFilter() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationFailureHandler(customAuthFailure);
filter.setAuthenticationSuccessHandler(loginHandler);
return filter;
}
#Bean
public CorsConfigurationSource corsConfigurationSource()
{
List<String> allowedClients = Arrays.asList(env.getProperty("digiid.allowed.clients").split(","));
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(allowedClients);
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
configuration.setMaxAge(Long.parseLong("3600"));
configuration.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization,X-Auth-Token"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
With the spring-boot upgrade to 2.x, "SameSite" attribute of Cookie handled in DefaultCookieSerializer.java class is set to "Lax" by default. 
 
  
Try setting  "SameSite" attribute's value to "None".
For more details, https://datatracker.ietf.org/doc/html/draft-west-first-party-cookies-07
  
  
  

Resources