Authentication and authorization are fundamental to most Laravel applications. Authentication verifies who a user is, while authorization determines what they can do. Laravel provides powerful tools for both.
This comprehensive guide covers Laravel authentication and authorization, including built-in solutions, custom implementations, role-based access control, and best practices for secure user management.
Authentication vs Authorization
Understanding the difference is crucial:
- Authentication: Verifying user identity (login, who you are)
- Authorization: Determining user permissions (what you can do)
Laravel's Built-in Authentication
Laravel Breeze
Lightweight authentication scaffolding:
composer require laravel/breeze --dev
php artisan breeze:install
npm install && npm run dev
php artisan migrate
Laravel Jetstream
Full-featured authentication with teams, API tokens, and more:
composer require laravel/jetstream
php artisan jetstream:install livewire
php artisan migrate
Laravel Sanctum
API token authentication for SPAs and mobile apps:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Authentication Methods
Email/Password Authentication
// Login
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return redirect()->intended('/dashboard');
}
// Register
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
Auth::login($user);
// Logout
Auth::logout();
Social Authentication (OAuth)
// Install Socialite
composer require laravel/socialite
// Configure in config/services.php
'github' => [
'client_id' => env('GITHUB_CLIENT_ID'),
'client_secret' => env('GITHUB_CLIENT_SECRET'),
'redirect' => env('GITHUB_REDIRECT_URI'),
],
// Controller
public function redirectToProvider()
{
return Socialite::driver('github')->redirect();
}
public function handleProviderCallback()
{
$githubUser = Socialite::driver('github')->user();
$user = User::firstOrCreate(
['email' => $githubUser->email],
[
'name' => $githubUser->name,
'github_id' => $githubUser->id,
]
);
Auth::login($user);
return redirect('/dashboard');
}
API Token Authentication
// Create token
$token = $user->createToken('api-token')->plainTextToken;
// Use token in requests
Authorization: Bearer {token}
// Revoke token
$user->tokens()->delete();
// Revoke specific token
$user->tokens()->where('id', $tokenId)->delete();
User Registration and Login
Registration Flow
// RegisterController
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
event(new Registered($user));
Auth::login($user);
return redirect('/dashboard');
}
Login Process
// LoginController
public function authenticate(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
Password Management
Password Reset
// Send reset link
use Illuminate\Support\Facades\Password;
$status = Password::sendResetLink(
$request->only('email')
);
// Reset password
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user, $password) {
$user->forceFill([
'password' => Hash::make($password)
])->save();
}
);
Password Confirmation
// Require password confirmation
Route::middleware(['auth', 'password.confirm'])->group(function () {
Route::get('/settings', [SettingsController::class, 'edit']);
});
// Confirm password
if (! Hash::check($request->password, $request->user()->password)) {
return back()->withErrors(['password' => 'Incorrect password']);
}
$request->session()->passwordConfirmed();
Authorization
Gates
// Define gate in AuthServiceProvider
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
// Use in controller
if (Gate::denies('update-post', $post)) {
abort(403);
}
// Or use authorize helper
$this->authorize('update-post', $post);
Policies
// Generate policy
php artisan make:policy PostPolicy --model=Post
// PostPolicy.php
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
// Use in controller
$this->authorize('update', $post);
// Or in Blade
@can('update', $post)
Edit
@endcan
Role-Based Access Control (RBAC)
Using Spatie Permission Package
// Install
composer require spatie/laravel-permission
// Publish migrations
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
// Assign role
$user->assignRole('admin');
// Assign permission
$user->givePermissionTo('edit articles');
// Check role
if ($user->hasRole('admin')) {
// User is admin
}
// Check permission
if ($user->can('edit articles')) {
// User can edit articles
}
// Middleware
Route::middleware(['role:admin'])->group(function () {
// Admin routes
});
Route::middleware(['permission:edit articles'])->group(function () {
// Routes requiring permission
});
Custom Role Implementation
// Migration
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('role_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
$table->foreignId('role_id')->constrained();
});
// User model
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function hasRole($role)
{
return $this->roles->contains('name', $role);
}
// Middleware
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
abort(403);
}
return $next($request);
}
Middleware for Protection
// Auth middleware (built-in)
Route::middleware('auth')->group(function () {
// Protected routes
});
// Guest middleware
Route::middleware('guest')->group(function () {
// Only accessible when not authenticated
});
// Custom middleware
Route::middleware(['auth', 'role:admin'])->group(function () {
// Admin-only routes
});
Multi-Factor Authentication (MFA)
// Install
composer require pragmarx/google2fa-laravel
// Enable MFA for user
$user->two_factor_secret = encrypt($google2fa->generateSecretKey());
$user->save();
// Verify code
$valid = $google2fa->verifyKey(
decrypt($user->two_factor_secret),
$request->code
);
if ($valid) {
// MFA verified
}
Session Management
Session Configuration
// config/session.php
'lifetime' => 120, // minutes
'expire_on_close' => false,
'encrypt' => true,
'secure' => env('SESSION_SECURE_COOKIE', true),
'same_site' => 'strict',
Session Security
- Use secure cookies in production
- Set appropriate session lifetime
- Regenerate session ID on login
- Use HTTPS for session cookies
Best Practices
- Always hash passwords (never store plain text)
- Use strong password requirements
- Implement rate limiting on login
- Use HTTPS for all authentication
- Implement proper session management
- Log authentication events
- Use CSRF protection
- Implement account lockout after failed attempts
Conclusion
Laravel authentication and authorization provide powerful tools for managing user access and permissions. Whether you use built-in solutions like Breeze or Jetstream, or implement custom authentication, Laravel makes it straightforward to build secure user management systems.
By implementing proper authentication, authorization, and role-based access control, you can ensure your application is secure and users have appropriate access to features and resources.
Working with experienced Laravel developers who understand authentication and authorization best practices can help you build secure, user-friendly applications with proper access control.