libra/docs/stories/story-1.2-authentication-ro...

174 lines
6.4 KiB
Markdown

# 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