EP-001: Authentication & Access Control
Business Objective
Secure, role-based access is foundational to every hotel operation. Front desk agents, housekeeping staff, managers, and administrators all need different levels of access to the platform. A robust auth system protects guest PII (Aadhaar, passport data), financial data, and ensures audit compliance. Multi-factor authentication meets PCI-DSS and SOC 2 requirements.
Audience
- Primary: All staff (Front Desk Agent, Housekeeping Staff, F&B Staff, Manager, Admin)
- Secondary: Super Admin (SaaS platform), Third-party API consumers
Scope
In Scope
- User login (email/password) with JWT access + refresh tokens
- Multi-Factor Authentication (TOTP via authenticator app)
- Role-Based Access Control (9 roles with permissions)
- Password management (history, complexity, reset, force-change)
- SSO integration (OIDC/SAML for enterprise chains)
- Session management (concurrent sessions, forced logout)
- Brute-force protection (account lockout after N attempts)
- API key management for third-party integrations
- User CRUD (invite, activate, deactivate, delete)
- Profile management (name, avatar, preferences)
Out of Scope
- Biometric authentication (fingerprint, face ID) — deferred to mobile app phase
- Social login (Google, Facebook) — not applicable for staff portal
- Hardware security keys (FIDO2/WebAuthn) — future consideration
Current Implementation Status
- Backend: Auth service fully built with controllers, DTOs, guards, strategies. JWT + refresh token flow. MFA via otplib/TOTP. RBAC with 9 roles defined in Prisma enum (SUPER_ADMIN, ADMIN, MANAGER, FRONT_DESK, HOUSEKEEPING, FNB, ACCOUNTS, RESERVATIONS, STAFF). Password history (last 5). Brute-force detection. Billing controller. Session management.
- Dashboard: Login page with NextAuth v5 integration. User management pages in Settings. Role assignment. Password reset flow.
- Mobile: Token-based auth in React Native apps
- Tests: Auth guard tests, JWT strategy tests exist
Gap Analysis
- SSO (OIDC/SAML): Backend DTOs/controllers exist but no actual identity provider integration tested. Enterprise chains need this for SSO with their corporate directory.
- API Key Management: Schema and basic endpoints exist but no dashboard UI for third-party developers to manage keys.
- Audit Trail for Auth Events: Login/logout events logged but not surfaced in a dedicated security audit dashboard.
- Password Expiry Policy: Password history exists but no configurable expiry enforcement (e.g., force change every 90 days).
- IP Whitelisting: No support for restricting admin access to specific IP ranges — needed for enterprise security policies.
User Stories
| Story ID | Title | Priority | Points | Status | Sprint |
|---|---|---|---|---|---|
| US-001-001 | User Login with Email/Password | P0 | 3 | Built | 1 |
| US-001-002 | JWT Token Refresh | P0 | 3 | Built | 1 |
| US-001-003 | User Logout & Session Invalidation | P0 | 2 | Built | 1 |
| US-001-004 | MFA Setup (TOTP) | P0 | 5 | Built | 1 |
| US-001-005 | MFA Verification on Login | P0 | 3 | Built | 1 |
| US-001-006 | Role-Based Access Control (9 Roles) | P0 | 8 | Built | 1 |
| US-001-007 | Password Reset via Email | P0 | 3 | Built | 1 |
| US-001-008 | Force Password Change | P1 | 2 | Built | 1 |
| US-001-009 | Password History Enforcement | P1 | 3 | Built | 1 |
| US-001-010 | Brute-Force Account Lockout | P0 | 3 | Built | 1 |
| US-001-011 | User CRUD (Invite, Activate, Deactivate) | P0 | 5 | Partial | 1 |
| US-001-012 | SSO — OIDC Integration | P2 | 8 | Partial | 14 |
| US-001-013 | SSO — SAML Integration | P2 | 8 | Partial | 14 |
| US-001-014 | API Key Management for Third Parties | P2 | 5 | Partial | 14 |
| US-001-015 | Password Expiry Policy Configuration | P2 | 3 | Not Started | 14 |
| US-001-016 | Security Audit Log Dashboard | P1 | 5 | Not Started | 8 |
Dependencies
- None (foundational epic — all other epics depend on this)
Acceptance Criteria (Epic Level)
- Staff can log in with email/password and receive JWT tokens
- MFA can be enabled and enforced per user or per role
- 9 roles with distinct permissions control access to all endpoints
- Password policies (history, complexity, reset) are enforced
- Account locks after 5 failed login attempts with configurable cooldown
- All auth events are audit-logged with IP, user agent, timestamp
- Session can be invalidated remotely by admin
KPIs / Success Metrics
- Login success rate > 99%
- MFA enrollment > 80% for admin/manager roles
- Account lockout false positive rate < 1%
- Token refresh latency < 100ms
- Zero unauthorized access incidents
Detailed User Stories
US-001-001: User Login with Email/Password
As a hotel staff member, I want to log in with my email and password, So that I can access the HMP dashboard with my assigned role.
Priority: P0 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
POST /api/v1/auth/login— AuthController.login(). LoginDto with email/password validation. Returns { accessToken, refreshToken, user }. - Frontend:
/loginpage with NextAuth v5. Credentials provider configured. Login form with email/password fields. - Tests: Auth guard tests, JWT strategy tests exist.
Acceptance Criteria
Scenario 1: Successful login
- Given the user has a valid account with email "frontdesk@hotel.com"
- When the user submits correct email and password
- Then the system returns a JWT access token (15-min expiry) and refresh token (7-day expiry)
- And the user is redirected to the dashboard
Scenario 2: Invalid credentials
- Given the user submits an incorrect password
- When the login request is processed
- Then the system returns 401 Unauthorized with message "Invalid credentials"
- And the failed attempt is logged with IP address
Scenario 3: Deactivated account
- Given the user's account has been deactivated by admin
- When the user attempts to log in
- Then the system returns 403 Forbidden with message "Account is deactivated. Contact your administrator."
Scenario 4: Missing tenant
- Given the user's email is not associated with any tenant
- When the user attempts to log in
- Then the system returns 404 Not Found with message "Account not found"
US-001-002: JWT Token Refresh
As a logged-in staff member, I want my session to refresh automatically, So that I don't get logged out during my shift while actively using the system.
Priority: P0 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
POST /api/v1/auth/refresh— Uses refresh token to issue new access token. Refresh token rotation implemented. - Frontend: NextAuth handles automatic token refresh via JWT callback.
Acceptance Criteria
Scenario 1: Automatic refresh
- Given the access token is within 2 minutes of expiry
- When the frontend detects the approaching expiry
- Then a new access token is requested using the refresh token
- And the user's session continues uninterrupted
Scenario 2: Expired refresh token
- Given the refresh token has expired (> 7 days)
- When a token refresh is attempted
- Then the system returns 401 and the user is redirected to the login page
US-001-003: User Logout & Session Invalidation
As a staff member, I want to log out of the system, So that my session is securely terminated, especially on shared front desk computers.
Priority: P0 | Points: 2 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
POST /api/v1/auth/logout— Invalidates refresh token. - Frontend: Logout button in sidebar. NextAuth signOut().
Acceptance Criteria
Scenario 1: Successful logout
- Given the user clicks "Logout"
- When the logout request is processed
- Then the refresh token is invalidated in the database
- And the user is redirected to the login page
- And subsequent API calls with the old access token are rejected after expiry
US-001-004: MFA Setup (TOTP)
As an admin or manager, I want to set up two-factor authentication using an authenticator app, So that my account is protected against credential theft (PCI-DSS requirement).
Priority: P0 | Points: 5 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
POST /api/v1/auth/mfa/setup— generates TOTP secret, returns QR code URI.POST /api/v1/auth/mfa/verify— verifies TOTP code and enables MFA. Uses otplib. - Frontend: MFA setup flow in user profile settings. QR code display. Verification code input.
Acceptance Criteria
Scenario 1: MFA setup flow
- Given the user navigates to Security settings
- When they click "Enable Two-Factor Authentication"
- Then a QR code is displayed for scanning with Google Authenticator / Authy
- And backup codes are displayed for emergency access
- And the user must enter a valid 6-digit code to confirm setup
Scenario 2: Invalid verification code
- Given the user enters an incorrect 6-digit code during setup
- When the code is submitted
- Then the system shows "Invalid code. Please try again."
- And MFA is not enabled
US-001-005: MFA Verification on Login
As a user with MFA enabled, I want to be prompted for my authenticator code after entering my password, So that an attacker with my password alone cannot access the system.
Priority: P0 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend: Login flow checks if MFA is enabled. If yes, returns
mfaRequired: trueand a temporary token.POST /api/v1/auth/mfa/validatecompletes login. - Frontend: MFA challenge screen shown when
mfaRequiredis true.
Acceptance Criteria
Scenario 1: MFA challenge on login
- Given the user has MFA enabled
- When they successfully enter email and password
- Then a second screen prompts for the 6-digit TOTP code
- And upon valid code entry, the full JWT tokens are issued
Scenario 2: Invalid MFA code
- Given the user enters an incorrect TOTP code
- When submitted
- Then "Invalid authentication code" is shown
- And the user can retry (up to 5 attempts before lockout)
US-001-006: Role-Based Access Control (9 Roles)
As a hotel admin, I want to assign specific roles to staff members, So that a front desk agent cannot access financial reports, and housekeeping staff cannot modify reservations.
Priority: P0 | Points: 8 | Sprint: 1 | Status: Built
Implementation Status
- Backend: 9 roles in Prisma enum: SUPER_ADMIN, ADMIN, MANAGER, FRONT_DESK, HOUSEKEEPING, FNB, ACCOUNTS, RESERVATIONS, STAFF. RolesGuard decorator. @Roles() annotations on controllers.
- Frontend: Role assignment in user management. Route-level protection via middleware. Menu items filtered by role.
Acceptance Criteria
Scenario 1: Role-based menu visibility
- Given a user is assigned the FRONT_DESK role
- When they log in to the dashboard
- Then they see: Dashboard, Reservations, Front Desk, Guests, Housekeeping (view-only)
- And they do NOT see: POS, Reports (financial), Settings, Super Admin
Scenario 2: API-level enforcement
- Given a user with HOUSEKEEPING role
- When they call
POST /api/v1/reservations - Then the system returns 403 Forbidden
- And an unauthorized access attempt is logged
US-001-007: Password Reset via Email
As a staff member who forgot their password, I want to reset my password via email, So that I can regain access without contacting the admin.
Priority: P0 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
POST /api/v1/auth/forgot-password— sends reset link.POST /api/v1/auth/reset-password— accepts token + new password. - Frontend: Forgot password page with email input. Reset password page with token validation.
Acceptance Criteria
Scenario 1: Password reset flow
- Given the user clicks "Forgot Password" on the login page
- When they enter their registered email
- Then a password reset email is sent with a time-limited link (30 minutes)
- And the link leads to a "Set New Password" page
Scenario 2: Expired reset token
- Given the reset link was generated more than 30 minutes ago
- When the user clicks the link
- Then "This link has expired. Please request a new password reset." is shown
US-001-008: Force Password Change
As an admin, I want to force a user to change their password on next login, So that I can enforce security after a suspected breach or for new hires.
Priority: P1 | Points: 2 | Sprint: 1 | Status: Built
Implementation Status
- Backend:
forcePasswordChangeflag on user model. Checked during login.PATCH /api/v1/users/:id/force-password-change. - Frontend: Redirect to password change screen when flag is true.
Acceptance Criteria
Scenario 1: Force change on login
- Given the admin has set "Force Password Change" for a user
- When the user logs in with their current password
- Then they are redirected to a "Change Password" screen
- And they cannot navigate to any other page until the password is changed
US-001-009: Password History Enforcement
As a security-conscious admin, I want the system to prevent users from reusing recent passwords, So that compromised passwords are not recycled.
Priority: P1 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend: Last 5 password hashes stored. Checked during password change. Validation in auth service.
- Frontend: Error message shown when password matches history.
Acceptance Criteria
Scenario 1: Password reuse blocked
- Given a user attempts to change their password to one of their last 5 passwords
- When the new password is submitted
- Then the system rejects it with "You cannot reuse your last 5 passwords"
US-001-010: Brute-Force Account Lockout
As a security system, I want to lock accounts after repeated failed login attempts, So that brute-force attacks are prevented.
Priority: P0 | Points: 3 | Sprint: 1 | Status: Built
Implementation Status
- Backend: Failed attempt counter in Redis. Lockout after 5 failures. Configurable cooldown (default 15 minutes). IP-based tracking.
- Frontend: "Account temporarily locked" message with countdown.
Acceptance Criteria
Scenario 1: Account lockout after 5 failures
- Given a user has failed login 5 times consecutively
- When they attempt a 6th login (even with correct password)
- Then the system returns "Account temporarily locked. Try again in 15 minutes."
- And the lockout event is logged with IP address
Scenario 2: Lockout reset after cooldown
- Given 15 minutes have passed since lockout
- When the user attempts to log in with correct credentials
- Then login succeeds and the failed attempt counter resets
US-001-011: User CRUD (Invite, Activate, Deactivate)
As a hotel admin, I want to invite new staff, activate/deactivate their accounts, and manage their profiles, So that I can control who has access to the platform.
Priority: P0 | Points: 5 | Sprint: 1 | Status: Partial
Implementation Status
- Backend: User CRUD endpoints exist. Create user with role assignment. Activate/deactivate endpoints. List users with pagination.
- Frontend: User management page in Settings with list view, create form, edit form. Role assignment dropdown.
- Gap: Email invitation flow not fully wired (invite token generation exists but email sending not connected). Bulk user import not available.
Acceptance Criteria
Scenario 1: Invite new staff member
- Given the admin navigates to Settings > Users
- When they click "Invite User" and fill in email, name, and role
- Then an invitation email is sent with a link to set their password
- And the user appears in the list as "Invited" status
Scenario 2: Deactivate staff member
- Given an admin selects an active user
- When they click "Deactivate"
- Then the user's status changes to "Inactive"
- And the user's active sessions are invalidated
- And the user cannot log in
US-001-012: SSO — OIDC Integration
As a hotel chain IT admin, I want to configure OIDC-based Single Sign-On, So that staff can log in using their corporate identity provider (Azure AD, Okta, Google Workspace).
Priority: P2 | Points: 8 | Sprint: 14 | Status: Partial
Implementation Status
- Backend: OIDC strategy skeleton exists in auth service. DTOs for OIDC configuration.
- Frontend: No SSO configuration UI in settings.
- Gap: No actual identity provider integration tested. No callback handling. No account linking.
Acceptance Criteria
Scenario 1: OIDC login flow
- Given the hotel has configured Azure AD as OIDC provider
- When a staff member clicks "Sign in with Corporate Account"
- Then they are redirected to Azure AD login
- And upon successful authentication, they are logged into HMP with their mapped role
US-001-013: SSO — SAML Integration
As a hotel chain IT admin, I want to configure SAML-based SSO for properties that use SAML identity providers, So that all chain properties share a single authentication system.
Priority: P2 | Points: 8 | Sprint: 14 | Status: Partial
Implementation Status
- Backend: SAML strategy skeleton exists. DTOs for SAML configuration.
- Gap: No SAML metadata parsing, no assertion consumer service, no account linking UI.
Acceptance Criteria
Scenario 1: SAML login flow
- Given the hotel has uploaded a SAML metadata XML
- When a staff member initiates SSO login
- Then they are redirected to the SAML IdP, authenticate, and return with a SAML assertion
- And HMP creates/links the user account based on SAML attributes
US-001-014: API Key Management for Third Parties
As a hotel admin, I want to generate and manage API keys for third-party integrations, So that external systems (POS terminals, door locks, accounting) can authenticate with HMP APIs.
Priority: P2 | Points: 5 | Sprint: 14 | Status: Partial
Implementation Status
- Backend: API key model in schema. Basic generation and validation.
- Gap: No dashboard UI for managing API keys. No scoping (all-or-nothing access). No usage tracking.
Acceptance Criteria
Scenario 1: Generate API key
- Given the admin navigates to Settings > API Keys
- When they click "Generate New Key" and select permissions/scopes
- Then a new API key is displayed (shown only once)
- And the key appears in the list with creation date, last used, and status
US-001-015: Password Expiry Policy Configuration
As a hotel admin, I want to configure password expiry policies (e.g., force change every 90 days), So that our security posture meets SOC 2 and PCI-DSS requirements.
Priority: P2 | Points: 3 | Sprint: 14 | Status: Not Started
Implementation Status
- Backend: Not implemented. Password history exists but no expiry tracking.
- Frontend: No configuration UI.
Acceptance Criteria
Scenario 1: Configure password expiry
- Given the admin navigates to Settings > Security
- When they set password expiry to 90 days
- Then users who haven't changed their password in 90 days are forced to change on next login
US-001-016: Security Audit Log Dashboard
As a hotel admin or security officer, I want to view a dashboard of all authentication events (logins, failed attempts, lockouts, role changes), So that I can monitor for suspicious activity and meet compliance audit requirements.
Priority: P1 | Points: 5 | Sprint: 8 | Status: Not Started
Implementation Status
- Backend: Auth events are logged but not exposed via a dedicated API endpoint for dashboard consumption.
- Frontend: No security audit log page.
Acceptance Criteria
Scenario 1: View security audit log
- Given the admin navigates to Settings > Security Audit Log
- When the page loads
- Then a searchable, filterable table shows: timestamp, user, event type (login/logout/failed/lockout/mfa), IP address, user agent
- And events can be filtered by date range, user, and event type
- And CSV export is available