Skip to main content

Authentication

The system has three distinct user populations, each with their own Laravel auth guard and Filament panel. All three are backed by the same users table but accessed via different guards so a client portal user cannot authenticate into the admin panel.


Three Guards

// config/auth.php
'guards' => [
'web' => ['driver' => 'session', 'provider' => 'users'], // Admin panel
'client' => ['driver' => 'session', 'provider' => 'users'], // Client portal
'partner' => ['driver' => 'session', 'provider' => 'users'], // Partner portal
'sanctum' => ['driver' => 'sanctum', 'provider' => 'users'], // REST API
],

All guards use the users provider (same table). The guard name determines which panel the user can enter. A user record linked only via CLIENT_USERS cannot pass the canAccessPanel() check on the Admin panel.


Panel Access Control

Each panel's canAccessPanel() method enforces which user type is allowed:

// AdminPanelProvider — only FIRM_USER_PROFILES
public function canAccessPanel(Panel $panel): bool
{
return FirmUserProfile::where('user_id', auth()->id())
->where('law_firm_id', Filament::getTenant()?->id)
->where('is_active', true)
->exists();
}

// ClientPanelProvider — only CLIENT_USERS
public function canAccessPanel(Panel $panel): bool
{
return ClientUser::where('user_id', auth()->id())
->where('status', 'active')
->exists();
}

// PartnerPanelProvider — only PARTNER_ATTORNEY_USERS
public function canAccessPanel(Panel $panel): bool
{
return PartnerAttorneyUser::where('user_id', auth()->id())
->where('status', 'active')
->exists();
}

REST API Authentication (Sanctum)

Mobile apps and external integrations authenticate with a Bearer token issued by Sanctum. Tokens carry named abilities that map to permission codes from the PERMISSIONS table:

time-entries:write    → LAWYER_TIME_ENTRY.CREATE
invoices:read → INVOICE.READ
matters:read → CASE.READ
documents:write → DOCUMENT.UPLOAD

Token abilities are checked in policies:

public function create(User $user, Matter $matter): bool
{
// Sanctum ability check + RBAC permission check
return $user->tokenCan('matters:write')
&& $this->rbac->check($user, 'CASE.CREATE', $matter->law_firm_id);
}

Password Reset and Email Verification

Filament exposes password reset and email verification flows out of the box via Laravel Fortify integration. The password_reset_tokens table is used for the reset flow. Email verification uses the signed URL approach from Illuminate\Auth\MustVerifyEmail.


Sequence: Staff Login

See the existing Login Flow sequence diagram for the full flow. In Laravel the steps map as:

  1. POST /admin/login — Filament login form submission
  2. ResolveTenant middleware — resolves LawFirm from URL slug
  3. Auth::attempt(['email' => ..., 'password' => ...]) — Laravel validates credentials
  4. canAccessPanel() — verifies user has an active FirmUserProfile for this firm
  5. Session written to Redis — user_id, guard, expiry
  6. Redirect to /admin/{firm-slug}/dashboard