When a user registers or logs in, the server generates a JWT token containing the user’s ID and username. The token is signed using HMAC-SHA with a secret key and includes an expiration timestamp.
public String register(RegisterUserRequest userRequest) { // ... validation logic ... User newUser = new User( username, encoder.encode(userRequest.getPassword()) ); userRepository.save(newUser); return JwtUtil.generateToken(newUser.getId(), newUser.getUsername());}public String login(LoginUserRequest loginRequest) { User user = userRepository.findByUsername(loginRequest.getUsername()) .orElseThrow(UsernameOrPasswordIncorrectException::new); if (!BCrypt.checkpw(loginRequest.getPassword(), user.getPassword())) throw new UsernameOrPasswordIncorrectException(); return JwtUtil.generateToken(user.getId(), user.getUsername());}
Tokens are valid for 30 days by default (JWT_EXPIRATION_MS = 1000 * 60 * 60 * 30)
User passwords are hashed using BCrypt before being stored in the database. BCrypt automatically handles salt generation and is resistant to rainbow table and brute-force attacks.
Registration
Login verification
User newUser = new User( username, encoder.encode(userRequest.getPassword()));
The encoder is Spring Security’s PasswordEncoder configured to use BCrypt.
if (!BCrypt.checkpw(loginRequest.getPassword(), user.getPassword())) throw new UsernameOrPasswordIncorrectException();
BCrypt’s checkpw method compares the plain text password with the stored hash.
Authentication settings are defined in Configuration.java:
Configuration.java
public class Configuration { // Password must be at least 6 characters public static final int MIN_PASSWORD_LENGTH = 6; // Username must be 2-8 characters public static final int MIN_USERNAME_LENGTH = 2; public static final int MAX_USERNAME_LENGTH = 8; // JWT secret (should be set via environment variable) public static final String JWT_SECRET = System.getenv("JWT_SECRET") == null ? "dGhpcy1wYXNzc3dvcmQtaXMtc3VwZXItZHVwZXItc2VjcmV0..." : System.getenv("JWT_SECRET"); // Token expires after 30 days public static final long JWT_EXPIRATION_MS = 1000 * 60 * 60 * 30;}
The JWT_SECRET should always be set via the JWT_SECRET environment variable in production. The default value is only for development.