Alaa Amer Articles

We offer a comprehensive collection of essential educational articles in web development to turn your ideas into digital reality

Authentication & Authorization: Secure Laravel Applications

Laravel 2026-01-01 Alaa Amer

Authentication & Authorization: Secure Laravel Applications

Expert Guide by Alaa Amer – Professional Web Developer & Applications Designer

Laravel provides robust authentication and authorization systems. Master security patterns, API protection, and enterprise-level access control for production applications.

2️⃣ Role-Based Access Control (RBAC)

Advanced Permission System:

<?php
// app/Models/Role.php
namespace App\Models;

use Spatie\Permission\Models\Role as SpatieRole;

class Role extends SpatieRole
{
    protected $fillable = [
        'name', 'guard_name', 'description', 'level', 'is_system'
    ];

    protected $casts = [
        'is_system' => 'boolean',
        'level' => 'integer'
    ];

    public function users()
    {
        return $this->belongsToMany(User::class, 'model_has_roles', 'role_id', 'model_id');
    }

    public function isSystemRole(): bool
    {
        return $this->is_system;
    }

    public function canBeDeleted(): bool
    {
        return !$this->is_system && $this->users()->count() === 0;
    }

    public function hasHigherLevelThan(Role $role): bool
    {
        return $this->level > $role->level;
    }
}

// app/Models/Permission.php
namespace App\Models;

use Spatie\Permission\Models\Permission as SpatiePermission;

class Permission extends SpatiePermission
{
    protected $fillable = [
        'name', 'guard_name', 'description', 'category', 'is_system'
    ];

    protected $casts = [
        'is_system' => 'boolean'
    ];

    public function scopeByCategory($query, string $category)
    {
        return $query->where('category', $category);
    }

    public function getFormattedNameAttribute(): string
    {
        return ucfirst(str_replace('.', ' ', $this->name));
    }
}

// database/seeders/RolePermissionSeeder.php
namespace Database\Seeders;

use App\Models\{Role, Permission, User};
use Illuminate\Database\Seeder;

class RolePermissionSeeder extends Seeder
{
    public function run(): void
    {
        // Create Permissions
        $permissions = [
            // User Management
            ['name' => 'users.view', 'category' => 'users', 'description' => 'View users'],
            ['name' => 'users.create', 'category' => 'users', 'description' => 'Create users'],
            ['name' => 'users.edit', 'category' => 'users', 'description' => 'Edit users'],
            ['name' => 'users.delete', 'category' => 'users', 'description' => 'Delete users'],

            // Post Management
            ['name' => 'posts.view', 'category' => 'posts', 'description' => 'View posts'],
            ['name' => 'posts.create', 'category' => 'posts', 'description' => 'Create posts'],
            ['name' => 'posts.edit', 'category' => 'posts', 'description' => 'Edit posts'],
            ['name' => 'posts.delete', 'category' => 'posts', 'description' => 'Delete posts'],
            ['name' => 'posts.publish', 'category' => 'posts', 'description' => 'Publish posts'],

            // System Administration
            ['name' => 'admin.dashboard', 'category' => 'admin', 'description' => 'Access admin dashboard'],
            ['name' => 'admin.settings', 'category' => 'admin', 'description' => 'Manage system settings'],
            ['name' => 'admin.roles', 'category' => 'admin', 'description' => 'Manage roles'],
        ];

        foreach ($permissions as $permission) {
            Permission::firstOrCreate(['name' => $permission['name']], $permission);
        }

        // Create Roles
        $roles = [
            [
                'name' => 'super-admin',
                'description' => 'Super Administrator',
                'level' => 100,
                'is_system' => true,
                'permissions' => Permission::all()->pluck('name')->toArray()
            ],
            [
                'name' => 'admin',
                'description' => 'Administrator',
                'level' => 90,
                'is_system' => false,
                'permissions' => [
                    'users.view', 'users.create', 'users.edit',
                    'posts.view', 'posts.create', 'posts.edit', 'posts.delete', 'posts.publish',
                    'admin.dashboard'
                ]
            ],
            [
                'name' => 'editor',
                'description' => 'Content Editor',
                'level' => 70,
                'is_system' => false,
                'permissions' => [
                    'posts.view', 'posts.create', 'posts.edit', 'posts.publish'
                ]
            ],
            [
                'name' => 'author',
                'description' => 'Content Author',
                'level' => 50,
                'is_system' => false,
                'permissions' => [
                    'posts.view', 'posts.create', 'posts.edit'
                ]
            ],
            [
                'name' => 'user',
                'description' => 'Regular User',
                'level' => 10,
                'is_system' => true,
                'permissions' => []
            ]
        ];

        foreach ($roles as $roleData) {
            $permissions = $roleData['permissions'];
            unset($roleData['permissions']);

            $role = Role::firstOrCreate(['name' => $roleData['name']], $roleData);
            $role->syncPermissions($permissions);
        }
    }
}

Advanced Authorization Middleware:

<?php
// app/Http/Middleware/CheckRole.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckRole
{
    public function handle(Request $request, Closure $next, ...$roles)
    {
        if (!auth()->check()) {
            return redirect()->route('login');
        }

        $user = auth()->user();

        // Check if user is locked
        if ($user->isLocked()) {
            auth()->logout();
            return redirect()->route('login')
                ->withErrors(['account' => 'Your account has been temporarily locked.']);
        }

        // Check roles
        foreach ($roles as $role) {
            if ($user->hasRole($role)) {
                return $next($request);
            }
        }

        // Log unauthorized access attempt
        activity()
            ->causedBy($user)
            ->withProperties([
                'roles_required' => $roles,
                'user_roles' => $user->getRoleNames()->toArray(),
                'route' => $request->route()->getName(),
                'ip' => $request->ip()
            ])
            ->log('unauthorized_access_attempt');

        abort(403, 'Insufficient privileges.');
    }
}

// app/Http/Middleware/CheckPermission.php
class CheckPermission
{
    public function handle(Request $request, Closure $next, string $permission, ?string $guard = null)
    {
        if (!auth($guard)->check()) {
            return $this->handleUnauthenticated($request);
        }

        $user = auth($guard)->user();

        if (!$user->can($permission)) {
            return $this->handleUnauthorized($request, $user, $permission);
        }

        return $next($request);
    }

    protected function handleUnauthenticated(Request $request)
    {
        if ($request->expectsJson()) {
            return response()->json(['message' => 'Unauthenticated.'], 401);
        }

        return redirect()->guest(route('login'));
    }

    protected function handleUnauthorized(Request $request, $user, string $permission)
    {
        // Log the unauthorized attempt
        activity()
            ->causedBy($user)
            ->withProperties(['permission' => $permission])
            ->log('unauthorized_permission_attempt');

        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'This action is unauthorized.',
                'required_permission' => $permission
            ], 403);
        }

        abort(403);
    }
}

4️⃣ Advanced Security Features

Multi-Factor Authentication:

<?php
// app/Http/Controllers/TwoFactorController.php
namespace App\Http\Controllers;

use App\Http\Requests\TwoFactorRequest;
use Illuminate\Http\JsonResponse;
use PragmaRX\Google2FA\Google2FA;

class TwoFactorController extends Controller
{
    protected $google2fa;

    public function __construct()
    {
        $this->middleware('auth');
        $this->google2fa = new Google2FA();
    }

    public function enable(): JsonResponse
    {
        $user = auth()->user();

        if ($user->two_factor_confirmed_at) {
            return response()->json(['message' => '2FA already enabled'], 400);
        }

        $secretKey = $user->enableTwoFactor();

        $qrCodeUrl = $this->google2fa->getQRCodeUrl(
            config('app.name'),
            $user->email,
            $secretKey
        );

        return response()->json([
            'secret_key' => $secretKey,
            'qr_code_url' => $qrCodeUrl,
            'recovery_codes' => $this->generateRecoveryCodes($user)
        ]);
    }

    public function confirm(TwoFactorRequest $request): JsonResponse
    {
        $user = auth()->user();

        if ($user->confirmTwoFactor($request->code)) {
            activity()
                ->causedBy($user)
                ->log('two_factor_enabled');

            return response()->json(['message' => '2FA enabled successfully']);
        }

        return response()->json(['message' => 'Invalid code'], 400);
    }

    public function verify(TwoFactorRequest $request): JsonResponse
    {
        $user = auth()->user();

        // Check 2FA code
        if ($this->verifyCode($user, $request->code)) {
            session(['2fa_verified' => true]);

            return response()->json(['message' => '2FA verification successful']);
        }

        return response()->json(['message' => 'Invalid 2FA code'], 400);
    }

    public function disable(TwoFactorRequest $request): JsonResponse
    {
        $user = auth()->user();

        if ($this->verifyCode($user, $request->code)) {
            $user->disableTwoFactor();

            activity()
                ->causedBy($user)
                ->log('two_factor_disabled');

            return response()->json(['message' => '2FA disabled successfully']);
        }

        return response()->json(['message' => 'Invalid code'], 400);
    }

    protected function verifyCode($user, string $code): bool
    {
        // Try regular 2FA code
        if ($user->two_factor_secret) {
            $secret = decrypt($user->two_factor_secret);
            if ($this->google2fa->verifyKey($secret, $code)) {
                return true;
            }
        }

        // Try recovery codes
        $recoveryCodes = json_decode(decrypt($user->two_factor_recovery_codes ?? '[]'), true);
        if (in_array($code, $recoveryCodes)) {
            // Remove used recovery code
            $recoveryCodes = array_diff($recoveryCodes, [$code]);
            $user->update([
                'two_factor_recovery_codes' => encrypt(json_encode($recoveryCodes))
            ]);
            return true;
        }

        return false;
    }

    protected function generateRecoveryCodes($user): array
    {
        $recoveryCodes = [];
        for ($i = 0; $i < 10; $i++) {
            $recoveryCodes[] = strtoupper(Str::random(4) . '-' . Str::random(4));
        }

        $user->update([
            'two_factor_recovery_codes' => encrypt(json_encode($recoveryCodes))
        ]);

        return $recoveryCodes;
    }
}

// app/Http/Middleware/RequireTwoFactor.php
class RequireTwoFactor
{
    public function handle(Request $request, Closure $next)
    {
        $user = auth()->user();

        if ($user && $user->two_factor_confirmed_at && !session('2fa_verified')) {
            if ($request->expectsJson()) {
                return response()->json(['message' => '2FA verification required'], 403);
            }

            return redirect()->route('2fa.verify');
        }

        return $next($request);
    }
}

Security Monitoring & Logging:

<?php
// app/Services/SecurityService.php
namespace App\Services;

use App\Models\{SecurityLog, LoginAttempt, User};
use Illuminate\Http\Request;

class SecurityService
{
    public function logSecurityEvent(string $event, ?User $user = null, array $data = []): void
    {
        SecurityLog::create([
            'user_id' => $user?->id,
            'event' => $event,
            'ip_address' => request()->ip(),
            'user_agent' => request()->userAgent(),
            'data' => $data,
            'created_at' => now()
        ]);
    }

    public function detectSuspiciousActivity(User $user): bool
    {
        // Multiple login attempts from different IPs
        $recentAttempts = LoginAttempt::where('user_id', $user->id)
            ->where('created_at', '>=', now()->subHour())
            ->distinct('ip_address')
            ->count('ip_address');

        if ($recentAttempts > 3) {
            $this->logSecurityEvent('suspicious_login_pattern', $user, [
                'distinct_ips' => $recentAttempts
            ]);
            return true;
        }

        // Rapid API calls
        $apiCalls = SecurityLog::where('user_id', $user->id)
            ->where('event', 'api_request')
            ->where('created_at', '>=', now()->subMinute())
            ->count();

        if ($apiCalls > 100) {
            $this->logSecurityEvent('api_abuse', $user, [
                'requests_per_minute' => $apiCalls
            ]);
            return true;
        }

        return false;
    }

    public function blockMaliciousIPs(): void
    {
        // Find IPs with excessive failed attempts
        $maliciousIPs = LoginAttempt::where('successful', false)
            ->where('created_at', '>=', now()->subDay())
            ->groupBy('ip_address')
            ->having(DB::raw('COUNT(*)'), '>', 50)
            ->pluck('ip_address');

        foreach ($maliciousIPs as $ip) {
            // Add to blocked IPs list
            Cache::put("blocked_ip:{$ip}", true, now()->addHours(24));

            $this->logSecurityEvent('ip_blocked', null, ['ip' => $ip]);
        }
    }
}

Next Steps

Master building robust APIs with Laravel API Development patterns and best practices.

📩 Need help with Laravel security?

Laravel Authentication Authorization Security JWT API Security RBAC Permissions
Article Category
Laravel

Authentication & Authorization: Secure Laravel Applications

Master Laravel authentication, authorization systems, API security, role-based access control, and advanced security patterns for enterprise applications.

Authentication & Authorization: Secure Laravel Applications
01

Consultation & Communication

Direct communication via WhatsApp or phone to understand your project needs precisely.

02

Planning & Scheduling

Creating clear work plan with specific timeline for each project phase.

03

Development & Coding

Building projects with latest technologies ensuring high performance and security.

04

Testing & Delivery

Comprehensive testing and thorough review before final project delivery.

Alaa Amer
Alaa Amer

Professional web developer with over 10 years of experience in building innovative digital solutions.

Need This Service?

Contact me now for a free consultation and quote

WhatsApp Your satisfaction is our ultimate goal

What We Offer

  • Website Maintenance & Updates

    Keep your website secure updated optimized

  • API Integration

    Connect your systems with powerful APIs

  • Database Design & Optimization

    Faster queries cleaner structure fewer issues

  • Website Security Hardening

    Protect your site from cyber threats

  • Automation & Scripts

    Automate repetitive tasks and save time

Have Questions?

Call Us Now

00201014714795