Careeroza
Registering Users
The Registration Endpoint
public record RegisterRequest(
@Email @NotBlank String email,
@NotBlank @Size(min = 8, max = 64) String password) {}
public record UserResponse(Long id, String email, String role) {}
@Service
public class RegistrationService {
private final UserRepository users;
private final PasswordEncoder passwordEncoder;
public RegistrationService(UserRepository users, PasswordEncoder passwordEncoder) {
this.users = users;
this.passwordEncoder = passwordEncoder;
}
@Transactional
public UserResponse register(RegisterRequest req) {
String email = req.email().toLowerCase();
if (users.existsByEmail(email)) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "Email already registered");
}
User saved = users.save(new User(email, passwordEncoder.encode(req.password()), "CUSTOMER"));
return new UserResponse(saved.getId(), saved.getEmail(), saved.getRole());
}
}
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final RegistrationService registrationService;
public AuthController(RegistrationService registrationService) {
this.registrationService = registrationService;
}
@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public UserResponse register(@Valid @RequestBody RegisterRequest req) {
return registrationService.register(req);
}
}- The role is set by the server (
CUSTOMER), never taken from the request body. Otherwise anyone could register as ADMIN. - The response never contains the password or its hash.
/api/auth/registermust bepermitAll()in the security config.
Register, Then Log In
Example
Sign up, try again with the same email, then use the new account:
curl -i -X POST localhost:8080/api/auth/register -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Neha@2024secure"}'
curl -i -X POST localhost:8080/api/auth/register -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"another-pass"}'
curl -i -u [email protected]:Neha@2024secure localhost:8080/api/cartExample output
HTTP/1.1 201
Content-Type: application/json
{"id":42,"email":"[email protected]","role":"CUSTOMER"}
HTTP/1.1 409
Content-Type: application/problem+json
{"type":"about:blank","title":"Conflict","status":409,"detail":"Email already registered","instance":"/api/auth/register"}
HTTP/1.1 200
Content-Type: application/json
{"items":[],"total":0.0}What Is in the Database
Stored Row
SELECT id, email, password_hash, role FROM users WHERE email = '[email protected]';Example output
id | email | password_hash | role ----+----------------+--------------------------------------------------------------+---------- 42 | [email protected] | $2a$12$Qm9yN3VhY2hTYWx0VmFsdWUu8yHk3f1QmZ0uZc6rT0qJ2a1Xv9bKe | CUSTOMER
Exercise: Add a rule to RegistrationService that rejects passwords containing the user's email name (the part before @), ignoring case.
Show answer
String name = email.substring(0, email.indexOf('@'));
if (req.password().toLowerCase().contains(name)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Password must not contain your email name");
}