The auth middleware locks a route so only logged-in users get through, and a guard is the rulebook that decides how Laravel recognises those users.
πPicture a club. The bouncer at the door is the auth middleware: no wristband, no entry. The guard is the club's policy on what counts as a valid wristband. For the main room that's a paper wristband (a session), and for the VIP API lounge it's a scanned QR code (a token).
Logging in is only useful if pages check for it
Private pages stay private
One word, auth, keeps strangers out of dashboards, settings and drafts.
Personalise everything
Once you can read the current user, you can show their name, their posts and their settings.
Smooth redirects
Guests get sent to login, and logged-in users skip the login page. Both are configured in one place.
What the auth middleware does
| Middleware | Lets through | Otherwise | Typical routes |
|---|---|---|---|
auth | Logged-in users | Redirects to /login | Dashboard, settings, βnew postβ |
guest | Visitors who are not logged in | Redirects to the home/dashboard | Login, register, forgot password |
Lock pages down and use the current user
-
Protect routes with
auth(andguest)Add the middleware to a single route, or wrap a whole group so you can't forget one.
use App\Http\Controllers\PostController; Route::get('/dashboard', fn () => view('dashboard')) ->middleware('auth')->name('dashboard'); Route::view('/login', 'auth.login')->middleware('guest')->name('login'); Route::middleware('auth')->group(function () { Route::resource('posts', PostController::class)->except(['index', 'show']); });Here anyone can read posts, but only logged-in users can create, edit or delete them.
-
Read the logged-in user
There are three common ways to get the current user. They all return the same
Usermodel, ornullfor a guest.use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; public function index(Request $request) { $user = $request->user(); // from the request (great in controllers) $user = Auth::user(); // facade $user = auth()->user(); // helper $id = Auth::id(); // just the ID $loggedIn = Auth::check(); // true / false $posts = $request->user()->posts()->latest()->get(); return view('dashboard', compact('posts')); }The
posts()relationship comes from Relationships. Using it means each user only ever sees their own posts. -
Show and hide things in Blade
Use
@authand@guestto switch parts of a layout. Inside a view,auth()->user()works too.<nav> @auth Hi, {{ auth()->user()->name }}! <a href="{{ route('dashboard') }}">Dashboard</a> <form method="POST" action="{{ route('logout') }}"> @csrf <button>Log out</button> </form> @endauth @guest <a href="{{ route('login') }}">Log in</a> <a href="{{ route('register') }}">Register</a> @endguest </nav>β οΈ Hiding a link isn't protection@authonly changes what's displayed. Anyone can still type the URL directly, so the route itself must use theauthmiddleware. -
Log out properly
Logging out takes three lines: forget the user, destroy the session and issue a new CSRF token. Always use a POST form, never a plain link. Otherwise another site could log your users out with a simple
<img>tag.use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; Route::post('/logout', function (Request $request) { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/'); })->middleware('auth')->name('logout'); -
Meet guards in
config/auth.phpA guard defines how users are recognised on each request. A provider defines where they're loaded from. The default
webguard uses the session plus theuserstable.'defaults' => [ 'guard' => env('AUTH_GUARD', 'web'), 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'), ], 'guards' => [ 'web' => [ 'driver' => 'session', // remember users with a session cookie 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => env('AUTH_MODEL', App\Models\User::class), ], ],Most apps only ever use
web. APIs add a token-based guard, likeauth:sanctum(see Sanctum). You can pick a guard explicitly withAuth::guard('web')->user()or->middleware('auth:sanctum'). -
Change where people get redirected
In Laravel 11+, you configure redirects in
bootstrap/app.php. There's noHttp/Kernel.phpany more.->withMiddleware(function (Middleware $middleware) { // where `auth` sends guests, and where `guest` sends logged-in users $middleware->redirectGuestsTo('/login'); $middleware->redirectUsersTo('/dashboard'); })By default, guests are sent to the route named
login. If your login page has a different name, this is the place to fix it.
Avoid this, do that
public function index()
{
if (! Auth::check()) {
return redirect('/login');
}
// ...
}
Repeating the check in every method is easy to forget, and one missed method means a leaked page.
Route::middleware('auth')->group(function () {
Route::get('/dashboard', ...);
Route::get('/settings', ...);
});
Declare protection once, at the route level, where it's visible in route:list.
<a href="/logout">Log out</a>
A GET logout can be triggered by any page on the internet, and it skips CSRF protection.
<form method="POST" action="{{ route('logout') }}">
@csrf <button>Log out</button>
</form>
A POST form with @csrf can only be submitted from your own site.
On pages guests can see, auth()->user() may be null. Use the null-safe operator: auth()->user()?->name.
- Create a
/secretroute protected byauth, and visit it while logged out. Where do you end up? - Visit
/loginwhile logged in and check that theguestmiddleware redirects you. - Add a nav bar that shows the user's name with
@authand login/register links with@guest. - Change
redirectUsersToinbootstrap/app.phpto/postsand test it. - Open
config/auth.phpand find thewebguard and theusersprovider.
Key takeaways
authmiddleware = members only;guestmiddleware = visitors only.- Get the user with
$request->user(),Auth::user()orauth()->user(). @auth/@guestchange what's shown, but routes still need middleware.- Log out with POST:
Auth::logout(),invalidate(),regenerateToken(). - A guard decides how users are recognised (session, token), and it's configured in
config/auth.php. - Redirects for guests and users live in
bootstrap/app.php.