springspring-securityspring-security-rest

SecurityContext is null even if it was instantiated in SecurityContextHolder


I have a problem with Spring Security. When I'm trying to authenticate an user on my application, I'm redirected back to signin.html. After debugging, I saw that even if I'm instantiating SecurityContextHolder.getContext().setAuthentication(); , SecurityContext is null.

This is my authentication code:

public boolean dbAuthentication(String username, String password) {
            Boolean response = false;
            try {
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                response = passwordEncoder.matches(password, userDetails.getPassword());
                if(response) {
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
                    if (usernamePasswordAuthenticationToken.isAuthenticated()) {
                        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    }
                }
            } catch(Exception e) {
                response = false;
            }
            return response;
        }

This is my WebSecurityConfig class:

   public class WebSecurityConfig {

    @Autowired
    private AppConfig appConfig;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() throws Exception{
        return (web) -> web.ignoring().requestMatchers( "/build/**","/ext/**","/resources/**","../../../resources/**","/../../resources/**","../resources/**");
    }


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.
                    csrf(AbstractHttpConfigurer::disable).
                    headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
                    .authorizeHttpRequests(a -> a
                            .requestMatchers("/app/**").permitAll()
                            .requestMatchers("/signin.html").permitAll()
                            .requestMatchers("/forgot.html").permitAll()
                            .requestMatchers("/getCustomCss/**").permitAll()
                            .requestMatchers("/oauth2sso/**").permitAll()
                            .requestMatchers("/isLdapEnabled/**").permitAll()
                            .requestMatchers("/isSamlEnabled/**").permitAll()
                            .requestMatchers("/prefetchFiles*").permitAll()
                            .requestMatchers("/languages/getLanguages*").permitAll()
                            .requestMatchers("/getSessionTimeout").permitAll()
                            .requestMatchers("/wakeUpElastic/**").permitAll()
                            .requestMatchers("/forgotPassword*").permitAll()
                            .requestMatchers("/recoverPassword*").permitAll()
                            .requestMatchers("/authenticate*").permitAll()
                            .requestMatchers("/build/**").permitAll()
                            .requestMatchers("/ext/**").permitAll()
                            .requestMatchers("/resources/**").permitAll()
                            .requestMatchers("/logout*").permitAll()
                            .anyRequest().authenticated()
                    ).formLogin(formLogin -> formLogin.loginPage("/signin.html").
                            usernameParameter("username")
                            .passwordParameter("password")
                            .defaultSuccessUrl("/index.html", true)
                            .failureUrl("/signin.html?error=true"))
                    .logout(l -> l
                            .invalidateHttpSession(true)
                            .deleteCookies("SESSIONID")
                            .logoutUrl("/signin.html?logout"));
        return http.build();
    }
}

This problem occurs when I'm trying to update the SpringSecurity version to latest one and I tried to follow every instruction from official documentation, but without success.


Solution

  • I think you are referring to this line in dbAuthentication(..) method as you have instantiated the securityContext.

    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
    

    The problem is, that you are getting the SecurityContext from SecurityContextHolder and trying to set the Authentication value which is not recommended. You need to populate the security context as

    SecurityContext context = SecurityContextHolder.createEmptyContext();
    Authentication authentication =
        new TestingAuthenticationToken("username", "password", "ROLE_USER");
    context.setAuthentication(authentication);
    
    SecurityContextHolder.setContext(context);
    

    Only then, you will be able to use it.

    Regarding not being able to find it in the documentation, Here is the link to the official doc on setting SecurityContext.