Skip to content

Auth, Roles & Permissions

KoAkademy manages sensitive student academic, financial, and medical records. Authentication and authorization are strictly enforced at multiple boundaries across the stack.

GuardUsed ForImplementation Details
webAdmin panel, Staff workspace, Faculty & Student portalsSession-based state with encrypted cookies; guarded by portal-specific audience middleware
sanctumPublic & authenticated REST API (/api/*)Bearer tokens with fine-grained abilities
  • Email & Password: Standard credential authentication with rate limiting and secure hashing.
  • Passkeys (WebAuthn): Hardware security keys and biometric sign-in via laravel/passkeys.
  • Multi-Factor Authentication (2FA):
    • TOTP authenticator apps (SecurityAwareAppAuthentication).
    • Time-based email one-time passcodes (SecurityAwareEmailAuthentication).
  • Social Authentication: Optional OAuth login via Laravel Socialite (configured per deployment).

Role definitions and permissions use spatie/laravel-permission with Filament Shield:

  • Role Enum (UserRole): Defines roughly 30 distinct institutional roles (e.g. SuperAdmin, Admin, President, Registrar, Cashier, Dean, Professor, Student, Alumni).
  • Role Hierarchy: Methods like $role->canAccessAdminPortal(), $role->isFaculty(), and $role->getManageableRoles() determine portal access and assignment privileges without hardcoding role strings.
  • Super Administrator Bypass: The super_admin role has system-wide administrative access across all tenant schools.

Authorization in KoAkademy is never purely client-side; every protected action is verified at three distinct layers:

Incoming Request
1. Middleware Layer
├── EnsureAdministrativePortalAccess / EnsureFacultyAccess / EnsureStudentAccess
├── EnsureFeatureEnabled (Pennant feature flags)
└── SetTenantContext (School tenancy scoping)
2. Controller / Form Request Layer
├── FormRequest::authorize() method
└── $this->authorize('ability', Model::class) or Gate::authorize()
3. Policy Layer (Eloquent Model Policies)
└── Specific ability checks (e.g. StudentEnrollmentPolicy, AccountPolicy)

Contributor Code Sample: Protecting a Custom Action

Section titled “Contributor Code Sample: Protecting a Custom Action”

When creating a new controller or API endpoint, implement a dedicated Policy and authorize the incoming request:

<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\StudentEnrollment;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
final class EnrollmentStatusController extends Controller
{
public function updateStatus(Request $request, StudentEnrollment $enrollment): JsonResponse
{
// 1. Authorize against the model's policy
Gate::authorize('update', $enrollment);
// 2. Validate input parameters
$validated = $request->validate([
'status' => ['required', 'string', 'in:pending,verified,approved,rejected'],
'reason' => ['nullable', 'string', 'max:255'],
]);
// 3. Perform the state change
$enrollment->update([
'status' => $validated['status'],
'rejection_reason' => $validated['reason'] ?? null,
]);
return response()->json([
'message' => 'Enrollment status updated successfully.',
'enrollment' => $enrollment,
]);
}
}

Matching Eloquent Policy (StudentEnrollmentPolicy)

Section titled “Matching Eloquent Policy (StudentEnrollmentPolicy)”
<?php
declare(strict_types=1);
namespace App\Policies;
use App\Enums\UserRole;
use App\Models\StudentEnrollment;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
final class StudentEnrollmentPolicy
{
use HandlesAuthorization;
public function viewAny(User $user): bool
{
return $user->hasAnyRole([
UserRole::SuperAdmin->value,
UserRole::Admin->value,
UserRole::Registrar->value,
]);
}
public function update(User $user, StudentEnrollment $enrollment): bool
{
if ($user->hasRole(UserRole::SuperAdmin->value)) {
return true;
}
// Must belong to the same school and have administrative role
return $user->school_id === $enrollment->school_id
&& $user->hasAnyRole([UserRole::Admin->value, UserRole::Registrar->value]);
}
}
  • Audit Trails: spatie/laravel-activitylog tracks changes to administrative records, visible in Admin Workspace → Audit Logs.
  • Impersonation: Privileged administrators can impersonate staff or students for support inquiries (stechstudio/filament-impersonate). All impersonated actions are tagged in audit logs.
  • Privacy Protections: Student medical records, personal identity numbers, and credentials are encrypted or obfuscated in application logs.