Generating One-Time Passwords and Verification URLs in a Signup Flow
00:00 So let's go to our signup route, and right here we're going to generate our one-time password. So here we'll say generate TOTP, that's coming from Epic Web TOTP. And we want to specify the algorithm as SHA-256, it's more secure than the default of SHA-1.
00:18 SHA-1 is the default because one-time password generators like Google Authenticator and 1Password, they default to SHA-1 and in fact in some cases don't even work with any other algorithm. But because we are the ones sending or generating the one-time password and verifying it, we can send it to a more secure algorithm, which is nice.
00:37 And then we're going to set the period to 10 minutes. So that means that this one-time password we're going to email the user will be valid for 10 minutes, which, you know, you're going to vary that depending on your product manager's decisions. Maybe they want a whole half hour or something like that.
00:52 So this is going to give us a one-time password that we can send the user, and then it's also going to give us a bunch of other things, which might be familiar. That's the stuff we need to store in the database so we can generate another one-time password and verify the one that the user has provided.
01:09 So we're going to collect all these up into a verification config. And with that now, we can create our redirect to URL, so where we want to send the user. So redirect to URL is a new URL. And here's the trick.
01:24 We're going to actually use the redirect to URL to also generate the URL that we're going to send to the user, our actual verification URL that includes the code. And when we send the user that email, we can't just do slash verify because that wouldn't work in the context of email. We need to include the full domain.
01:43 And we could just hard code the domain, but we have previews and we have local host and all that stuff. So we have this utility called get domain URL. That is quite handy. And we'll take the request URL and it knows where did this request come from. That's where we're going to be sending it to the user.
02:02 So that is going to get us the URL that the request came in from or the domain. And then we add slash verify to that. Okay, so with redirect URL, we're going to set the type to onboarding and our target will be the email that the user supplied. So we are onboarding a user.
02:20 And the thing that we're onboarding them with is this email address. And then we will create a verify, verify URL, it's going to be a copy of this. But the verify URL is also going to have, whoops, the verify URL is also going to have
02:40 a code search program that is set to the one time password. So we're going to email the user this. We're not going to redirect them to this because this is the part that they need to verify. But by putting that into the URL, we can pre fill the code for them, which will be quite nice. Okay, great.
02:58 So with all of that, now we're going to add a verification to the database. Now remember, we have a unique constraint on the type and the target fields in the database. So we can't have more than one of that combination. So we're going to use an upsert to do that.
03:14 So we're going to await Prisma verification upsert. And upsert requires a where clause. So we're going to use the target type, there we go, where the type is onboarding and the target is email. Now I don't like having these magic strings.
03:32 So we're going to take this and we're going to extract it to a type right there. And then we can just use that here. Okay, great. And so then the data that we need to supply is actually going to be the same, whether it's an update or a create.
03:48 So I'm going to make a verification data object here that's going to include the type and the target will be the email. And we'll take the verification config, so all those properties from the verification config, like the secret and algorithm, all that stuff.
04:03 And then we'll also set an expires at, which would be a new date that is comprised of date.now plus the verification period times a thousand milliseconds because the period here is set to seconds, but this new date needs milliseconds.
04:21 So we're going to have that times one thousand. I also don't like the magic number right here. So what we're going to do is say verification config. That's not right. Verification config, there we go, dot period. And that will have the period that we specified up there.
04:37 So if we decide to change this in the future, we say we want this to be 30 minutes. We don't have to update it in two places, which is nice. And it also just kind of communicates the intent there, which I think is good. Okay. So with that verification data now, if we're creating, we're going to create a new record with that verification. If we're updating, we're going to update the existing record with the verification data.
04:57 So in any case, that way we don't have to worry about the unique constraint that we have set on there. It will, if there's an existing one, we'll just override it. So that's nice. Okay, great. So now we need to include the one-time password and the verify URL in the email that we're sending the user.
05:14 So we can say, yeah, something as simple as like, here's your code and here's their one-time password and then include the verify URL. Again, like we'll wordsmith this and it'll look amazing later. It's not super critical to get that right right now.
05:32 Okay, finally, before we were bringing in the verification storage and setting the onboarding email session and all that stuff, we don't want to do that now because the user hasn't actually verified yet. And so what we're going to do instead is we're going to return a redirect to the redirect
05:49 to URL and we're going to two-string that thing. And so now the user information should be prefilled. So with all that done, let's try it out. We have bobby at example.com and there it is. Our type is onboarding.
06:07 Our target is bobby at example.com. Let's just also check out the output here. So we've got our code right there and we have our URL right here. So if I were to open that up, then we're going to get this big, ugly error that says it's not implemented yet because it's not. We need to actually implement that.
06:25 But you'll see that we do have the code right there. And in the next exercise, we're actually going to handle this verification. And there's a bit going into that. So we're going to break that up into another exercise.
06:40 So in review, what we did here was we create, let's give ourselves a little bit more room right here. So what we're doing here is we create a one-time password using generateTOTP.
06:55 It's a time-based one-time password from Epic Web TOTP. And we get a one-time password from there and the verification config. Then we're going to create this redirect to, so where we want the user to go. We set the type and target search params there.
07:14 And then we also create a verify URL that includes the code. Then we create a verification in the database and we send the user the one-time password and the verification URL. And then redirect the user to the redirect to URL, which excludes the code.
07:31 So this way they can type in the code if they choose or they can go to the verify URL directly and it will pre-fill everything. And that is what we did in this step. Let's move on to the next exercise where we can actually verify the user.