MATIH Platform is in active MVP development. Documentation reflects current implementation status.
6. Identity & Access Management
Authentication
User Registration

User Registration

Production - POST /api/v1/auth/register

Self-service registration allows new users to create accounts on the MATIH platform. The registration flow creates a user in the default tenant, assigns the default user role, sends a verification email, and returns authentication tokens.


6.2.5Registration Flow

Client                  AuthController          AuthenticationService
  |                           |                          |
  |--- POST /auth/register -->|                          |
  |                           |--- register() ---------->|
  |                           |                          |--- Check email uniqueness
  |                           |                          |--- Validate password length
  |                           |                          |--- Create User entity
  |                           |                          |--- Assign "user" role
  |                           |                          |--- Send verification email
  |                           |                          |--- Generate tokens
  |<-- 200 (AuthResponse) ----|<-- AuthResponse ---------|

Request

curl -X POST http://localhost:8081/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "newuser@example.com",
    "password": "MySecureP@ss123",
    "firstName": "Alex",
    "lastName": "Johnson"
  }'

Request Schema

FieldTypeRequiredValidationDescription
emailStringYes@NotBlank, @Email, max 255User email address
passwordStringYes@NotBlank, 8-128 charsAccount password
firstNameStringNoMax 100 charsUser first name
lastNameStringNoMax 100 charsUser last name

Response (200 OK)

{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiJ9...",
  "tokenType": "Bearer",
  "expiresIn": 900,
  "user": {
    "id": 42,
    "email": "newuser@example.com",
    "firstName": "Alex",
    "lastName": "Johnson",
    "displayName": "Alex Johnson",
    "tenantId": "00000000-0000-0000-0000-000000000001",
    "roles": ["ROLE_USER"],
    "emailVerified": false
  }
}

Note that emailVerified is false immediately after registration. The user must complete email verification separately.


6.2.6Implementation Details

AuthenticationService.register()

@Transactional
public AuthResponse register(RegisterRequest request, String userAgent, String ipAddress) {
    // 1. Check if email already exists in default tenant
    if (userRepository.existsByTenantIdAndEmail(DEFAULT_TENANT_ID, request.getEmail())) {
        throw new BusinessException("An account with this email already exists");
    }
 
    // 2. Validate password strength
    if (request.getPassword() == null || request.getPassword().length() < 8) {
        throw new BusinessException("Password must be at least 8 characters");
    }
 
    // 3. Create the user entity
    User user = User.builder()
        .tenantId(DEFAULT_TENANT_ID)
        .email(request.getEmail())
        .passwordHash(passwordEncoder.encode(request.getPassword()))
        .firstName(request.getFirstName())
        .lastName(request.getLastName())
        .displayName(request.getFirstName() + " " + request.getLastName())
        .enabled(true)
        .mfaEnabled(false)
        .build();
 
    // 4. Assign default "user" role
    roleRepository.findByTenantIdAndName(DEFAULT_TENANT_ID, "user")
        .ifPresent(role -> user.getRoles().add(role));
 
    User savedUser = userRepository.save(user);
 
    // 5. Send verification email
    sendVerificationEmail(savedUser);
 
    // 6. Generate tokens and return
    UserDetails userDetails = userDetailsService.loadUserByUsername(savedUser.getEmail());
    String accessToken = jwtTokenProvider.generateAccessToken(userDetails);
    String refreshToken = jwtTokenProvider.generateRefreshToken(savedUser.getEmail());
    saveRefreshToken(savedUser, refreshToken, userAgent, ipAddress);
 
    return AuthResponse.builder()
        .accessToken(accessToken)
        .refreshToken(refreshToken)
        .tokenType("Bearer")
        .expiresIn(securityProperties.getJwt().getAccessTokenExpiration() / 1000)
        .user(buildUserInfo(savedUser))
        .build();
}

Key Behaviors

  • Default Tenant: Self-registration creates users in the default tenant (00000000-0000-0000-0000-000000000001). Admin-created users use the tenant specified in the X-Tenant-ID header via UserController.createUser().
  • Password Hashing: Passwords are hashed using Spring Security's PasswordEncoder (BCrypt) before storage. The plain-text password is never persisted.
  • Display Name: Automatically constructed from firstName + " " + lastName. If both are null, the @PrePersist hook falls back to the email address.
  • Role Assignment: The default user role is looked up from the database. If it does not exist (e.g., in a fresh database), the user is created without any roles.
  • Immediate Token Issuance: Unlike some systems that require email verification before login, MATIH issues tokens immediately after registration. The emailVerified flag in the token response allows the frontend to prompt for verification.

Error Codes

CodeHTTP StatusDescription
BUSINESS_RULE_VIOLATION400Email already exists or password too short
VALIDATION_ERROR400Missing required fields or invalid email format

Admin User Creation

Administrators can create users via the UserController endpoint, which offers more control:

curl -X POST http://localhost:8081/api/v1/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "email": "team.member@company.com",
    "password": "InitialP@ss123",
    "firstName": "Team",
    "lastName": "Member",
    "displayName": "Team Member",
    "phoneNumber": "+1234567890",
    "roleIds": [1, 3]
  }'

This endpoint requires ADMIN or PLATFORM_ADMIN role and allows specifying the target tenant and initial role assignments.