Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Background -> Learning Spring Security
- * Requirements -> to create a "all-in-one" authentication mechanism that allows multiple methods of authentication (e.g. authentication via username, via email, via phone number, oauth, OTP, etc.)
- * Logic -> Create custom `SecurityFilterChain` to personalize access routes, custom `PasswordEncoder` for using Argon2PasswordEncoder, as well as custom `UserDetailsService` to allow loading `UserDetails` in spring via JPA/Hibernate
- Problem -> I can authenticate via username just fine, but using email to authenticate throws an error, because the `myCustomAuthenticationProvider.authenticate()` method calls "loadUserByUsername()" method... which is fine if I am passing a username into it... but what if I am passing an email into it? It won't be able to load the UserDetails object, because, well.. it needs a username for it.
- Further steps -> I am unable to think what to do from now. I can't think of a way to overload the `loadUserByUsername` method, nor does spring allow me to do that. Moreover the `myCustomUserDetailsService.loginUserByEmail(String email, String password)` method defined in my own custom `UserDetailsService` is calling the `loadUserByUsername` method (which I think is by design, since in spring security architecture, the authentication manager HAS to call it to authenticate the credentials?)
- */
- // File - WebSecurityConfig.java
- @Configuration
- @EnableWebSecurity
- public class WebSecurityConfig {
- @Autowired
- private AuthService authService;
- @Autowired
- private PasswordEncoder passwordEncoder;
- @Bean
- public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
- httpSecurity.
- csrf(csrf -> csrf.disable()).
- authorizeHttpRequests(auth -> auth.
- requestMatchers("/auth/register", "/auth/login/username").permitAll().
- anyRequest().authenticated()
- ).
- authenticationManager(authenticationManager());
- return httpSecurity.build();
- }
- @Bean
- public AuthenticationManager authenticationManager() {
- DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(authService);
- authenticationProvider.setPasswordEncoder(passwordEncoder);
- return new ProviderManager(authenticationProvider);
- }
- @Bean
- public PasswordEncoder encoder() {
- return new Argon2PasswordEncoder(10, 50, 100, 1024, 20);
- }
- }
- // File - AuthService.java
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.core.userdetails.UserDetailsService;
- import org.springframework.stereotype.Service;
- import com.ramyak.springsecuritywithjwt.dto.UserDTO;
- import jakarta.servlet.http.HttpServletRequest;
- @Service
- public interface AuthService extends UserDetailsService {
- public UserDTO RegisterNewUser(UserDTO userDTO, String requestURL);
- public String loginUserByEmail(String email, HttpServletRequest httpServletRequest);
- public UserDetails loginUserByUsername(String username, HttpServletRequest httpServletRequest);
- }
- // File - AuthServiceImpl.java
- @Component
- public class AuthServiceImpl implements AuthService {
- @Autowired
- private AuthRepository authRepository;
- // Here is where I am facing problem, my authManager is calling this method, which I have also confirmed with the debugger. No surprises here, since its in the architecture of spring to call it, but what do I do if email comes here?
- @Override
- public UserDetails loadUserByUsername(String username) {
- System.out.println("Inside loadUserByUsername"); /// This gets printed out to console
- Optional<AppUser> u = authRepository.findByUsername(username);
- return null;
- }
- @Override
- public UserDTO RegisterNewUser(UserDTO userDTO, String requestURL) {
- Optional<AppUser> u = authRepository.findByUsername(userDTO.getUsername());
- if (u.isEmpty()) {
- AppUser u1 = new AppUser();
- u1.setPassword(new Argon2PasswordEncoder(10, 50, 100, 1024, 20).encode(userDTO.getPassword()));
- authRepository.save(u1);
- u1.setEmail(userDTO.getEmail());
- u1.setUsername(userDTO.getUsername());
- u1.setRole(userDTO.getRole());
- u = Optional.of(authRepository.save(u1));
- return UserDTO.convertEntitytoDTO(u.get());
- } else {
- System.out.println("User already exists");
- return UserDTO.convertEntitytoDTO(new AppUser(null, null, null, null, null));
- }
- }
- @Override
- public String loginUserByEmail(String email, HttpServletRequest httpServletRequest) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public UserDetails loginUserByUsername(String username, HttpServletRequest httpServletRequest) throws UsernameNotFoundException {
- System.out.println(new Argon2PasswordEncoder(10, 50, 100, 1024, 20).toString());
- Optional<AppUser> oau = authRepository.findByUsername(username);
- UserDetails u = User.withUsername(oau.get().getUsername()).password((oau.get().getPassword())).roles(oau.get().getRole()).build();
- return u;
- }
- }
- // File - AuthController.java
- @RestController
- @RequestMapping(path = "/auth")
- public class AuthenticationController {
- @Autowired
- private AuthService authService;
- @Autowired
- private AuthenticationManager authenticationManager;
- @PostMapping("/register")
- public ResponseEntity<UserDTO> registerNewUser(@RequestBody UserDTO userDTO, HttpServletRequest httpServletRequest) {
- UserDTO registeredUserDto = authService.RegisterNewUser(userDTO, httpServletRequest.getRequestURL().toString());
- return new ResponseEntity<UserDTO>(registeredUserDto, HttpStatus.OK);
- }
- @PostMapping("/login/username")
- public ResponseEntity<?> loginUserByUsername(@RequestBody LoginRequestDTO loginRequestDTO, HttpServletRequest httpServletRequest) throws UsernameNotFoundException {
- UserDetails result = authService.loginUserByUsername(loginRequestDTO.getUsername(), httpServletRequest);
- if (result != null) {
- UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(result, result.getPassword());
- authenticationManager.authenticate(upat); // Error occurs here
- }
- return null;
- }
- @PostMapping("/login/email")
- public ResponseEntity<?> loginUserByEMail(HttpServletResponse httpServletResponse) {
- return null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment