Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Auth Laravel Package

illuminate/auth

Illuminate/auth provides Laravel's authentication and authorization services: session guards, user providers, password hashing, gates and policies, and remember-me support. It powers login, registration, and access control out of the box, integrating with Eloquent and middleware to secure routes and...

View on GitHub
Deep Wiki
Context7

Getting Started

  • Treat this as a read-only subtree split of laravel/framework that Composer publishes for the auth subsystem. In a normal Laravel app you already have it — confirm with composer show illuminate/auth. Only add it to composer.json when you are wiring Illuminate components by hand, and then pin the version to your framework's, or you'll get Illuminate\Contracts mismatches.
  • Scaffold the UI rather than hand-rolling it: laravel/breeze (Blade/React/Vue starter scaffolding) or laravel/fortify (headless auth with routes, actions and views decoupled). Both sit on top of this package and give you a working login, register, forgot-password, reset-password, verify-email and confirm-password flow in one command.
  • First place to look: config/auth.php. Everything day-to-day resolves through the three keys there — defaults.guard, guards (session driver with a provider, or token for static API keys), and providers (eloquent driver pointing at App\Models\User). Second place: Illuminate\Auth\SessionGuard — it is the class that actually implements attempt, login, logout, viaRemember.
  • Your first real use case is "protect a route, log a user in, log them out":
// routes/web.php
Route::post('/login', function (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' => 'Invalid credentials.'])->onlyInput('email');
})->middleware('guest');

Route::post('/logout', function (Request $request) {
    Auth::logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    return redirect('/');
})->middleware('auth');
  • Verify the wiring before writing features: php artisan route:list --path=login, php artisan about (shows default guard), and Auth::getDefaultDriver() in tinker.

Implementation Patterns

  • Pick the guard per surface, explicitly. web (session) for browser, sanctum for SPA/mobile tokens, api (token driver) for machine clients. Then name it in middleware — auth:web, auth:sanctum — and in code with Auth::guard('sanctum')->user(). If most of your app uses one non-default guard, call Auth::shouldUse('sanctum') in a service provider so Auth::user() and the @auth directive agree.
  • Login flow checklist (the sequence matters): Auth::attempt(...) → $request->session()->regenerate() (Laravel's SessionGuard::login() migrates the session, but regenerate again after your own logic) → redirect with intended(). On failure, never echo why — one generic error keyed on email.
  • attempt vs validate vs once: attempt() logs in and persists to session; validate() only checks credentials (good for pre-flight checks or re-auth before sensitive actions); once() authenticates for the current request only (queue workers, stateless calls). Auth::attemptWhen($creds, fn ($user) => $user->is_active) is the clean way to add an activation gate without a custom guard.
  • Authorization is part of this package. Your User uses Illuminate\Foundation\Auth\User which pulls in Authorizable; that's what makes Gate, Policy, $user->can('update', $post), @can('update', $post), and the can:update,post middleware route work. Keep role checks in policies, not in controllers — Auth::user()->is_admin sprinkled through views is the classic drift.
  • Password resets go through the broker, not the guards:
$status = Password::sendResetLink($request->only('email'));

if ($request->filled('token')) {
    $status = Password::reset($request->only('email', 'password', 'password_confirmation', 'token'),
        function (User $user, string $password) {
            $user->forceFill(['password' => Hash::make($password)])->save();
            event(new PasswordReset($user));
        });
}

Configure passwords.users.expire (minutes) and .throttle (seconds) in config/auth.php, and use Password::broker('admins') when you have a second provider.

  • Email verification: implement Illuminate\Contracts\Auth\MustVerifyEmail on the model and apply the verified middleware (EnsureEmailIsVerified). The contract alone does nothing — the middleware plus the VerificationController/Fortify routes are what enforce it.
  • Hook the events instead of overriding classes. Login, Logout, Failed, Lockout, Attempting, Authenticated, PasswordReset, Verified are dispatched by the guards and brokers. Audit logging, "last login at" columns and security alerts belong in listeners registered from an EventServiceProvider; that keeps your customizations upgrade-safe.
  • Throttle login attempts with the RateLimiter facade in your login controller (Breeze's LoginRequest does exactly this): RateLimiter::tooManyAttempts($key, 5) → RateLimiter::hit($key) → throw a ValidationException with throttle in the message bag. The key is usually Str::lower($email).'|'.$request->ip().
  • Custom guards and providers are extension points on AuthManager, registered in a provider's boot(): Auth::extend('jwt', fn ($app, $name, $config) => new JwtGuard(...)) and Auth::provider('ldap', fn ($app, $config) => new LdapUserProvider(...)). Auth::viaRequest('api-token', fn ($request) => ...) is the shortcut when the config is just a closure.
  • API tokens: prefer laravel/sanctum for first-party SPAs and mobile; laravel/passport when you need full OAuth2 (scopes, refresh tokens, client grants). Both plug into this package's guard contract, so $request->user() and auth:sanctum behave like any other guard.
  • Testing: $this->actingAs($user) (or actingAs($user, 'sanctum')) shortcuts the whole guard stack. For login-flow tests, assert on the real thing — $this->post('/login', [...])->assertAuthenticatedAs($user) — and use Event::fake([Login::class]) + Event::assertDispatched when the point of the test is the side effect.
  • Impersonation / admin "log in as user" is one line: Auth::login($user) (optionally Auth::guard('web')->login($user)) — but stash the original id in session and add an explicit exit route, or support will have a bad day.

Gotchas and Tips

  • Do not add illuminate/auth to a Laravel app's composer.json. It's a split of the framework; a version skew between it and laravel/framework produces confusing Class not found or contract-signature errors. If it's already listed, remove it and let the framework supply it.
  • Auth::user() returns null silently. Either gate with Auth::check(), type-hint Request $request and use $request->user(), or put auth middleware on the route. Null-property errors on a protected page almost always mean the middleware was never applied (or a different guard resolved it).
  • Guard name mismatch is the #1 "why is user() null" cause. auth:sanctum in the route but Auth::guard('web')->user() in the controller gives you two different users. Check Auth::getDefaultDriver() and log Auth::guard()->getName() while debugging.
  • Session must be started. Auth::attempt() returning true yet the next request being anonymous means the session isn't persisting — missing StartSession/web middleware group, session driver set to array, or a mismatched SESSION_DOMAIN/SESSION_COOKIE for the SPA domain.
  • Credentials keys become query constraints. Auth::attempt(['email' => ..., 'password' => ..., 'tenant_id' => 3]) adds where tenant_id = 3 to the user lookup. That's a feature, but a typo'd key (emails) turns into an unknown column or worse, an always-failing login.
  • The credentials array must contain the password key your model's getAuthPassword() expects (password by default) and the provider must be eloquent with a model implementing AuthenticatableContract. Any other key is treated as a plain lookup column.
  • remember_token column: Auth::attempt($creds, true) needs a nullable remember_token (100 chars) or the login succeeds and then throws on updateRememberToken(). Auth::viaRemember() tells you a session was resumed from the cookie.
  • Logout needs three calls. Auth::logout() clears the guard; you still need $request->session()->invalidate() and regenerateToken(). Skipping them leaves a fixed session id around.
  • Auth::logoutOtherDevices($password) requires the AuthenticateSession middleware on the routes that should be affected, plus the password re-check. Without the middleware it does nothing observable.
  • Auth::routes() no longer exists (removed in Laravel 8). Any tutorial telling you to add it is wrong — use Breeze, Fortify, or write the routes.
  • auth middleware aliases live in app/Http/Kernel.php on Laravel 10 and below, and in bootstrap/app.php (->withMiddleware(fn ($m) => $m->alias([...]))) on Laravel 11+. A missing alias shows up as "Target class [auth] does not exist".
  • Config caching bites auth hard. After editing config/auth.php on a deployed app, php artisan config:cache (or config:clear locally) — otherwise a stale guard/provider map sends you chasing ghosts.
  • Password hashing drift: if HASH_DRIVER changed (bcrypt ↔ argon2id) or the rounds value changed, existing users can't log in until rehashed. Laravel's rehash_on_login (Laravel 11+, config/hashing.php) handles this automatically; on older versions add it to your Login listener with Hash::needsRehash($user->getAuthPassword()).
  • Debugging failed logins: listen for Illuminate\Auth\Events\Failed (it carries $credentials and $user) rather than dumping inside the controller; inspect the resolved guard with Auth::guard()->getProvider()->getModel(); confirm providers.users.model points at a class that actually exists in the config cache.
  • Extend, don't fork. The sanctioned seams are Auth::extend, Auth::provider, Auth::viaRequest, custom PasswordBroker subclasses (rebind auth.password in the container), and event listeners. Overriding SessionGuard methods directly means re-merging on every framework bump.
  • can: middleware and @can silently pass for guests on abilities with no policy — always pair with auth middleware, and Gate::define an explicit deny for the unauthenticated case when the ability is security-sensitive.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
vento/laravel-airbrake
wfeller/laravel-batch
maco-studios/mage-os-installer
busarm/armie
siberfx/laravel-logger
kfteam1991/dcat-admin
dashed/dashed-laposta
dashed/dashed-ecommerce-montaportal
dashed/dashed-ecommerce-etsy
neohq/string-blade-compiler
log1x/acf-composer
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager