Why isn't my Spring Boot api authenticating user from MySQL database with the correct username/password?

Viewed 140

I'm new to spring boot and im making a web app for practice. I'm trying to set up the authentication for my Spring Boot project. I was following a tutorial and they mentioned that in the UserDetailsService (my implementation of it) is where I should autowire my JPA repository which is returning the existing user. The username matches. Once the UserDetails object is passed back to the AuthenticationProvider, I followed the flow of the program with the debugger line by line and it seems like it hits an "InvocationTargetException", yet, nothing appears on my console stacktrace. What could I be doing wrong?

On a side question, where is the password supposed to be verified? Does the AuthenticationManger handle that internally?

Auth Controller:

@RestController
@RequestMapping("api/auth")
public class Auth {
    
    @Autowired
    private AuthService authService;

    
    @PostMapping("login")
    public AuthenticationResponse login(@RequestBody LoginRequest loginRequest) {
        System.out.println("part 1");
        return authService.login(loginRequest);
    } 

AuthService:


@AllArgsConstructor
@Service
public class AuthService {

    private final PasswordEncoder passwordEncoder;
    private final HunterRepository hunterRepo;
    private final AuthenticationManager authenticationManager;

    public AuthenticationResponse login(LoginRequest loginRequest) {
        org.springframework.security.core.Authentication authenticate = 
               authenticationManager.authenticate(new 
                          UsernamePasswordAuthenticationToken(loginRequest.getUsername(),
                                          loginRequest.getPassword()));

           System.out.println("check 2: " + authenticate.isAuthenticated());
           SecurityContextHolder.getContext().setAuthentication(authenticate);
           String token = jwtProvider.generateToken(authenticate);
           System.out.println("this is token: " + token);
           return new AuthenticationResponse(token, loginRequest.getUsername());
    }

SecurityConfig :

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsServiceImpl userDetailsService;

    public SecurityConfig(UserDetailsServiceImpl userDetailsService){
      this.userDetailsService = userDetailsService;
    }   

    @Bean(BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().and()
        .csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.POST, "/api/**")
        .permitAll()
        .antMatchers("/api/**")
        .permitAll()
        .antMatchers(HttpMethod.GET, "/api/posts/")
        .permitAll()
        .antMatchers(HttpMethod.GET, "/api/posts/**")
        .permitAll()
        // change the bottom matchers to my site's urls
        .antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**")
        .permitAll()
        .anyRequest()
        .authenticated();
    }
    
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authenticationManager) throws Exception 
   {
        authenticationManager.userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder());
    }
    
    @Bean
    PasswordEncoder passwordEncoder() {
        /*
         * passwordEncoder is part of spring security. it is used to encrypt passwords with a 
         * BCrypt hashing algorithm
         */
        return new BCryptPasswordEncoder();
    }
}

UserDetailsServiceImpl

@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
    
    private final HunterRepository hunterRepo;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("check 2: " + username);
        Optional<Hunter> userOptional = hunterRepo.findByUsername(username);

        System.out.println("check 3, is value present?" + userOptional.isPresent());
        
//      Hunter hunter = userOptional
//          .orElseThrow(() -> new UsernameNotFoundException("No user " +
//                          "Found with username : " + username));
        Hunter hunter = null;
        if (userOptional.isPresent())
        {
            System.out.println("userOptional is present");
            hunter = userOptional.get();
        }
        else
        {
            System.out.println("userOptional is not present");
            throw new UsernameNotFoundException("no user found with username");
        }
            
            return new org.springframework.security
                    .core.userdetails.User(hunter.getUsername(), hunter.getPassword(),
                    hunter.isEnabled(), true, true,
                    true, getAuthorities("USER"));
    }
    
      private Collection<? extends GrantedAuthority> getAuthorities(String role) {
            //return Collections.singletonList(new SimpleGrantedAuthority(role));
          return Arrays.asList(new SimpleGrantedAuthority(role));
        }

}

HunterRepository

public interface HunterRepository extends CrudRepository<Hunter, Integer>{
    Optional<Hunter> findByUsername(String username);
}

stacktrace

stacktrace

returning message from the spring boot api after sending a POST request with a json with username and password in the body of request

api returning message

0 Answers
Related