Registration - Aligheri/jwt-owasp-based-starter GitHub Wiki
Overview
This documentation covers the user registration functionality in your Spring Boot application, which provides a flexible and extensible registration system through abstract base classes and interfaces.
Architecture
The registration system follows a template method pattern with the following key components:
Core Interfaces and Classes
RegisterRequest
Interface
The base interface that defines the contract for registration requests:
public interface RegisterRequest {
String getEmail();
String getPassword();
String getUsername();
}
DefaultRegistrationRequest
Class
A default implementation of the RegisterRequest
interface:
@Getter
@Setter
@Data
@NoArgsConstructor
public class DefaultRegistrationRequest implements RegisterRequest {
private String username;
private String password;
private String email;
}
Abstract Registration Method
The base registration method that must be implemented by subclasses:
V registerUser(U registrationRequest);
@Override
public V registerUser(U registrationRequest) {
throw new UnsupportedOperationException("registerUser must be overridden in subclass");
}
Implementation Guide
Step 1: Implement the Registration Service
Override the registerUser
method in your authentication service:
@Override
public DefaultRegisterResponse registerUser(DefaultRegistrationRequest request) {
// Validate username uniqueness
if (userRepository.existsByUsername(request.getUsername())) {
return new DefaultRegisterResponse("Error: Username is already taken!");
}
// Validate email uniqueness
if (userRepository.existsByEmail(request.getEmail())) {
return new DefaultRegisterResponse("Error: Email is already in use!");
}
// Create new user entity
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(passwordEncoder.encode(request.getPassword()));
// Set user status
UserStatus userStatus = UserStatus.builder()
.user(user)
.enabled(true)
.accountLocked(false)
.build();
user.setUserStatus(userStatus);
userRepository.save(user);
// Handle account activation
String code = activationService.generateActivationCode(user.getEmail());
activationService.sendActivationEmail(user.getEmail(), code);
return new DefaultRegisterResponse("User registered successfully!");
}
Step 2: Create the REST Controller
Implement the registration endpoint:
@PostMapping("/register")
public ResponseEntity<DefaultRegisterResponse> registerUser(
@Valid @RequestBody DefaultRegistrationRequest defaultRegistrationRequest) {
logger.info("Attempting to register user: {}", defaultRegistrationRequest.getUsername());
try {
DefaultRegisterResponse defaultRegisterResponse =
authenticationService.registerUser(defaultRegistrationRequest);
logger.info("User registered successfully: {}", defaultRegistrationRequest.getUsername());
return ResponseEntity.ok(defaultRegisterResponse);
} catch (RegisterException e) {
return ResponseEntity.badRequest().body(new DefaultRegisterResponse(e.getMessage()));
}
}
Key Features
1. Data Validation
- Username Uniqueness: Checks if the username is already taken
- Email Uniqueness: Validates that the email address is not already registered
- Input Validation: Uses
@Valid
annotation for request body validation
2. Password Security
- Passwords are encoded using a
PasswordEncoder
before storage - Never store plain text passwords in the database
3. User Status Management
- Creates a
UserStatus
entity with default values:enabled
: trueaccountLocked
: false
4. Account Activation
The registration process includes email activation functionality through the ActivationService
:
- Generates a unique activation code for the user's email
- Sends an activation email to the registered email address
- For detailed information about the ActivationService, refer to: [ActivationService Documentation](https://github.com/Aligheri/jwt-owasp-based-starter/wiki/ActivationService-and-its-implementation)
5. Error Handling
- Handles duplicate username/email scenarios gracefully
- Uses custom
RegisterException
for error management - Returns appropriate HTTP status codes
6. Logging
- Comprehensive logging for registration attempts and outcomes
- Helps with debugging and monitoring
Response Format
The registration endpoint returns a DefaultRegisterResponse
object with:
- Success message for successful registrations
- Error message for failed registrations
Security Considerations
- Password Encoding: All passwords are encoded before database storage
- Input Validation: Request data is validated using Bean Validation annotations
- Duplicate Prevention: Prevents duplicate usernames and emails
- Account Activation: Email verification adds an additional security layer
Extension Points
The architecture allows for easy customization:
- Custom Registration Requests: Implement the
RegisterRequest
interface for additional fields - Custom Validation Logic: Override the
registerUser
method to add business-specific validation - Custom Response Types: Define custom response classes for different registration scenarios
Dependencies
Ensure you have the following dependencies in your project:
- Spring Boot Starter Web
- Spring Boot Starter Data JPA
- Spring Boot Starter Validation
- Spring Boot Starter Security (for password encoding)
- Your custom authentication starter package
Usage Example
POST /register
Content-Type: application/json
{
"username": "john_doe",
"email": "[email protected]",
"password": "securePassword123"
}
Success Response:
{
"message": "User registered successfully!"
}
Error Response:
{
"message": "Error: Username is already taken!"
}