Courses
/
Getting Started with Laravel
/
Basic authentication: Login/Logout
Basic authentication: Login/Logout
Complete the authentication system with login and logout functionality. Learn about sessions, middleware, and protecting routes from unauthorized access.

I've created at least two accounts now, mostly because I don't have a sign-in page just yet. So let's fix that—we're almost done!

Users can register, but what happens when they come back tomorrow? They need to log in! Let's complete our authentication system with login and logout functionality. This is the final piece to make Chirper a real multi-user application.

Step 1: Create the Login Form

Let's make it so we don't see that 404 Not Found error again when we try to visit the login page.

In our resources/views, we have the auth directory for register. I'm going to create a new file for login.blade.php. We can start with the register page itself and just make changes, or you can just paste in what's in the lesson. There's nothing too crazy here—it's exactly what the register page is, just with fewer fields and directing to a login method.

Create resources/views/auth/login.blade.php:

</x-layout>

You can start to tell how a lot of this is repeatable in the sense of once you get the hang of what a form looks like, especially if it's a form that has similar fields, the next time you implement that form, it's going to be a lot easier. And Laravel just makes it easier too.

Step 2: Create Login and Logout Controllers

We created an Auth/Logout class already in the previous lesson for demonstration. Now we just need our Auth/Login. Following Laravel's single action controller pattern, let's create separate controllers for login and logout:

If we go to our Login auth controller, this is our invokable single-class controller. This is going to be one of the few controllers that's a little bit different, but only slightly. We're going to pull in that Auth facade.

In app/Http/Controllers/Auth/Login.php:

}

What this Auth facade is doing is we're using the attempt helper with this facade. We're taking the credentials that we've been given (this email and password), we're attaching the Remember checkbox if they gave that, and we're requesting a new session—we're regenerating that new session.

This attempt helper automatically has that remember variable. If it's false, it's false by default. Otherwise, if we pass that in, then it's true. This is doing all the heavy lifting for us.

Then we'll return back. Otherwise, if the auth attempt fails for whatever reason, then we're going to return back with errors. This is a neat little return helper to say, "Hey, we're returning to the previous page, regardless of where that was."

In app/Http/Controllers/Auth/Logout.php:

}

And seeing that we're requesting this session to be regenerated, it reminded me that I think we want to invalidate the session as well in the logout controller. So instead of just logging out this user, we can actually simplify this with Auth::logout() because we already know the authenticated user. Then we can say we need the request session and we're going to invalidate that, as well as regenerate a new token, so that way the user who is then not logged in still has a fresh token.

Step 3: Add Login/Logout Routes

Let's go ahead and add this login route to our web routes. In routes/web.php:

We want this to be a named route because we are using named routes. What we do need is the Route::view() to be able to pass in the /login page to the login view. And this is where we can have the middleware of guest and the named login route.

Why don't we name the logout as well, even though I don't think we're using it anywhere, but it's also helpful just in case we wanted to use it.

Note: Laravel automatically redirects to /login when an unauthenticated user tries to access a protected route. That's why we name it login.

Step 4: Update Chirp Component for Auth

Now we have this login page, and we should be able to log in with our previous email that we created. The logout button should work even with the named route.

If you haven't already, let's make sure we update resources/views/components/chirp.blade.php to properly check ownership so that way we know if the user can or cannot update or delete a chirp:

</div>

This ensures that we only show the edit and delete buttons for chirps that the current user owns.

Step 5: What is this "Remember Me" Functionality

Laravel's "Remember Me" feature:

  • Creates a long-lived cookie

  • Allows users to stay logged in between browser sessions

  • Automatically re-authenticates users when they return

The remember_token column in the users table stores this securely.

Testing the Complete Flow

Let's test the complete authentication flow:

  1. Logout if you're logged in (click logout in the nav)

  2. Try to create a chirp - you'll be redirected to login because of our middleware protection

  3. Log in with your credentials

  4. Check "Remember me" to stay logged in

  5. Create a chirp - it works and shows your avatar!

  6. Close your browser and come back - still logged in thanks to the remember token!

We are using the default authentication, the auth helper, and facade that Laravel gives, which includes remembering us and remembering that session.

Security Features

Laravel automatically protects you from:

  • Session hijacking - Sessions are regenerated on login

  • CSRF attacks - All forms require CSRF tokens

  • Password exposure - Passwords are hashed with bcrypt

  • Timing attacks - Password comparison is constant-time

  • Session fixation - Session IDs change after login

What We've Built

Just to recap what we've accomplished: if we try to create a chirp, because we have middleware attached to any of the POST methods for creating a chirp, editing a chirp, or anything like that, we can't do it unless we're authenticated. It takes us directly to the login page. We can register a new account if we'd like, or log back in with existing credentials.

Congratulations! You now have a complete authentication system:

  • ✅ User registration

  • ✅ Login with "remember me" functionality

  • ✅ Logout with session cleanup

  • ✅ Protected routes with middleware

  • ✅ User-specific content and permissions

Your Chirper app is now a real multi-user application where:

  • Anyone can view the chirp feed

  • Only registered users can create chirps

  • Users can only edit/delete their own chirps

  • Each chirp shows the user's avatar and name

We have the ability to add new chirps, and we can see that each chirp is attached to our particular user with our avatar. Logging out and signing in with a different email means that I cannot edit or delete chirps that another user created, but I can definitely edit and delete my own chirps. Full CRUD functionality!

Quick Design Update

Thankfully, the Laravel team has a TON of incredible designers who can help us make this look a lot better with just a small handful of changes. Now, the majority of these changes are all done in the app.css file for simplicity sake. Typically, within a modern application that uses TailwindCSS, you would modify the markup (HTML) itself. However, since I want to have you change as little as possible within your application, we are doing some things that wouldn't be considered "best practice."

That being said, the benefit of modern CSS with Laravel by using something like TailwindCSS is that everything just works. After all, Blade template files like we mentioned at the start is just HTML with some added niceties. All of Laravel's starter kits have TailwindCSS included out of the box so it's nice to learn to embrace it when at all possible.

In your resources/css/app.css file, we can add the following changes after the existing code:

Next, we added some Favicons and an OG image and referenced them in our resources/views/components/layout.blade.php file. If you would like to use those for your application you can find them in the Github repository here.

In that same Layout file, we have a new logo to add. This can replace the existing button logo that we were using with our cute little bird emoji and our existing footer respectively.

Next, to better match the new design, we can remove the shadow styles from our card elements in our resources/views/components/chirp.blade.php and the resources/views/chirps/edit.blade.php files.

Lastly, we can modify the h1's of the Register and Login view files to use text-xl mt-1 instead of the previous text-3xl.

Looking good!

Laravel Auth Starter Kits

Building auth manually taught you how it works, but in real projects, you'd often use:

  • Laravel Starter Kits - Ready-to-use authentication scaffolding with complete user interfaces

  • Laravel Fortify - Headless authentication backend for building authentication from scratch with your own UI

  • Laravel Socialite - OAuth authentication with providers like GitHub, Google, Facebook, Twitter, and more

These provide production-ready auth with email verification, password resets, two-factor authentication, and more!

Now, it might seem simple, but give yourself a round of applause—we just created your first Laravel application with complete authentication! Next up: Let's wrap up and talk about what's next in your Laravel journey!