add argon2 hashing and salting of password

This commit is contained in:
Mika Bomm 2024-09-02 19:18:02 +02:00
parent 717c181b74
commit c87a166834
3 changed files with 49 additions and 25 deletions

View file

@ -20,6 +20,8 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.security:spring-security-crypto:6.3.3'
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

View file

@ -35,30 +35,13 @@ public class UserController {
@PostMapping
public User createUser(@RequestBody UserDTO userDTO) {
User user = new User();
user.setUsername(userDTO.getUsername());
user.setName(userDTO.getName());
user.setEmail(userDTO.getEmail());
user.setPasswordHash(userDTO.getPassword());
return userService.save(user);
return userService.save(userDTO);
}
// FIXME: Use DTO instead of entity
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable UUID id, @RequestBody User userDetails) {
Optional<User> user = userService.findById(id);
if (user.isPresent()) {
User updatedUser = user.get();
updatedUser.setUsername(userDetails.getUsername());
updatedUser.setName(userDetails.getName());
updatedUser.setEmail(userDetails.getEmail());
updatedUser.setPasswordHash(userDetails.getPasswordHash());
updatedUser.setPasswordSalt(userDetails.getPasswordSalt());
userService.save(updatedUser);
return ResponseEntity.ok(updatedUser);
} else {
return ResponseEntity.notFound().build();
}
public ResponseEntity<User> updateUser(@PathVariable UUID id, @RequestBody UserDTO userDTO) {
Optional<User> updatedUser = userService.update(id, userDTO);
return updatedUser.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")

View file

@ -1,8 +1,10 @@
package com.mixel.docusphere.service;
import com.mixel.docusphere.dto.UserDTO;
import com.mixel.docusphere.entity.User;
import com.mixel.docusphere.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.stereotype.Service;
import java.util.List;
@ -12,8 +14,16 @@ import java.util.UUID;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
private final UserRepository userRepository;
// init argon2
private final Argon2PasswordEncoder passwordEncoder;
// Constructor
public UserService(UserRepository userRepository) {
this.passwordEncoder = new Argon2PasswordEncoder(16, 32, 1, 4096, 3);
this.userRepository = userRepository;
}
public List<User> findAll() {
return userRepository.findAll();
@ -23,10 +33,39 @@ public class UserService {
return userRepository.findById(id);
}
public User save(User user) {
public User save(UserDTO userDTO) {
User user = new User();
user.setUsername(userDTO.getUsername());
user.setName(userDTO.getName());
user.setEmail(userDTO.getEmail());
isPasswordAlreadySet(userDTO, user);
return userRepository.save(user);
}
public Optional<User> update(UUID id, UserDTO userDTO){
Optional<User> userOptional = userRepository.findById(id);
if (userOptional.isPresent()) {
User user = userOptional.get();
user.setUsername(userDTO.getUsername());
user.setName(userDTO.getName());
user.setEmail(userDTO.getEmail());
isPasswordAlreadySet(userDTO, user);
return Optional.of(userRepository.save(user));
}
return Optional.empty();
}
private void isPasswordAlreadySet(UserDTO userDTO, User user) {
if (userDTO.getPassword() != null && !userDTO.getPassword().isEmpty()) {
final String salt = KeyGenerators.string().generateKey();
user.setPasswordSalt(salt);
final String saltedPassword = salt + userDTO.getPassword();
user.setPasswordHash(passwordEncoder.encode(saltedPassword));
}
}
public void deleteById(UUID id) {
userRepository.deleteById(id);
}