0

I added Username and password field to an existing Customer entity. I have added a Custom JWT filter and authentication provider with a WebSecurityConfig annotated @Order(2). But when I send a post request with the Username and password payload , I get an Unauthorized Error 401 response But no error message in Server Log I have checked the WebConfig file appropriately .What am I not getting right ? I've been on this all day and I seem to be frustrated already.

This is UserDetails class

public class MyCustomerDetails implements UserDetails{

    /**
     * 
     */
    private static final long serialVersionUID = -5087929420394311276L;

    private Long id;
    private String username;
    private String password;
    
    public MyCustomerDetails() {
        
    }
    
    public MyCustomerDetails(Long id, String username, String password) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
    }

   public static MyCustomerDetails build(Customer customer) {
        return new MyCustomerDetails(customer.getId(), 
                customer.getUserName(), customer.getPassword());
    }


   @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getPassword() {
        // TODO Auto-generated method stub
        return password;
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return username;
    }

    ............

This is the Controller class

@CrossOrigin(origins = {"http://localhost:3000"})
@RestController
public class CustomerController {
    
        @Autowired
        CustomerAccountService customerRepo;
        
         @Autowired
         private CustomerJwtTokenUtil customerJwtTokenUtil;
        
         @Autowired
         private AuthenticationManager authenticationManager;
         
    
         @PostMapping(value="/validateCustomer")
          public ResponseEntity <?> createAuthenticationToken( @RequestBody MyCustomerDetails
          authenticationRequest) throws Exception 
             {  
             authenticate(authenticationRequest.getUsername(),  
                authenticationRequest.getPassword()); 
        // Long userId = authenticationRequest.getId();
             final MyCustomerDetails userDetails =  
                 (MyCustomerDetails)   customerRepo.loadUserByUsername(authenticationRequest.getUsername());
           
           final String token = 
                   customerJwtTokenUtil.generateToken(userDetails);
          
          return new ResponseEntity<>(new JwtResponse(token), HttpStatus.OK) ;
                    
         
               }
         private void authenticate(String username, String password) throws Exception {
                    try {
                        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
                    } catch (DisabledException e) {
                        throw new Exception("USER_DISABLED", e);
                    } catch (BadCredentialsException e) {
                        throw new Exception("INVALID_CREDENTIALS", e);
                    }
                }
             

This is the WebSecurityconfig class


@Configuration
@Order(2)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomerSecurityConfiguration extends WebSecurityConfigurerAdapter {

    
    @Autowired
    private CustomerJwtAuthenticationEntryPoint customerJwtAuthenticationEntryPoint;
    
    @Autowired
    private UserDetailsService myCustomerDetailsService;
    
    @Autowired 
    private CustomerJwtRequestFilter customerJwtRequestFilter;
     
    
    @Bean
    public CustomerAccountService myCustomerAccountService() {
        return new CustomerAccountService();
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    /*
     * @Bean public UserDetailsService myCustomerDetailsService() { return
     * myCustomerDetailsService(); }
     */
    
    
     @Bean
        public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder,
                                                                   UserDetailsService userDetailsService){ 
            DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
            daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
            daoAuthenticationProvider.setUserDetailsService(userDetailsService);
            return daoAuthenticationProvider;
      }
     
     
     @Override
     @Bean
     public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
     }

     
     protected void configure(AuthenticationManagerBuilder auth ) throws Exception {
         auth.userDetailsService(myCustomerDetailsService).passwordEncoder(passwordEncoder());
         }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.cors().and().csrf().disable()
      .authorizeRequests()
      .antMatchers("/***").permitAll()
    
     // .antMatchers("/customer/**").hasAuthority("CUSTOMER")
      .anyRequest().authenticated()
      .and()
      .exceptionHandling()
      .authenticationEntryPoint(customerJwtAuthenticationEntryPoint)
      
      .and()
      .formLogin().permitAll()
    //  .loginPage("/login")
     
      .and()
      .logout().logoutUrl("/logout").logoutSuccessUrl("/login")
     
      .and()
      .sessionManagement()
      .maximumSessions(1)
      .and()
      .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
      http.addFilterBefore(customerJwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
          
    
}

The Service class

@Primary
public class CustomerAccountService implements UserDetailsService {
    
    
    @Autowired  
    private CustomerAccountRepo custRepo;
    
    @Qualifier("passwordEncoder")
    @Autowired
    private PasswordEncoder bCryptPasswordEncoder;
    
    
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Customer customer = custRepo.findByUserName(username);
        if(customer == null) {
            throw new UsernameNotFoundException("Customer not found");
        }
        
      return MyCustomerDetails.build(customer);
        
      }
    

This is the Base class


@Configuration
@EnableWebMvc
//@ComponentScan(basePackages = "com.bethsaida.org.security")
@EnableJpaRepositories
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class BethsaidaApplication  {
    
     public static void main(String[] args) 
      {SpringApplication.run(BethsaidaApplication.class, args);}
 
     public class WebConfig implements WebMvcConfigurer 
        { 
         private static final long MAX_AGE_SECS = 3600;

        @Override
        public void addCorsMappings(CorsRegistry registry) 
         { registry.addMapping("/**")
             .allowedOrigins("*")
             .allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
             .maxAge(MAX_AGE_SECS);}
        }
     
    }



wizdemonizer
  • 115
  • 4
  • 15
  • Do you have another `WebSecurityConfigurerAdapter` with Order 1? To help with debugging you can turn on TRACE logging for Spring Security and see which Filters the request is going though `logging.level.org.springframework.security=TRACE` – Eleftheria Stein-Kousathana Oct 28 '21 at 07:34
  • @EleftheriaStein-Kousathana Yes I have another WebSecurityConfigurerAdapter with Order 1 . Thanks for your suggestions though will do that. – wizdemonizer Oct 28 '21 at 09:23

1 Answers1

0

You can use this

   @Override
   public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("POST", "PUT", "DELETE")
        .allowedHeaders("header1", "header2")
        .exposedHeaders("header1", "header2")
        .allowCredentials(false).maxAge(3600);
   }

inside your CustomerSecurityConfiguration class directly. Because WebMvcConfigurer is implemented by WebMvcConfigurerAdapter so you can define this method inside your CustomerSecurityConfiguration class.

For more information, you can see here

Neeraj
  • 121
  • 3