Current section: User Sessions 5 exercises

User Authentication and Session Management with Login Forms

Loading solution


00:00 Let's head on over to the login route here and right up here we've got all this regular conform stuff that we've done before. We have parse of the form data and here's our login form schema and we are transforming the data that has been provided. So the data that's provided is the

00:15 username and password. So assuming that those things are correct, they pass their schema, then we get into this transform. Now we've got this section for if the intent is not submit, then we're going to exit early and the user will be null. And that is totally fine,

00:33 this would be like if we're doing some sort of extra verification on the back end. We're actually not going to be doing any of that, but in the future if we ever decided we wanted to do that then this would be where you would place that. So we're going to keep that there.

00:51 Now we're going to find the user in the database. So based on the information that we've got, so we've got our user is going to be await prisma dot, and then that's from our utils there, dot user dot find unique. Yes, Copilot, you got it, where the username matches what they've

01:08 submitted. And let's do a select here. We only want the ID, we don't need like all the things that just would be wasteful. And so then we can say if there's not a user, then we don't want to actually display the user. In fact, we want to show an error. And so we're going to use context,

01:27 but instead of issues dot push, it's add issue. And the code we're going to say is custom. And the message, we don't want to say that there was no user found with that username, that we want to give as little information as possible. So we're going to just say

01:44 invalid username or password. And because we're saying it's either the username or the password, we're not going to specify a path. And then we can return z dot never. So what that is going to do is it's basically a way to say, this login parse is not going to work like there's there's no way

02:02 that this is valid, it is invalid. And so that way, we get an error and our error case right down here gets handled properly. Okay, so if there is a user, though, then we are all set to return

02:18 the data with that user as part of the submission. So we can look at submission, submission, dot value, and then we'll have the password to the user and the username right there. So we can do all of our transformation and everything like when we do have passwords,

02:34 we can do all that stuff in here. And then we can assume that once we get to this point, all of that stuff has been resolved, which is actually quite nice to be able to do it that way. So let's do a slight adjustment right here where we'll say user because if there is no user, then yeah, clearly, there's going to be an error right there, too. So we'll do that. You also notice that

02:55 we're deleting the password from the payload, because that is going to be sent back, probably something that would be good for conform to do for us in the future. And maybe it will. So if it does, I'll add that to the instructions. But as of today, I don't want to send the whole submission

03:10 object back with the password, because it just seems wrong to do that. And so we'll, we'll delete that value out of the submission. Okay, so we're going to get the user from

03:24 submission value. So let's do that const user from submission value. And then we're going to get our session. So I'm going to call it the cookie session is await session storage, we're going to grab that from our utility. And you'll want to be careful because you may have

03:42 noticed here, let's undo that session storage, you may have noticed right here, it's defaulting or auto completing to the session storage, which is a global in the DOM. That is not what we're using. We're using session storage from our app. And so that's what we've got right here. It's

04:00 fine. Even if you accidentally do session storage from the DOM, you'll do something like get, what is it get session requests, and that will TypeScript will be like, whoa, you're using the wrong thing here. So that's good, at least. But yeah, if you ever see that,

04:18 that's probably because you're using the DOM session storage as far as TypeScript is concerned. So make sure that you're importing it. Okay, so then we got our cookie session. And now we're going to set the user ID. So cookie session, set user ID to the user's ID.

04:38 There you go. That's it. And now we need to redirect to add headers. Whoops. And set cookie should be Yeah, Copilot doesn't know how to use this yet. We're going to say session storage dot commit session and pass the cookie session. So let's test this out. If I do something random

04:57 and something random here, then we're going to get username or password invalid. And that's exactly what we want. But then if I do Cody, who does exist, and login, we're in a good spot. So that is the login process. Pretty, pretty stellar, I must say. So let's take a quick

05:16 review here. What we've got is a transform that looks for the user based on the username that was provided. If there's not one, then we use Zod's API's to say, hey, there's an issue and

05:29 return z dot never so that this doesn't parse properly. And we end up in our error case here, we added a user right here, just to say, if the user doesn't exist, then like something is off, like this is not correct. So we will return the error. And then otherwise, we're going to grab

05:47 that user, we grab the cookie session, we set the user's ID in there, and then we redirect. And here, we can take a look at the login, we'll see our set cookie for Ian session is right there. And as a result, we'll see in the application that we have an E and good grief, here we go,

06:07 that we have an Ian session right there. And so now, we should be able to load the user, getting the user ID out of that cookie, we can do so securely because it has been cryptographically