Get 20% off web development packages
Authentication & Authorization: Secure Laravel Applications
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?
Article Category
Authentication & Authorization: Secure Laravel Applications
Master Laravel authentication, authorization systems, API security, role-based access control, and advanced security patterns for enterprise applications.
Consultation & Communication
Direct communication via WhatsApp or phone to understand your project needs precisely.
Planning & Scheduling
Creating clear work plan with specific timeline for each project phase.
Development & Coding
Building projects with latest technologies ensuring high performance and security.
Testing & Delivery
Comprehensive testing and thorough review before final project delivery.
Services Related to This Article
All ServicesWant to apply this article to your project?
If this topic is relevant to your current project, you can jump to one of the services above or browse the services page to choose the most suitable solution.