Spring Security: Failed to authorize filter invocation

Viewed 127

My Spring Boot application is returning a 403 status code (forbidden) when I call a GET request in my AdminControllor

I am trying to blacklist URLs which have "/admin/**" except for those users who have the authority "ADMIN" in my database.

I have disabled csrf which seems to be the most common issue for 403 forbidden.

The problem seems to relate (see debug logs) to this:

Failed to authorize filter invocation [GET /admin/allusers] with attributes [hasAuthority('ADMIN')]

Logs

2022-09-08 13:56:20.018 DEBUG 21328 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /admin/allusers
2022-09-08 13:56:20.026 DEBUG 21328 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2022-09-08 13:56:20.026 DEBUG 21328 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2022-09-08 13:56:20.042 DEBUG 21328 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [GET /admin/allusers] with attributes [hasAuthority('ADMIN')]
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] o.s.s.w.s.HttpSessionRequestCache        : Saved request http://localhost:8080/admin/allusers to session
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /error
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2022-09-08 13:56:20.090 DEBUG 21328 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Secured GET /error
2022-09-08 13:56:20.190 DEBUG 21328 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext
2022-09-08 13:56:20.198 DEBUG 21328 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext

My Security Config class

package com.example.spring_security.config;

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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
        .mvcMatchers("/admin/**").hasAuthority("ADMIN")
        .anyRequest().permitAll();
    return http.build();
}

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

My UserDetails

package com.example.spring_security.security;


import com.example.spring_security.entities.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.stream.Collectors;


public class SecurityUser implements UserDetails {

    private final User user;

    public SecurityUser(User user){
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getAuthorities()
                .stream()
                .map(SecurityAuthority::new)
                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

My UserDetailsService

package com.example.spring_security.services;

import com.example.spring_security.repositories.UserRepository;
import com.example.spring_security.security.SecurityUser;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class JpaUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    public JpaUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username)  {
        var u = userRepository.findUserByUsername(username);
        return u.map(SecurityUser::new)
                .orElseThrow(() -> new UsernameNotFoundException("Username not found " + username));
    }

}

My GrantedAuthority

package com.example.spring_security.security;

import com.example.spring_security.entities.Authority;
import org.springframework.security.core.GrantedAuthority;

public class SecurityAuthority implements GrantedAuthority {

    private final Authority authority;

    public SecurityAuthority(Authority authority) {
        this.authority = authority;
    }

    @Override
    public String getAuthority() {
        return authority.getName();
    }
}
1 Answers

I managed to get this working by adding formLogin() in my security configuration class. If omitted from Spring Security then there is no configuration for the authentication filter. See here.

Related