Defining Login Routes 0:00We wrapped up the previous episode by creating a login link, but we haven't yet set up the endpoint for that. Alright, let's get going. I'm going to go to my routes file, and let's duplicate this and say, let's make a get request to slash login, and that will hit a sessions controller at create. But now, while we're here, we should also consider middleware. Would it be appropriate for a signed-in user to access the login page? Well, no. You don't need to log in. You're already logged in. So let's also add a middleware of guest to this. But then this particular one would be the opposite, wouldn't it? In order to log out, you have to be logged in, which means a guest can never log out. It wouldn't make sense. So let's add the inverse, middleware auth. You have to be authenticated in order to reach this endpoint, or at least this controller. Okay, so let's go ahead and add our create action, and we'll return view sessions.create, Building Login View 0:47auth. You have to be authenticated in order to reach this endpoint, or at least this controller. Okay, so let's go ahead and add our create action, and we'll return view sessions.create, like so. Alright, in my views directory, add a new folder called sessions, or login, or whatever you want. Sessions.create.blade. Now, one more time, I'm going to copy this, but usually, repeatedly copying little blocks of HTML is my signal that maybe I'm missing a component or two. But for now, I want that pane to guide me towards the refactor. So I'm going to duplicate this one more time, like this, and then we'll say log in. Alright, let's have a look. Refresh, and we have our login. Okay, so actually, on that note, I think I can reuse some of this form from the registration page. So I will copy all of that, and then we'll just pick and choose what we need. Our button will say login, and by the way, these form inputs can also be extractedform from the registration page. So I will copy all of that, and then we'll just pick and choose what we need. Our button will say login, and by the way, these form inputs can also be extracted to a component, which we will plan on doing. You need to give us a password, you need to give us an email address, and maybe that's it. No username, and no password. I'm sorry, no name. That's all you need, and then we will make a POST request to Sessions. Okay, I'll let you have a look at that, and let's see how it looks in the browser. There's our login. So yeah, think about it. When I submit this, we have decided it's going to make a POST request because we are creating a new resource. This is a basic RESTful pattern. If you'd like, we can dedicate a whole lesson to resourceful controllers and some of these conventions, if you like. But yeah, right now, it's going to make a POST request to this endpoint. So, and actually on that note, if I provide anresourceful controllers and some of these conventions, if you like. But yeah, right now, it's going to make a POST request to this endpoint. So, and actually on that note, if I provide an email address and a password and log in, we're of course going to get a 404 because we don't have an endpoint set up yet. Okay, let's create a POST request to slash Sessions, or again, yeah, like if you want, you don't have to follow these patterns, or you can conditionally decide, oh, it doesn't make sense in this case. So let's say you decide in this particular case, you don't want it to be Sessions, you want it to be a POST to log in, then that's totally fine too. It doesn't matter. It's entirely a preference thing. So if we took that approach just to show you that we can, yeah, that would be fine as well. Doesn't matter. You can even switch from a Sessions controller to a login controller. Again, that's the fun part of being a programmer is that you Implementing Login Handler 3:24you that we can, yeah, that would be fine as well. Doesn't matter. You can even switch from a Sessions controller to a login controller. Again, that's the fun part of being a programmer is that you get to decide how you go about naming things and coding things and approaching tasks like this. Sort of like how every musician has their own trademark and their own style. The same is true for programming. Anyways, that's going to hit a store action where if we create that method now, this is where we, let's write it out. We should attempt to authenticate and log in the user based on the provided credentials. So that's one thing we have to do. We would also need to validate the request in general, like let's make sure you give us a valid email and things like that. And then of course, redirect with a success flash message. That's basically what we're trying to do here. Okay. Validate the request. We already know how to do this. Request, validate,that. And then of course, redirect with a success flash message. That's basically what we're trying to do here. Okay. Validate the request. We already know how to do this. Request, validate, and the email address you give us is required. Now we could optionally add a exists constraint. So we could do something like this. You've already learned about unique. Exists would be the inverse. This is saying, okay, we need to find an email address that exists on the users table and specifically in the email column that matches what you provided in that input. And if we can't find one, the validation is going to fail. So you might want to do that. There could even potentially be security concerns with that. If somebody wanted to figure out is such and such user or is such and such email address registered for the site? Well, that would be one way to confirm it. Just try to log in with that email. And if the validation says no account exists,user or is such and such email address registered for the site? Well, that would be one way to confirm it. Just try to log in with that email. And if the validation says no account exists, you now know that person isn't registered here. So that's potentially a security issue. It just sort of depends on what you're building. For now, why don't we just say, you got to give us an email address and you got to give us a password. And we're going to keep this one fairly sparse. Now, assuming that validation fails, the next step is attempt to log in. We're going to use that auth facade again or auth helper. We've already learned about log in a user, check to see if a user is logged in. There's one to check to see if we have a guest. But the next one you're going to learn is attempt. Attempt to log a user in with the given credentials that we provide here. Okay, the credentials are going to be what you provided in the form. So let's pass those through.going to learn is attempt. Attempt to log a user in with the given credentials that we provide here. Okay, the credentials are going to be what you provided in the form. So let's pass those through. Now, let's say that you do provide a valid email and a valid password that matches up. In that case, you're now signed in. Auth attempt does both of those. It takes care of signing you in, but it also takes care of confirming that you provided the correct password for the given account. It does both. So if that's the case, let's go ahead and redirect to the home page. We're down to this step with a success flash message. And how about welcome back? Like that. But now what about if authentication failed? Auth failed. Well, in that case, we need to effectively display a custom validation message. An easy way is to return back, and we're going to set the error back. So think about it. When validation fails up here, Handling Auth Failures 6:43we need to effectively display a custom validation message. An easy way is to return back, and we're going to set the error back. So think about it. When validation fails up here, Laravel just automatically and magically does that for you. But we've gotten past that point. But we still have what's effectively a validation error. So we're going to redirect back, and in the session, we're going to set that errors variable that we look for in the view. So what are we going to match up? The email address? And we'll say the provided or your provided credentials could not be verified. Yeah. Okay, let's give it a shot. We will log in, and let's try to log in somebody who doesn't exist. And there we go. Your provided credentials could not be verified. Although do notice that we lost the email. That's because we have to explicitly include it. So these are the sorts of things that happen automaticallycredentials could not be verified. Although do notice that we lost the email. That's because we have to explicitly include it. So these are the sorts of things that happen automatically by Laravel when you call request validate. That's why it's so useful. Otherwise, we have to say, well, include the old input. So have a look here. Flash an array of input to the session. And the input data is what the user typed into the inputs. So now if I try this again, it'll redirect back, but it also flashes the input. Now, I did say there were two ways to write this. This is totally fine and super common. The other option would be to throw a validation exception, illuminate validation, validation exception that you see up there with messages. And in this case, we're going to do the exact same thing where I pass the array here, like so. So if we throw this exception, it's going to behave very similarwith messages. And in this case, we're going to do the exact same thing where I pass the array here, like so. So if we throw this exception, it's going to behave very similar to if validation fails up here. Have a look. We run it, and you get the exact same thing. And basically what's happening here is when we throw an exception, behind the scenes, Laravel's handler is going to check, well, was a validation exception thrown? If that's the case, why don't we convert it into the proper response and redirect back? So this is often the approach I will take. But again, you're free to choose what you like best. So I will let you take a look at this. We know an invalid user can't sign in. But what about somebody who has a valid email address but again provides an incorrect password? Well, that's going to fail as well. Let's do it correct now. I think I did password. And there we go. Only in this case do we redirect to the Considering Production Security 9:21address but again provides an incorrect password? Well, that's going to fail as well. Let's do it correct now. I think I did password. And there we go. Only in this case do we redirect to the home page, and we say, welcome, Jeffrey Way. All right. And that is effectively the 101 for a basic registration system. We have pages and forms to register, to log in, to log out. But in fact, there would still be even more. We would need to, in a real-life application, handle the scenario where the user has forgotten their password. So they'd need a way to request a password reset. But we're not going to go that far, because as it turns out, if you want to take this manual approach, absolutely do it. But there's also starter kits that Laravel provides that gives you all of this functionality out of the box, even basic fundamental things like log-in throttling or even, on that note, session fixation handling. This is kind of ayou all of this functionality out of the box, even basic fundamental things like log-in throttling or even, on that note, session fixation handling. This is kind of a aside. Let's have a look at this. Session fixation is another form of web attack. The attacker tricks the user into using a specific session ID, and after the user logs into the web application using that ID, the attacker uses this valid session to gain access to the user's account. So as a general good practice, whenever you sign a user in manually, you also want to regenerate the user's session. These are the sorts of tricky little things that you just need to know about, or, of course, refer to the documentation where there's surely a note about that. But yeah, those are the sorts of things you need to be aware of when you write this code manually.are the sorts of things you need to be aware of when you write this code manually.