From 835ad93bac188174222ca0efc15542e3ea579b7d Mon Sep 17 00:00:00 2001 From: Romain Mallard Date: Tue, 16 Jun 2026 13:53:58 +0200 Subject: [PATCH] FEAT: Auth useing encrypted credentials in DB --- data/hotel.sqlite | Bin 4927488 -> 4927488 bytes .../hotel/config/DatabaseSeeder.java | 27 ++++++++++ .../hotel/config/SecurityConfig.java | 27 ++++++++++ .../hotel/controller/AuthController.java | 44 ++++++++-------- .../com/mallardromain/hotel/model/User.java | 49 ++++++++++++++++++ .../hotel/repository/UserRepository.java | 14 +++++ .../hotel/service/UserService.java | 48 +++++++++++++++++ src/main/resources/application.properties | 1 + 8 files changed, 188 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/mallardromain/hotel/config/DatabaseSeeder.java create mode 100644 src/main/java/com/mallardromain/hotel/model/User.java create mode 100644 src/main/java/com/mallardromain/hotel/repository/UserRepository.java create mode 100644 src/main/java/com/mallardromain/hotel/service/UserService.java diff --git a/data/hotel.sqlite b/data/hotel.sqlite index edcf485608dd5eaf6515153d7dc1817baf9f2da1..9c93398c32e321b4b01da87e75a53afeecc76651 100644 GIT binary patch delta 1678 zcmeIxOHUJF6b9gFr5Ax(E9!vtGHMa3we+slDwJM;0YXC?V%ZIJY#U0QOiL9vfQ#3} zjS^z`1+H{QB5qCm0dM#P{sXt}^n;ag=ejPQvp6|IS}{QezPcF4oS2S@f_7K``b$T@b{C$4678Nw1IZe0Xo6cU@zDQ_Jc0) z4Cn^Wf*$Z3H~^jpFMt<885{(Mz)PSPybN9euY%V=1-uU40B?dma2UJ=j)0?}AG{6T z0R!M&FbIx;AutR^z$h34<6r{32i^yh-~;d>m;xVxk3VzVVOT!Cc1}zPX<<^x2w5Q~ RPN+YB{00k7bsYcz delta 905 zcmd^-J!}$j7{>3o1FjUPtp!0^i}i~hNsjepe0OV$ z*RGp}nKPynrcp4n1+!k=%xbqCe|+j+`_}7jSdsL){o{#m)EfBawL9~hLasJn$O+Zd z>lb?BydzwuZtM4bai=U-deOOF)aXU?juR5=Xa2t0xlgw{mEjTVU01WBotv(QhSLm~ z`lHyNX0tIHQIpHB=B&oqq&?Ir|FXVbO0{Rcls_n{c(jz`JB3@0Xg}X5U-dp9D1$Cg z0aefqdO$CzfqkG4><9f|01Scy;1+NY90Iq3!(a#ugWJFe7zMY3F>nMN1>@ijFahe| zPH-2v8{7jX!7*?zxDQN$`@u9g4o-lRpaD*SCYS-UU=GZK)8Gs^3l_iwU=chB9(v0; j?;Uw{Su2$UhXqFjM+L_O#|0+@Ck3Yjr`uYoyz%`v+nhwc diff --git a/src/main/java/com/mallardromain/hotel/config/DatabaseSeeder.java b/src/main/java/com/mallardromain/hotel/config/DatabaseSeeder.java new file mode 100644 index 0000000..a0ec5c1 --- /dev/null +++ b/src/main/java/com/mallardromain/hotel/config/DatabaseSeeder.java @@ -0,0 +1,27 @@ +package com.mallardromain.hotel.config; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.password.PasswordEncoder; + +import com.mallardromain.hotel.model.User; +import com.mallardromain.hotel.repository.UserRepository; + +import io.jsonwebtoken.security.Password; + +@Configuration +public class DatabaseSeeder { + + @Bean + public CommandLineRunner seedDatabase(UserRepository userRepository, PasswordEncoder passwordEncoder) { + return args -> { + if (userRepository.count() == 0) { + User testUser1 = new User("test1", passwordEncoder.encode("password1")); + User testUser2 = new User("test2", passwordEncoder.encode("password2")); + + userRepository.save(testUser1); + userRepository.save(testUser2); + } + }; + } +} diff --git a/src/main/java/com/mallardromain/hotel/config/SecurityConfig.java b/src/main/java/com/mallardromain/hotel/config/SecurityConfig.java index 14877df..73a264a 100644 --- a/src/main/java/com/mallardromain/hotel/config/SecurityConfig.java +++ b/src/main/java/com/mallardromain/hotel/config/SecurityConfig.java @@ -2,8 +2,15 @@ package com.mallardromain.hotel.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @@ -39,4 +46,24 @@ public class SecurityConfig { return http.build(); } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public AuthenticationManager authenticationManager( + AuthenticationConfiguration config, + UserDetailsService userDetailsService, + PasswordEncoder passwordEncoder + ) throws Exception { + + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(userDetailsService); + authProvider.setPasswordEncoder(passwordEncoder); + + return new ProviderManager(authProvider); + } + + } diff --git a/src/main/java/com/mallardromain/hotel/controller/AuthController.java b/src/main/java/com/mallardromain/hotel/controller/AuthController.java index 07db939..0837805 100644 --- a/src/main/java/com/mallardromain/hotel/controller/AuthController.java +++ b/src/main/java/com/mallardromain/hotel/controller/AuthController.java @@ -1,6 +1,11 @@ package com.mallardromain.hotel.controller; +import org.springframework.security.core.AuthenticationException; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -15,39 +20,34 @@ import com.mallardromain.hotel.service.JWTService; public class AuthController { private final JWTService jwtService; + private final AuthenticationManager authenticationManager; - public AuthController(JWTService jwtService){ + public AuthController(JWTService jwtService, AuthenticationManager authenticationManager){ this.jwtService = jwtService; + this.authenticationManager = authenticationManager; } @PostMapping("/login") public ResponseEntity login( @RequestBody LoginRequest request ){ - //temps test1/2 - if ( - request.getUsername().equals("test1") - && - request.getPassword().equals("password1") - ) { - String token = jwtService - .generateToken(request.getUsername()); + try{ + /// NEW SECURE TOKEN LOGIN + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + request.getUsername(), + request.getPassword() + ) + ); + + String token = jwtService.generateToken(authentication.getName()); return ResponseEntity.ok(token); + + } catch (AuthenticationException e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid username/password"); } - - if ( - request.getUsername().equals("test2") - && - request.getPassword().equals("password2") - ) { - String token = jwtService - .generateToken(request.getUsername()); - - return ResponseEntity.ok(token); - } - - return ResponseEntity.status(401).body("Invalid username/password"); + } diff --git a/src/main/java/com/mallardromain/hotel/model/User.java b/src/main/java/com/mallardromain/hotel/model/User.java new file mode 100644 index 0000000..da36a7e --- /dev/null +++ b/src/main/java/com/mallardromain/hotel/model/User.java @@ -0,0 +1,49 @@ +package com.mallardromain.hotel.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + private String username; + + private String password; + + public User(){ + + } + + public User(String username, String password ){ + this.username = username; + this.password = password; + } + + public Integer getId(){ + return id; + } + + public void setId(Integer id){ + this.id = id; + } + + public String getUsername(){ + return username; + } + + public void setUsername(String username){ + this.username = username; + } + + public String getPassword(){ + return password; + } + + public void setPassword(String password){ + this.password = password; + } +} diff --git a/src/main/java/com/mallardromain/hotel/repository/UserRepository.java b/src/main/java/com/mallardromain/hotel/repository/UserRepository.java new file mode 100644 index 0000000..f897e10 --- /dev/null +++ b/src/main/java/com/mallardromain/hotel/repository/UserRepository.java @@ -0,0 +1,14 @@ +package com.mallardromain.hotel.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.mallardromain.hotel.model.User; + +public interface UserRepository extends JpaRepository { + + Optional findByUsername(String username); + + +} diff --git a/src/main/java/com/mallardromain/hotel/service/UserService.java b/src/main/java/com/mallardromain/hotel/service/UserService.java new file mode 100644 index 0000000..8b7b153 --- /dev/null +++ b/src/main/java/com/mallardromain/hotel/service/UserService.java @@ -0,0 +1,48 @@ +package com.mallardromain.hotel.service; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import com.mallardromain.hotel.model.User; +import com.mallardromain.hotel.repository.UserRepository; + +import jakarta.persistence.*; + + +@Service +public class UserService implements UserDetailsService { + + private final PasswordEncoder passwordEncoder; + + private final UserRepository repo; + + public UserService(UserRepository repo, PasswordEncoder passwordEncoder){ + this.repo = repo; + this.passwordEncoder = passwordEncoder; + } + + public User registerNewUser(String username, String rawPassword) { + User newUser = new User(); + newUser.setUsername(username); + + String hashedPassword = passwordEncoder.encode(rawPassword); + newUser.setPassword(hashedPassword); + + return repo.save(newUser); + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return repo.findByUsername(username) + .map(user -> org.springframework.security.core.userdetails.User + .withUsername(user.getUsername()) + .password(user.getPassword()) + .authorities("USER") // Default role + .build() + ) + .orElseThrow(() -> new UsernameNotFoundException("User not found in DB")); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8a78733..1247654 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,6 +2,7 @@ spring.application.name=hotel spring.datasource.url=jdbc:sqlite:hotel/data/hotel.sqlite spring.datasource.driver-class-name=org.sqlite.JDBC +spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect