Skip to main content
Version: Next

User Management Design

Document Type: Domain Design (Tier 2) Domain: USERMGMT Domain Character: Stateful SRS Reference: user-management.md Status: Draft Last Updated: 2026-01-25


1. Overview

1.1 Purpose

The User Management subsystem provides complete user lifecycle management including account administration, authentication, session control, and role-based access enforcement. It is the identity backbone of the system, controlling who can access the application and what actions they can perform.

This domain is characterized by:

  • Stateful user lifecycle with distinct states (active, blocked, pending email verification)
  • Hybrid authentication via AWS Cognito (native credentials or federated SAML)
  • Session management with single-device enforcement and inactivity timeout
  • Five-tier role hierarchy (Junior, Senior, Client-Admin, Manager, Super Admin)
  • Multi-site access control for Manager and Super Admin roles
  • Audit trail integration for all security-relevant actions

1.2 Requirements Covered

REQ IDTitleCategory
REQ-USERMGMT-001Display User AccountsAdministration
REQ-USERMGMT-002Modify User RoleAdministration
REQ-USERMGMT-003Reset User PasswordAdministration
REQ-USERMGMT-004Configure User MFAAdministration
REQ-USERMGMT-005Request Email VerificationAdministration
REQ-USERMGMT-006Control User Account StatusAdministration
REQ-USERMGMT-007Delete User AccountAdministration
REQ-USERMGMT-008Create User AccountAdministration
REQ-USERMGMT-009Authenticate UsersAuthentication
REQ-USERMGMT-010Verify Email on First LoginAuthentication
REQ-USERMGMT-011Manage User SessionsSession
REQ-USERMGMT-012Enforce Access Control PoliciesAccess Control
REQ-USERMGMT-013Enforce Role-Based Access ControlAccess Control
REQ-USERMGMT-014Provide Multi-Site Data AccessAccess Control
REQ-USERMGMT-015Enforce Authentication Security PoliciesSecurity
REQ-USERMGMT-016Ensure System Readiness Before LoginSystem

1.3 Constraints

Tier 2 Constraint: This document describes ownership, patterns, and design rationale. Authentication architecture details are in SDS: Security Architecture. It does not duplicate Cognito configuration or password policies documented in the SRS acceptance criteria.

1.4 Dependencies

DirectionDomain/ComponentPurpose
Provides toAll domainsAuthenticated user context via middleware
AUDITUser lifecycle events
Multi-site screensManager multi-site filtering
ConsumesAWS CognitoIdentity management, credential verification
AWS SESEmail notifications and verification
DynamoDBSession storage (production)

2. Component Architecture

2.1 Component Diagram

2.2 Component Responsibilities

ComponentTypeResponsibilityREQ Trace
LoginControllerControllerNative login flow (username/password)REQ-USERMGMT-009, 011
SamlLoginControllerControllerFederated SAML SSO via CognitoREQ-USERMGMT-009
MfaControllerControllerMFA setup and TOTP verificationREQ-USERMGMT-004, 009
ChangePasswordControllerControllerMandatory password change flowREQ-USERMGMT-003, 009
ResetPasswordControllerControllerForgot password flowREQ-USERMGMT-003
UsersControllerControllerUser CRUD operationsREQ-USERMGMT-001, 002, 007, 008
BlockedUsersControllerControllerUser enable/disable operationsREQ-USERMGMT-006
HandleAuthenticatedTraitShared auth logic (MFA challenge, session, access control)REQ-USERMGMT-009, 011, 012
CognitoAuthenticatorServiceCognito adminInitiateAuth wrapperREQ-USERMGMT-009
CognitoUserManagerServiceCognito user lifecycle operationsREQ-USERMGMT-003-008
StoreUserActionActionCreate user with Cognito syncREQ-USERMGMT-008
UpdateUserTypeActionActionUpdate user role with validationREQ-USERMGMT-002
BlockUserActionActionDisable user and revoke sessionsREQ-USERMGMT-006
UnblockUserActionActionEnable previously disabled userREQ-USERMGMT-006

2.3 Architectural Patterns

Pattern: Cognito-Synchronized State

All user state changes are synchronized to AWS Cognito:

Local Operation → Database Update → Cognito API Call → Audit Event

This ensures identity state consistency between local database and identity provider.

Pattern: Trait-Based Controller Composition

Authentication controllers share common logic via the HandleAuthenticated trait, reducing duplication while allowing controller-specific customization.

Pattern: Action-Based Business Logic

Business logic is encapsulated in Action classes, keeping controllers thin and logic testable:

// Controller delegates to action
$user = $storeUser(auth()->user(), $request->getStoreUserData());

3. Data Design

3.1 Entity Ownership

This domain owns the following entities:

EntityTablePurposeKey Relationships
UserusersUser account data-> sites (visible_sites), -> logged_in_site
UserVisibleSiteuser_visible_sitesSite access mapping-> user, -> site

3.2 Entity Relationship Overview

3.3 User Type Enumeration

ValueNameDescription
1JUNIORBase role with Run Files, Reports, Audits, Upload access
2SENIORJunior + Westgard settings management
3CLIENT_ADMINUser Management and Audits only
4SUPER_ADMINFull system access
5MANAGERMulti-site read-only access

3.4 Role Permission Matrix

PermissionJuniorSeniorClient-AdminManagerSuper Admin
View Run FilesYesYesNoReadYes
View ReportsYesYesNoReadYes
View AuditsYesYesYesReadYes
Upload RunsYesYesNoNoYes
Westgard SettingsNoYesNoNoYes
User ManagementNoNoYes*NoYes
Multi-Site AccessNoNoNoYesYes
Create Comments/AlertsYesYesNoYesYes
Modify ResultsYesYesNoNoYes

*Client-Admin cannot modify Super Admin accounts.


4. Interface Design

4.1 APIs Provided

EndpointMethodPurposeREQ Trace
/loginPOSTNative authenticationREQ-USERMGMT-009
/login/samlGETInitiate SAML SSOREQ-USERMGMT-009
/logoutPOSTSession terminationREQ-USERMGMT-011
/api/usersGETList users with filtersREQ-USERMGMT-001
/api/usersPOSTCreate user accountREQ-USERMGMT-008
/api/users/{id}PUTUpdate user attributesREQ-USERMGMT-002
/api/users/{id}DELETEDelete disabled userREQ-USERMGMT-007
/api/blocked-usersPOSTDisable user accountREQ-USERMGMT-006
/api/blocked-users/{id}DELETEEnable user accountREQ-USERMGMT-006
/change-passwordGET/POSTMandatory password changeREQ-USERMGMT-003, 009
/mfa-setupGETMFA setup screenREQ-USERMGMT-004
/verify-mfaPOSTVerify TOTP codeREQ-USERMGMT-004, 009

4.2 APIs Consumed

ServicePurposeREQ Trace
AWS CognitoIdentity management, credential verificationREQ-USERMGMT-003-009
AWS SESEmail verification, notificationsREQ-USERMGMT-005, 008

4.3 Events Published

EventPayloadPurposeListener
UserLoggedInuser_id, timestampAudit trailLogIntoDatabase
UserLoggedOutuser_id, timestampAudit trailLogIntoDatabase
UserAccountCreateduser_id, creator_idAudit trailLogIntoDatabase
UserAccountDeleteduser_id, deleter_idAudit trailLogIntoDatabase
UserAccountDisableduser_id, modifier_idAudit + real-time logoutLogIntoDatabase, BroadcastDisable
UserAccountEnableduser_id, modifier_idAudit trailLogIntoDatabase
UserAssociatedWithRoleuser_id, old_role, new_roleAudit trailLogIntoDatabase
PasswordChangeduser_id, timestampAudit trailLogIntoDatabase

5. Behavioral Design

5.1 User Lifecycle State Machine

5.2 Authentication Flow

Algorithm: Authenticate User

Inputs:
- credentials: username/password OR SAML assertion
- auth_type: "native" | "federated"

Outputs:
- result: AuthResult (success with session, or challenge required)

Assumptions:
- AWS Cognito is accessible
- User pool is configured

Steps:
1. If auth_type == "native":
a. Call CognitoAuthenticator.authenticate(credentials)
b. If PASSWORD_CHANGE challenge: redirect to change-password
c. If MFA_SETUP challenge: redirect to mfa-setup with secret
d. If SOFTWARE_TOKEN_MFA challenge: redirect to mfa-verify
e. If success: proceed to step 3

2. If auth_type == "federated":
a. Redirect to Cognito hosted UI
b. Cognito returns access_token via callback
c. Proceed to step 3

3. Fetch Cognito user attributes using access_token
4. Validate access control:
a. If multi-site enabled and no valid visible sites: reject
b. If site requires Cognito group and user lacks group: reject
5. Create or update local user (UpdateOrCreateLocalUser)
6. Mark email as verified in Cognito
7. Login to Laravel session (auth()->login)
8. Terminate other sessions (logoutOtherDevices)
9. Emit UserLoggedIn event
10. Redirect to application

Notes:
- SAML users are auto-provisioned with Senior role
- Session termination enforces single-device policy

5.3 User Creation Flow

Algorithm: Create User Account

Inputs:
- actor: Authenticated admin user
- data: StoreUserData (username, email, role, visible_sites)

Outputs:
- user: Created User entity

Assumptions:
- Actor has permission to create users
- Email and display name are unique

Steps:
1. Begin database transaction
2. Create User record:
- username (lowercased)
- email
- user_type (defaults to JUNIOR)
- display_name
- cognito_group
3. Sync visible sites relationship
4. Call CognitoUserManager.createCognitoUser(user)
5. Commit transaction
6. Emit UserAccountCreated event
7. Emit UserAssociatedWithRole event
8. Return created user

Notes:
- On Cognito failure, transaction rolls back
- Cognito sends password setup email to user

5.4 Account Disable Flow

Algorithm: Disable User Account

Inputs:
- user: User to disable
- actor: Authenticated admin user

Outputs:
- user: Disabled User entity

Assumptions:
- Actor has permission to disable users
- User is not currently online (unless force_block)

Steps:
1. Set user.blocked = true
2. Revoke all user tokens (user.tokens.each.revoke())
3. Emit UserAccountDisabled event
4. Call CognitoUserManager.disableCognitoUser(user)
5. Return disabled user

Notes:
- Disabled users cannot authenticate
- Active sessions are terminated via token revocation
- Cognito disable prevents federated login

5.5 MFA Enrollment Flow

5.6 Role Assignment Logic

Algorithm: Update User Role

Inputs:
- actor: Admin user performing change
- user: Target user
- new_role: Role to assign

Outputs:
- void (updates user in place)

Assumptions:
- Actor has permission based on ALLOWED_TYPES_FOR_TYPE matrix

Steps:
1. Validate actor can assign new_role:
- JUNIOR can only assign JUNIOR
- SENIOR can only assign SENIOR
- CLIENT_ADMIN can assign MANAGER, CLIENT_ADMIN, SENIOR, JUNIOR
- MANAGER can assign MANAGER, CLIENT_ADMIN, SENIOR, JUNIOR
- SUPER_ADMIN can assign any role
- No one can assign SUPER_ADMIN except SUPER_ADMIN
2. If validation fails: throw ValidationException
3. Store old role for audit
4. Update user.user_type = new_role
5. Call CognitoUserManager.updateCognitoUserAttributes(user)
6. If role changed: emit RoleChangedForUser event

Notes:
- CLIENT_ADMIN cannot modify SUPER_ADMIN accounts
- Role changes are synchronized to Cognito custom:UserGroup attribute

5.7 Password Policy Decision Table

ConditionPassword ExpiryHistory CheckComplexity CheckAction
New accountN/AN/AYesCognito enforces on creation
Admin resetN/AN/AYesForce change on next login
Self-changeReset timerYes (5 previous)YesAccept if valid
Expired (90 days)YesN/AN/AForce change on login
Reused passwordN/AFailN/AReject with error

Precedence: Complexity check always runs. History check only on self-change. Default: If no condition matches, proceed with normal authentication.


6. Error Handling

ConditionDetectionResponseUser Impact
Invalid credentialsCognito AuthenticationExceptionReturn to login with error"Authentication error" message
Account disabledCognito UserDisabledExceptionReturn to login with errorCannot login
Account locked (5 attempts)Cognito NotAuthorizedExceptionReturn to login with errorMust contact admin
Invalid MFA codeCognito CodeMismatchExceptionReturn to MFA screenCan retry
Expired MFA sessionCognito ExpiredCodeExceptionReturn to loginMust start over
No valid visible sitesgetCognitoError checkReturn to login with error"No valid visible sites"
Invalid Cognito groupgetCognitoError checkReturn to login with error"Invalid user group"
Delete enabled userController checkHTTP 403 ForbiddenMust disable first
Concurrent modificationDatabase constraintHTTP 409 ConflictRefresh and retry

7. Configuration

SettingLocationDefaultEffectREQ Trace
session_inactivity_timeout_minutesclient_configurations30Inactivity timeoutREQ-USERMGMT-011
prevent_native_loginconfig/auth.phpfalseHide native login formREQ-USERMGMT-009
require_cognito_groupclient_configurationsfalseRequire Cognito groupREQ-USERMGMT-012
block_unauthorized_ipclient_configurationsfalseEnable IP whitelistREQ-USERMGMT-012
password_expiry_daysCognito config90Days until password expiresREQ-USERMGMT-015
password_history_countCognito config5Previous passwords blockedREQ-USERMGMT-015
max_login_attemptsCognito config5Lockout thresholdREQ-USERMGMT-015
use_multiple_sitesfeaturesvariesEnable multi-site modeREQ-USERMGMT-014

See Configuration Reference for full list.


8. Implementation Mapping

8.1 Code Locations

ComponentTypePath
LoginControllerControllerapp/Http/Controllers/Auth/LoginController.php
SamlLoginControllerControllerapp/Http/Controllers/Auth/SamlLoginController.php
MfaControllerControllerapp/Http/Controllers/Auth/MfaController.php
ChangePasswordControllerControllerapp/Http/Controllers/Auth/ChangePasswordController.php
ResetPasswordControllerControllerapp/Http/Controllers/Auth/ResetPasswordController.php
UsersControllerControllerapp/Http/Controllers/UsersController.php
BlockedUsersControllerControllerapp/Http/Controllers/BlockedUsersController.php
HandleAuthenticatedTraitapp/Http/Controllers/Auth/HandleAuthenticated.php
CognitoAuthenticatorServiceapp/Support/CognitoAuthenticator.php
CognitoUserManagerServiceapp/CognitoUserManager.php
UserModelapp/User.php
StoreUserActionActionapp/Actions/UserManagement/StoreUserAction.php
UpdateUserTypeActionActionapp/Actions/UserManagement/UpdateUserTypeAction.php
BlockUserActionActionapp/Actions/Users/BlockUserAction.php
UnblockUserActionActionapp/Actions/Users/UnblockUserAction.php
UpdateUserActionActionapp/Actions/Users/UpdateUserAction.php

8.2 Requirement Traceability

REQ IDDesign SectionPrimary Code
REQ-USERMGMT-001SS4.1UsersController.index, ListUsersAction
REQ-USERMGMT-002SS5.6UpdateUserTypeAction
REQ-USERMGMT-003SS5.2ChangePasswordController, CognitoUserManager.changeCognitoUserPassword
REQ-USERMGMT-004SS5.5MfaController, User.enableMfa, CognitoUserManager.enableMfaOfCognitoUser
REQ-USERMGMT-005SS5.3CognitoUserManager.makeEmailAsVerifiedOfCognitoUser
REQ-USERMGMT-006SS5.1, SS5.4BlockUserAction, UnblockUserAction, CognitoUserManager.disableCognitoUser
REQ-USERMGMT-007SS5.1UsersController.destroy, User.remove
REQ-USERMGMT-008SS5.3StoreUserAction, CognitoUserManager.createCognitoUser
REQ-USERMGMT-009SS5.2LoginController, SamlLoginController, HandleAuthenticated
REQ-USERMGMT-010SS5.2HandleAuthenticated.authenticated
REQ-USERMGMT-011SS5.2HandleAuthenticated.logoutOtherDevices, LoginController.logout
REQ-USERMGMT-012SS5.2HandleAuthenticated.getCognitoError
REQ-USERMGMT-013SS3.4UserType middleware, User.ALLOWED_TYPES_FOR_TYPE
REQ-USERMGMT-014SS3.4User.visibleSites, multi-site filtering
REQ-USERMGMT-015SS5.7Cognito password policies, audit events
REQ-USERMGMT-016-Frontend health check (not backend implementation)

9. Design Decisions

DecisionRationaleAlternatives Considered
AWS Cognito for identityManaged service reduces security burden, supports SAMLSelf-hosted (rejected: maintenance overhead)
Cognito tokens not persistedReduces attack surface, simplifies token managementStore tokens (rejected: complexity, rotation burden)
Single-device enforcementSecurity requirement, prevents session sharingAllow concurrent (rejected: security risk)
Soft-delete for usersPreserve audit history, allow recoveryHard delete (rejected: loses history)
Role hierarchy in codeSimple matrix, easy to understandDatabase-driven (rejected: over-engineering)
Synchronous Cognito syncConsistency, simpler error handlingAsync queue (rejected: eventual consistency issues)
Trait-based controller compositionCode reuse without inheritance hierarchyBase class (rejected: inflexible), duplication (rejected: maintenance)

DocumentRelevant Sections
SRS: user-management.mdRequirements source
SDS: Security ArchitectureAuthentication architecture, token design, authorization model
SDS: AUDIT DomainAudit event storage and query
SDS: Configuration ReferenceUser management configuration options