6.4 KiB
6.4 KiB
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
- Admin users →
- Logout clears session properly and redirects to login page
- Middleware protects admin-only routes (return 403 for unauthorized)
- Failed login attempts logged to
admin_logstable
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
// config/fortify.php
'features' => [
// Features::registration(), // DISABLED
Features::resetPasswords(),
Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
],
Custom Views Setup
// FortifyServiceProvider boot()
Fortify::loginView(fn () => view('auth.login'));
// No registerView - registration disabled
Role Implementation
- Use
user_typecolumn: 'admin', 'individual', 'company' - Admin check:
$user->user_type === 'admin' - Client check:
in_array($user->user_type, ['individual', 'company'])
Gate Definitions
// 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 authenticationcan:admin- Require admin role- Custom middleware for session timeout if needed
Environment Configuration
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
statusfield 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 languagetest_user_can_login_with_valid_credentials- Valid credentials redirect to dashboardtest_admin_redirects_to_admin_dashboard- Admin user goes to admin dashboardtest_client_redirects_to_client_dashboard- Client user goes to client dashboardtest_invalid_credentials_show_error- Wrong password shows bilingual errortest_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 blockedtest_rate_limit_message_is_bilingual- Error message respects localetest_rate_limit_resets_after_one_minute- Can retry after cooldown
Session Management:
test_logout_clears_session- Logout destroys session datatest_remember_me_extends_session- Remember token works (if implemented)
Authorization:
test_admin_can_access_admin_routes- Admin passescan:adminmiddlewaretest_client_cannot_access_admin_routes- Client gets 403 on admin routestest_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 passestest_admin_gate_returns_false_for_client_user- Gate check failstest_client_gate_returns_true_for_individual_user- Client gate passestest_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
userstable withuser_typeenum (admin,individual,company),statusenum (active,deactivated), andpreferred_languageenum (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