# Story 1.2: Authentication & Role System ## Epic Reference **Epic 1:** Core Foundation & Infrastructure ## User Story As an **admin**, I want **a secure authentication system with Admin/Client roles**, So that **only authorized users can access the platform with appropriate permissions**. ## Story Context ### Existing System Integration - **Integrates with:** Fortify authentication, users table - **Technology:** Laravel Fortify, Livewire Volt - **Follows pattern:** Existing `app/Actions/Fortify/` for custom logic - **Touch points:** FortifyServiceProvider, login views, middleware ## Acceptance Criteria ### Functional Requirements - [ ] Fortify configured with custom Volt views - [ ] Login page with bilingual support (Arabic/English) - [ ] Session timeout after 2 hours of inactivity - [ ] Rate limiting on login attempts (5 attempts per minute) - [ ] Admin role with full access to all features - [ ] Client role with restricted access (own data only) - [ ] Registration feature DISABLED (admin creates all accounts) ### Security Requirements - [ ] CSRF protection enabled on all forms - [ ] Password hashing using bcrypt - [ ] Gates/Policies for authorization checks - [ ] Secure session configuration - [ ] Remember me functionality (optional) ### Integration Requirements - [ ] Login redirects to appropriate dashboard: - Admin users → `/admin/dashboard` (to be created in Epic 2) - Client users → `/dashboard` (to be created in Epic 2) - For now, redirect to a placeholder route or home page - [ ] Logout clears session properly and redirects to login page - [ ] Middleware protects admin-only routes (return 403 for unauthorized) - [ ] Failed login attempts logged to `admin_logs` table ### Quality Requirements - [ ] Login form validates inputs properly - [ ] Error messages are clear and bilingual - [ ] All test scenarios in "Test Scenarios" section pass - [ ] No security vulnerabilities ## Technical Notes ### Fortify Configuration ```php // config/fortify.php 'features' => [ // Features::registration(), // DISABLED Features::resetPasswords(), Features::emailVerification(), Features::updateProfileInformation(), Features::updatePasswords(), ], ``` ### Custom Views Setup ```php // FortifyServiceProvider boot() Fortify::loginView(fn () => view('auth.login')); // No registerView - registration disabled ``` ### Role Implementation - Use `user_type` column: 'admin', 'individual', 'company' - Admin check: `$user->user_type === 'admin'` - Client check: `in_array($user->user_type, ['individual', 'company'])` ### Gate Definitions ```php // AuthServiceProvider or AppServiceProvider Gate::define('admin', fn (User $user) => $user->user_type === 'admin'); Gate::define('client', fn (User $user) => $user->user_type !== 'admin'); ``` ### Middleware - `auth` - Require authentication - `can:admin` - Require admin role - Custom middleware for session timeout if needed ### Environment Configuration ```env SESSION_LIFETIME=120 # 2 hours in minutes SESSION_EXPIRE_ON_CLOSE=false ``` ### Edge Case Behavior **Rate Limiting (5 attempts per minute):** - After 5 failed attempts, show message: "Too many login attempts. Please try again in 60 seconds." - Use bilingual message from translation files - Log rate limit events for security monitoring **Session Timeout (2 hours inactivity):** - When session expires, redirect to login page - Show flash message: "Your session has expired. Please log in again." - Preserve intended URL for redirect after re-authentication **Deactivated Account Login Attempt:** - Check `status` field during authentication - If `status === 'deactivated'`, reject login with message: "Your account has been deactivated. Please contact the administrator." ## Test Scenarios ### Feature Tests (tests/Feature/Auth/) **Login Flow:** - [ ] `test_login_page_renders_correctly` - Login page displays in default language - [ ] `test_user_can_login_with_valid_credentials` - Valid credentials redirect to dashboard - [ ] `test_admin_redirects_to_admin_dashboard` - Admin user goes to admin dashboard - [ ] `test_client_redirects_to_client_dashboard` - Client user goes to client dashboard - [ ] `test_invalid_credentials_show_error` - Wrong password shows bilingual error - [ ] `test_nonexistent_user_shows_error` - Unknown email shows generic error (no user enumeration) - [ ] `test_deactivated_user_cannot_login` - Deactivated account rejected with message **Rate Limiting:** - [ ] `test_rate_limiting_blocks_after_five_attempts` - 6th attempt blocked - [ ] `test_rate_limit_message_is_bilingual` - Error message respects locale - [ ] `test_rate_limit_resets_after_one_minute` - Can retry after cooldown **Session Management:** - [ ] `test_logout_clears_session` - Logout destroys session data - [ ] `test_remember_me_extends_session` - Remember token works (if implemented) **Authorization:** - [ ] `test_admin_can_access_admin_routes` - Admin passes `can:admin` middleware - [ ] `test_client_cannot_access_admin_routes` - Client gets 403 on admin routes - [ ] `test_unauthenticated_user_redirected_to_login` - Guest redirected from protected routes ### Unit Tests (tests/Unit/) **Gate Definitions:** - [ ] `test_admin_gate_returns_true_for_admin_user` - Gate check passes - [ ] `test_admin_gate_returns_false_for_client_user` - Gate check fails - [ ] `test_client_gate_returns_true_for_individual_user` - Client gate passes - [ ] `test_client_gate_returns_true_for_company_user` - Client gate passes ## Definition of Done - [ ] Login page renders correctly in both languages - [ ] Users can log in with valid credentials - [ ] Invalid credentials show proper error (bilingual) - [ ] Deactivated users cannot log in - [ ] Rate limiting prevents brute force (5 attempts/minute) - [ ] Session expires after 2 hours inactivity - [ ] Admin routes protected from clients (403 response) - [ ] All Feature and Unit tests from "Test Scenarios" section pass - [ ] Code formatted with Pint ## Dependencies - **Story 1.1:** Database schema - creates `users` table with `user_type` enum (`admin`, `individual`, `company`), `status` enum (`active`, `deactivated`), and `preferred_language` enum (`ar`, `en`) - **Story 1.3:** Bilingual infrastructure (for login page translations) ## Risk Assessment - **Primary Risk:** Security misconfiguration - **Mitigation:** Use Laravel's built-in security features, no custom auth logic - **Rollback:** Restore Fortify defaults ## Estimation **Complexity:** Medium **Estimated Effort:** 3-4 hours