Current section: Verification 5 exercises

Verification Flow and Dynamic Query Parameters

Loading solution


00:00 Let's go over to the verify route and right up here we're going to add the type because we do set the type in our query params up here but we don't actually render the type and we could just hard code it as onboarding but we know that we're going to be having other verification types. We're

00:16 going to add two-factor authentication and stuff like that. So we're going to add a type query param here. Export const type query param. This is going to be the type and then we're going to need

00:29 a schema for validating that the type is valid and so right now we only have one valid type but we'll have more in the future. So we're going to say types is onboarding and we'll say this is

00:43 as const. That way it literally is an array that has this string onboarding. That's all and from that we can create our verification type schema which will be a z enum of those types and we can

01:00 also in the future we can like export the type of that schema and we'll be doing that but Kelly will handle that for us and that will be useful in the future you'll see. Okay great and then we're going to add the type query param to the schema and so that's going to be our verification type

01:17 schema and so now we're going to actually verify that that is submitted as well so we have the access to that when we're grabbing the verification from the database. Okay great so let's go down to our UI actually and make sure that that gets submitted properly. So we're going to add the

01:33 type query param here and then we can add a hidden input for the type as well. Input and let's see Copilot's got that yeah now we're talking. So we have just using conform the regular stuff that

01:50 we've done before. Okay great so with that all out of the way we have this validate request. This validate request is actually called inside the loader and in the action and that's why we have it as like a separate thing because when the user clicks on the link they will show up on this page

02:05 and they'll have the url search param set and we'll have the type and the target and the verification and so we can verify it right away for them rather than just filling it in and requiring them to press submit. Now I'm going to add a little caveat to this and that is that there

02:19 are some email clients that will actually hit the email or the links that are inside of emails for spam detection and stuff like that. So because we're going to delete our verification after we've

02:34 verified things then the one we're verifying is actually the who like whatever robot is checking for spam and so when the user clicks on it that verification will get deleted and it's gone forever.

02:47 So this is definitely a trade-off that you might consider doing something in the future where you say we're not going to actually validate the request we'll just pre-fill it and so like to do that you'd literally just say pre-fill with all of the data that they have available to them

03:05 and then require them to hit submit. So there are just some cases where you might consider doing something like that instead but in our case we're going to validate the request in both the loader and the action and now we're going to actually go and retrieve the verification. So let's get our

03:21 verification is await prisma dot verification find unique and let's bring in prisma from there there we go and our where clause it's going to say the it's actually I think it's the target type

03:37 there we go and the the target is going to come from the data and the type is going to come from the data also but this is going to be the type query param so that's going to be the value of that and actually we I like to do things this way target query param that way we keep these things

03:57 in sync and in fact to make this even better let's go to sign up and we'll come over here and update these to use those as well that's why we're exporting them type query param and our target query oh actually no we don't want to set that we want to set this there we go type query param

04:15 and this should be the target query param and then we have our code query param there we go okay cool so that way like I want to get rid of as many of these magic strings as we possibly can so

04:31 there we go with that and then our where clause is actually not complete because I also want to verify that we aren't getting a verification that's expired so we're going to add an or clause here to say that it's it either shouldn't have an expiration at at all

04:50 or it should have an expiration that is less than the current date so we're going to say the expires at should be greater than the current date or it should be null it should be one of whoops it should be one of those two things so we've got our verification and then there we go

05:12 now we just have to add an issue if there is no verification so if there's not a verification then we're going to do actually pretty much the same thing as this below here so we've got a context at issue on the code it's a custom type of issue and the message is invalid code

05:32 then we're going to return z.never which will make sure that our types are all happy and all good okay great and then finally we're going to use the verify code util from epic web totp and

05:46 that is not auto importing for some weird reason so we're going to import that from totp there it is right there okay and let's see maybe I spelled it wrong verify totp there it is okay so it's

06:01 verify totp and it takes the one-time password as well as all the verification arguments so we're going to say otp is going to come from our data code query param and then the rest of this

06:17 is going to come from our verification and with that we'll know whether the code is valid and if it's not then we'll send an error otherwise we're good to proceed and so in that case we'll handle our errors and whatever right here and then we can proceed as if everything is good

06:35 which of course it will be because we are only submitting good errors so we're going to get our we're going to call this the submission value from our submission and then we're going to delete the verification so await prisma verification delete and our where clause

06:54 it's going to have the target from those values there we go and so now that verification will be gone from our database freeing ourselves up from potential issues in the future just having an

07:09 ever-growing database of stuff that is unnecessary and yeah then we're going to do the same thing that we were doing in signup before we verified the url or the user their email now we're going to do that over here so i just gave that to you in here or cody gave that to us because um yeah

07:26 we don't you already did that so we're just copying this over from our signup stuff and we have our onboarding session key and then our redirect right here so we're setting the onboarding

07:38 email session to the value that submission value that we have and redirecting the user to onboarding so that we're basically transferring this data from this page to the onboarding page and that

07:55 um that is that and what's cool about this is that now the way that we have this structured there's no way for a user to get the onboarding email session uh the onboarding email set into their cookie unless they've gone through the verification process and so once the verify

08:14 session has this value in there we can be totally confident that the user has verified this email address which i think is pretty rad so let's try this out we're going to say hannah at example.com

08:27 and there we go let's come over to our output right here and this is to hannah at example.com here's our code so we could copy this and paste it right in there and that would work or i can

08:41 copy this and paste it right here and boom that takes me straight into the onboarding flow and if i were to actually since i'm still here if i were to try to submit this code now this will not work

08:54 because that verification has been deleted at this point so invalid code but i do still have that onboarding email in my session and so i can't continue to onboard until that expires of course so our onboarding process is all set we can actually verify the user is who they say they are

09:15 and now what we have is created this thing that we can actually use for doing all sorts of different kinds of verifications so what kelly the co-worker is going to do to this file is just fill it with a a bunch of nice pieces of abstraction that will make it easier for us to use this

09:34 same stuff for verifying other things like two-factor auth for example so let's quickly review and then i'll let you go um to go take a break so what we did here was we added a type

09:49 query param we added some verification on that type so we put that in our verify schema and then down in our ui we included that in our default value and added that to our hidden inputs

10:04 so that would get submitted from the url search params the user will never have to enter that those values and then in our validate request we got the verification from the database making sure

10:17 that it's not expired and we're grabbing the values for target and type from the submission so we're going to get whatever whatever they entered as their code that doesn't matter we're going to get this from the url search params the target that we're verifying so the user's email

10:36 and then the type which in our case is onboarding and all that stuff is available in the search params right here there's nothing secret about that that's that's fine so we're grabbing that information right there to get our verification if that doesn't exist which is the case when i submitted this then we're going to send back an error that says hey invalid code we're not going

10:54 to give them a ton of information just enough to say hey you got to try that again and then we're going to try and verify the one-time password the time-based one-time password with verify totp and if that code is valid oh and we're going to pass in the verification stuff that we got from the data database that that's why we stored it in the database in the first place

11:14 and then we're going to take the data that they submitted which will include the code so that code right there and that will be the one-time password we're trying to verify if it is valid or if it's not valid then we'll return an error if it is valid then we're good to

11:29 proceed so we come down here we grab the submission value we delete that verification from the database and then we do the same thing that we were doing in in our sign up before we did all of this actual verification stuff which is to grab the verify session set the onboarding email

11:48 session and then redirect to onboarding and then onboarding can use that in its stuff right here so here first it has this require onboarding email that we did earlier and that from that we can

12:04 actually create the user information so we do the signup process with that email now the user doesn't even have to enter their email in the onboarding flow because that's stored in their cookie after being verified so there that is the verification flow great work