Current section: Password 5 exercises

Creating and Hashing Passwords for User Sign-Up

Loading solution


00:00 Let's go to the signup route and I'm going to actually start by importing bcrypt from bcrypt.js so that we can see the problem that happens here when we do that. I'm going to bring in a password from our data. So this is all the stuff that Kelly put together for us. Should be pretty familiar if

00:18 you've gone through the forms workshop already. So we just have this transform that transforms the data the user submitted into a newly created user. So part of that newly created user should be a password and so we're going to add a password creation here. Because that's a different table, we're going to have exactly what Copilot wants,

00:37 create and then our hash will be generated by bcrypt. Now, that actually should be everything. We should be done, but we've got a little problem here. If we look at our output from our server, we're going to see that the node built-in crypto, which is imported by bcrypt, must be polyfilled for the browser.

00:57 So you can enable that. You can polyfill crypto and send that to the client if you so desire. But it's an enormous polyfill and we aren't even using bcrypt in the client at all. Now, Remix is pretty smart about separating things. But the biggest problem here is that this module resolution happens

01:15 before Remix gets a chance to separate things out. So that's why crypto and bcrypt end up in the client here. So where did bcrypt go? There it is. So as the module resolution is happening before Remix gets its chance to separate things out, ESBuild is going through and it's saying, okay, so here's bcrypt,

01:34 let's dive into bcrypt and bcrypt depends on crypto. So that means you're going to need the crypto polyfill and then things blow up in a not so nice way. So we have a pretty simple solution for this. We can actually create a special file that has a dot server in the name,

01:51 and that will signify to ESBuild and the plugins that Remix has, that there's no chance in the world that this file should ever end up in the client. And that way the module resolution doesn't even go there for the client side. So let's make an auth dot server because we're going to need this eventually anyway. And we're going to import here,

02:11 actually I'll just steal that import from here and we'll export bcrypt. And then we can import bcrypt in this way. So coming down here, we'll just let the editor do this for us because who writes their own imports anyway. And so with that, we get bcrypt being loaded

02:29 and our rebuild is totally happy and everything. And of course, this is not the end result. By the time we're done with this workshop, we're not going to be exporting bcrypt from this auth server. We're actually going to put all of our bcrypt related utilities just in this file directly and call those. But this is totally a fine solution

02:48 for other types of things where you're like, wow, this is a server only thing. Let's just stick it in a dot server file. And now we don't have to worry about that module resolution stuff. So let's make sure that this actually does work. So we're going to say bobby at example.com and Bobby is the username. Bob is the name. Bob's your uncle is a password.

03:09 And I agree to the terms of service. Ta-da! Now we're logged in as Bob and we've got a profile. So as a quick review, the biggest complicated things that we had to do here is we had to stick our bcrypt import in a server only file

03:26 to ensure that bundling excludes bcrypt and all of its dependencies, even during module resolution. So we put this in an auth dot server, which we're going to have eventually anyway. And then we are able to import bcrypt from that file. And then we just modify this form

03:45 that we have done before with this conform and Zod stuff that we've got here. So our Zod schema includes the password schema and all of that stuff. And so by the time we get to this transform, we know everything is valid. We can take that password as is and create a row in our password table

04:04 for this newly created user. And that gets us a newly created user with a password. Good job.