Initial commit
This commit is contained in:
109
app/Http/Middleware/RequireAdminProfile.php
Normal file
109
app/Http/Middleware/RequireAdminProfile.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Helpers\ProfileAuthorizationHelper;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Require Admin Profile Middleware
|
||||
*
|
||||
* Ensures that only administrators or central banks can access admin routes.
|
||||
* Prevents IDOR attacks and cross-guard access by validating profile ownership
|
||||
* using ProfileAuthorizationHelper.
|
||||
*
|
||||
* Usage:
|
||||
* - Apply to routes that require admin or central bank access
|
||||
* - Validates active profile from session
|
||||
* - Checks cross-guard attacks via ProfileAuthorizationHelper
|
||||
* - Logs all access attempts for security monitoring
|
||||
*/
|
||||
class RequireAdminProfile
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
// Get active profile from session
|
||||
$activeProfileType = session('activeProfileType');
|
||||
$activeProfileId = session('activeProfileId');
|
||||
|
||||
if (!$activeProfileType || !$activeProfileId) {
|
||||
Log::warning('RequireAdminProfile: No active profile in session', [
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
abort(403, __('No active profile selected'));
|
||||
}
|
||||
|
||||
$profile = $activeProfileType::find($activeProfileId);
|
||||
|
||||
if (!$profile) {
|
||||
Log::warning('RequireAdminProfile: Active profile not found', [
|
||||
'active_profile_type' => $activeProfileType,
|
||||
'active_profile_id' => $activeProfileId,
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
abort(403, __('Active profile not found'));
|
||||
}
|
||||
|
||||
// Validate profile ownership using ProfileAuthorizationHelper
|
||||
// This prevents cross-guard attacks (e.g., web user accessing admin profile)
|
||||
ProfileAuthorizationHelper::authorize($profile);
|
||||
|
||||
// Verify admin or central bank permissions
|
||||
if ($profile instanceof \App\Models\Admin) {
|
||||
// Admin access OK
|
||||
Log::info('RequireAdminProfile: Admin access granted', [
|
||||
'admin_id' => $profile->id,
|
||||
'admin_name' => $profile->name,
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
if ($profile instanceof \App\Models\Bank) {
|
||||
// Only central bank (level 0) can access admin routes
|
||||
if ($profile->level === 0) {
|
||||
Log::info('RequireAdminProfile: Central bank access granted', [
|
||||
'bank_id' => $profile->id,
|
||||
'bank_name' => $profile->name,
|
||||
'bank_level' => $profile->level,
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
Log::warning('RequireAdminProfile: Non-central bank attempted admin access', [
|
||||
'bank_id' => $profile->id,
|
||||
'bank_name' => $profile->name,
|
||||
'bank_level' => $profile->level,
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
|
||||
abort(403, __('Central bank access required for admin functions'));
|
||||
}
|
||||
|
||||
// Not admin or central bank
|
||||
Log::warning('RequireAdminProfile: Unauthorized profile type attempted admin access', [
|
||||
'profile_type' => get_class($profile),
|
||||
'profile_id' => $profile->id,
|
||||
'ip_address' => $request->ip(),
|
||||
'url' => $request->fullUrl(),
|
||||
]);
|
||||
|
||||
abort(403, __('Admin or central bank access required'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user