Authentication & Security Module
The SREDSimplify backend employs a stateless, token-based authentication architecture utilizing JWT (JSON Web Tokens) and Spring Security.
1. Core Authentication Flows
The system supports multiple authentication vectors:
- Email & Password: Standard registration with BCrypt password hashing.
- Google OAuth 2.0: Secure third-party login via ID Token validation.
- Invitation Codes: Optional gating for enterprise onboarding.
Sequence Diagram: Registration & Login
mermaid
sequenceDiagram
participant Client
participant AuthController
participant AuthServiceImpl
participant PostgreSQL
participant Redis
participant EmailQueue
%% Registration Flow
Note over Client,EmailQueue: Flow 1: Account Registration
Client->>AuthController: POST /api/v1/auth/register
AuthController->>AuthServiceImpl: register(email, password)
AuthServiceImpl->>PostgreSQL: Verify email uniqueness
AuthServiceImpl->>PostgreSQL: Save User & UserIdentity (BCrypt)
AuthServiceImpl->>Redis: SET verification_token (24h TTL)
AuthServiceImpl->>EmailQueue: XADD sred:email:send (Welcome + Verify Link)
AuthServiceImpl-->>Client: 201 Created (Proceeds to Auto-login)
%% Login Flow
Note over Client,PostgreSQL: Flow 2: Email Login
Client->>AuthController: POST /api/v1/auth/login
AuthController->>AuthServiceImpl: login(email, password)
AuthServiceImpl->>PostgreSQL: Authenticate (Verify BCrypt hash)
AuthServiceImpl->>AuthServiceImpl: Generate Access Token (15m)
AuthServiceImpl->>AuthServiceImpl: Generate Refresh Token (7d)
AuthServiceImpl-->>Client: 200 OK {accessToken, refreshToken}2. Spring Security Filter Chain
Security is enforced via the JwtAuthenticationFilter, which runs on every incoming request.
Token Extraction
The filter inspects the standard Authorization header:
java
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
// Valid Bearer Token found
}Context Population
If the token's signature is valid and it hasn't expired, the filter:
- Extracts the
userId. - Loads user authorities (Roles:
USER,ADMIN). - Populates the
SecurityContextHolder, allowing downstream Controllers to use@AuthenticationPrincipal.
3. Secure Token Revocation (Logout)
Because JWTs are stateless, they cannot be conventionally "invalidated" before expiration. We handle secure logouts using a hybrid approach:
- The Refresh Token is deleted from the client and invalidated in Redis.
- The Access Token (which has a short lifespan of 15 minutes) is discarded by the frontend.
- For critical security events (e.g., password change), the
jwt_secretor a user-specific token version is rotated in the database.