-
Notifications
You must be signed in to change notification settings - Fork 0
Description
🎯 Problem Statement
Current Architecture Mismatch:
- Frontend: React PWA using Bearer tokens (stored in localStorage)
- API Routes: All protected with
auth:sanctummiddleware - Permissions: Created with
guard_name='web'(session-based) - User Model: No explicit
$guard_nameproperty (defaults to 'web')
Result: Spatie Laravel-Permission checks fail because:
- Sanctum authenticates user successfully ✅
- User attempts action requiring permission (e.g.,
roles.read) - Spatie checks
webguard for permissions ❌ - No permission found → 403 Forbidden
📊 Current State
Authentication Flow
Frontend Request
↓ Header: Authorization: Bearer <token>
API Middleware: auth:sanctum
↓ Token validated
User authenticated (sanctum guard)
↓ $user->can('roles.read')
Spatie checks 'web' guard ← MISMATCH!
❌ PermissionDoesNotExist: "There is no permission named `roles.read` for guard `sanctum`"
Affected Test Files
tests/Feature/RoleManagementApiTest.php(26 tests, 3 failing)tests/Feature/RoleApiTest.php(27 tests, all failing with 403)tests/Feature/PersonApiTest.php(13 tests, all failing with 403)
Total Impact: 36 failing tests due to guard mismatch
Code Locations
-
Permission Creation (all test files):
// Current (implicit web guard) Permission::create(['name' => 'roles.read']); // Target (explicit sanctum guard) Permission::create(['name' => 'roles.read', 'guard_name' => 'sanctum']);
-
User Model (
app/Models/User.php):// Current (no guard declared) class User extends Authenticatable { } // Target (explicit sanctum guard) class User extends Authenticatable { protected $guard_name = 'sanctum'; }
-
Auth Config (
config/auth.php):// Already configured (✅ complete) 'guards' => [ 'sanctum' => [ 'driver' => 'sanctum', 'provider' => 'users', ], ],
🎯 Target State
Authentication Flow (After Migration)
Frontend Request
↓ Header: Authorization: Bearer <token>
API Middleware: auth:sanctum
↓ Token validated
User authenticated (sanctum guard)
↓ $user->can('roles.read')
Spatie checks 'sanctum' guard ← MATCH!
✅ Permission found → Authorization succeeds
Benefits
- Semantic Correctness: 'sanctum' guard explicitly documents token-based auth
- Zero Technical Debt: No confusion for future developers
- Self-Documenting: Code clearly states authentication mechanism
- Future-Proof: Correct foundation for expanding RBAC features
- Consistency: Guard name matches actual authentication method
📋 Sub-Issues & Implementation Tasks
- Update RoleManagementApiTest to use sanctum guard #126: Update
RoleManagementApiTest.phpto use sanctum guard - Update RoleApiTest to use sanctum guard #127: Update
RoleApiTest.phpto use sanctum guard - Update PersonApiTest to use sanctum guard #128: Update
PersonApiTest.phpto use sanctum guard - Add $guard_name property to User model #129: Add
$guard_name = 'sanctum'to User model - Set sanctum as default guard in config/auth.php #134: Set sanctum as default guard in
config/auth.php - Document Guard Architecture and sanctum usage #130: Document Guard Architecture and sanctum usage
✅ Acceptance Criteria
- All permissions created with
guard_name='sanctum'in tests - User model declares
protected $guard_name = 'sanctum' - All 207 tests pass (including 36 previously failing)
- PHPStan Level Max: 0 errors
- Laravel Pint: Clean
- Guard architecture documented
- Config default guard set to 'sanctum'
- No semantic confusion between guard names and auth mechanism
🔗 Related Issues
Resolved by:
- PR fix(tests): Migrate permission system from web to sanctum guard #133: Update RoleManagementApiTest to use sanctum guard #126, Update RoleApiTest to use sanctum guard #127, Update PersonApiTest to use sanctum guard #128, Add $guard_name property to User model #129
- PR fix(auth): Set sanctum as default guard in config/auth.php #135: Set sanctum as default guard in config/auth.php #134
- PR docs(rbac): Document Guard architecture and sanctum usage #136: Document Guard Architecture and sanctum usage #130
Unblocks:
- RBAC Phase 4: Documentation & Final Testing #108 - RBAC Phase 4: Role Management CRUD API (READY ✅)
Context:
- Created during RBAC Phase 4 implementation when guard mismatch was discovered
- Architecture review determined systematic migration is preferred over quick fix
📚 Technical Context
Laravel Guards Explained
Guard: Authentication mechanism that determines HOW users are authenticated.
Web Guard:
- Session/cookie-based authentication
- Server stores session state
- Cookie contains session ID
- Typical for traditional web apps
Sanctum Guard:
- Token-based authentication
- Stateless (no server sessions)
- Bearer token in Authorization header
- Typical for SPAs and mobile apps
Spatie Permission Integration
Spatie Laravel-Permission is guard-aware - permissions are tied to specific guards. This allows:
- Different permission sets per authentication mechanism
- Fine-grained access control based on how user authenticated
Our Architecture: Pure token-based API (no sessions) → Should use 'sanctum' guard exclusively.
⏱️ Effort Estimate
Per Test File: 20-30 minutes (add✅ DONEguard_nameto Permission::create calls)User Model: 5 minutes (add single line)✅ DONEConfig Update: 10 minutes (change default guard)✅ DONEDocumentation: 30-45 minutes✅ DONE- Total: ~2-3 hours one-time investment ✅ COMPLETED
🚀 Migration Progress
- ✅ Phase 1: Test files updated (Update RoleManagementApiTest to use sanctum guard #126, Update RoleApiTest to use sanctum guard #127, Update PersonApiTest to use sanctum guard #128)
- ✅ Phase 2: User model updated (Add $guard_name property to User model #129)
- ✅ Phase 3: Full test suite verified (207 tests pass)
- ✅ Phase 4: Config default guard updated (Set sanctum as default guard in config/auth.php #134)
- ✅ Phase 5: Documentation complete (Document Guard Architecture and sanctum usage #130)
Status: 🎉 100% COMPLETE - All sub-issues merged!
Risk: Low - isolated change, comprehensive test coverage
Created: 2025-11-09 during RBAC Phase 4 implementation
Completed: 2025-11-09 (same day!)
Status: ✅ All 6 sub-issues complete (100% done)
Priority: High (architectural correctness)
Metadata
Metadata
Assignees
Type
Projects
Status