0

I have implemented spring security for the apis. All the apis are working fine for ADMIN role but when I access with other roles it gives 404 error.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }

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

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());

        return authProvider;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/**").hasAuthority("ADMIN")
                .antMatchers("/api/repairs/**").hasAuthority("MECHANIC")
                .antMatchers("/api/users/**", "/api/sales-report/**").hasAuthority("MANAGER")
                .antMatchers("/api/bikes/**", "/api/transactions/**", "/api/customers/**", "/api/spareparts/**")
                .hasAuthority("SALESPERSON")
                .anyRequest().authenticated()
                .and()
                .formLogin().defaultSuccessUrl("/swagger-ui/")
                .and()
                .logout().permitAll()
                .and()
                .exceptionHandling().accessDeniedPage("/403")
        ;
    }

}

EDIT: I have added the custom implementations of the user details and user details service class.

This is my UserDetails custom implementatuion

public class CustomUserDetails implements UserDetails {

    @Autowired
    private User user;

    public CustomUserDetails() {
    }

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

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Set<Role> roles = user.getRoles();
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getRole()));
        }
        return authorities;
    }

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

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

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

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

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

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

and this is the custom implementation of UserDetailsService.

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByName(username);
        CustomUserDetails customUserDetails = null;
        if (user != null) {
            customUserDetails = new CustomUserDetails();
            customUserDetails.setUser(user);
        } else {
            throw new UsernameNotFoundException("User does not exist with name " + username);
        }
        System.out.println("NAME" + customUserDetails.getAuthorities());
        return customUserDetails;
    }
}
Abdullah
  • 45
  • 6

1 Answers1

0

I have solved it if any body faces this issue in the future. I changed it to

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/repairs/**").hasAnyAuthority("ADMIN", "MECHANIC")
                .antMatchers("/users/**", "/sales-report/**").hasAnyAuthority("ADMIN", "MANAGER")
                .antMatchers("/bikes/**", "/transactions/**", "/customers/**", "/spareparts/**")
                .hasAnyAuthority("ADMIN", "SALESPERSON")
                .anyRequest().authenticated()
                .and()
                .formLogin().defaultSuccessUrl("/swagger-ui/")
                .and()
                .logout().permitAll()
                .and()
                .exceptionHandling().accessDeniedPage("/403")
        ;
    }

I changed the configure method, the problem was that .antMatchers("/api/**").hasAuthority("ADMIN") was restricting other roles to access anything that comes after /api/.

Abdullah
  • 45
  • 6