User Sign-Up 🚀 Verify/Confirm Email & Forgot/Reset Password with a .NET 6 Web API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey friends it's me patrick god thank you so much for clicking on this video today we're gonna cover a part of an authentication process or a user sign up process you name it i think lots of you guys wanted to see an implementation for an email verification or confirmation again you name it and also a forgot password feature so the main part of this tutorial is we will implement the verification of an email address and also a feature for for getting the password so if the user forgot the password forgot the password then the user will be able to reset it and by the way if you are a student of my blazer e-commerce course i know you want to have this thing with the blazer web assembly front-end and it is coming and depending on when you're watching this this might be already implemented and uploaded to the course please little patience still and you will get this feature soon in the blazer ecommerce course all right but for now what we're going to do is we will start from scratch so we will implement a cubic user registration and login process with no json web token i've got another video for that so please check out the info cards here there are a couple of info cards here in this tutorial maybe you want to have a look there but for now here we will only well not only it's still one hour of a tutorial where we will register a user store this user in the database so we will also use entity firmware core migrations code first migrations store this user together with the password hash and assault and also tokens for verifying the email address and also a token for the password request the password reset request all right so register user log the user in verify the email and reset the password so this is what we're going to do and if you learned something and like this video then i would really appreciate it if you click the like button maybe subscribe to my channel it does make a difference thank you so much for doing that don't forget the bell icon to get a notification when a new video is online also maybe you want to have a look at my newsletter because then you get these videos here earlier in your inbox and you will also get early access to my upcoming courses for instance to the big.net web developer boot camp we cover the back end the front end and also some other stuff like git agile software development devops maybe stuff like that and the last thing today it's a mix of tea and coffee i know maybe it sounds disgusting but first it was coffee and when the coffee was empty i i put some tea on top still tastes pretty nice so thank you so much for all your support guys i love you forever and as you will see in the video it is late for me at least it's really late half past 10 it's late for me so sun is asleep i'm making this video thank you so much for watching already and now enjoy the tutorial all right visual studio 2022 we create a new project and this shall be an asp.net core web api we call this verify email and for god password tutorial isn't this a great name okay i think you get the idea then we leave everything as it is so dot net 6 is our target framework https all right controllers yes the traditional controllers i don't want to use minimal apis here and we enable open api support because we will test this with swagger we are not going to build a front end here we will use swagger to test our end points and when this is created this project then the very first thing we need i see something in my taskbar there it is okay let's close this and let's just have a look yeah all right everything's fine okay empty project here you know what this is i guess you see the standard default example with a forecast class focus controller and so on but i really don't want to go deep into that for that we've got another tutorial the web api and ef core tutorial with dot net six almost 200k views for the time of recording this year so guys thank you so so much for all your support maybe you also want to like and subscribe thanks thanks by the way it does make a difference but now to our actual tutorial what we want to do is we want to register a user we want to lock this user in but this user should have to verify the registration first so the idea is to send an email we won't send an email got another tutorial for that so please check this one out and email it's actually from last week we can do that but what we will do here then to enable that with the verification is we will create a token which is in essence a random a random string with random characters and this will then be used to verify the the user email address and then after that we will also implement for got password the for good password feature and this is in essence pretty similar we will also create a token for that okay i talked enough about that i guess let's let's let's implement that stuff so the first thing is the user model and for that let's just add a new folder call this models because we will also need some more stuff we will use some ddos data transfer objects um but first the actual model is the user and we will also use entity from a core code my code code first migrations to add a users table and this user here then in the database definitely need more coffee because it's late and i don't know can't focus that much but i'm sure you will learn a lot today so please stay with me here first thing we need is an id and then the next thing already the email address let's just call this email and this shall be an empty string [Music] then the next thing is the password and if you followed my other tutorials already you know that i want to use a byte array with a password hash and also a password sold let's just initialize that with a new byte array by the way you can also see that in my skillshare class so maybe you want to have a look there if you haven't already but also in the dot net jump start or the blazer e-commerce course so lots of stuff where we use similar approaches and go deeper there of course so these are password hash passwords all the only byte array properties the next thing now already this is what i wanted to tell you is the verification token right so when a user registers we will create a verification token this has nothing to do with adjacent web token for instance it's just a series of random characters and then the user has to call a certain endpoint where the user will use then this verification token and we will then check is this token valid by just looking for a user with that token and if we find a user then the user well is verified alright so this is in essence the whole magic and what we also want to do is we want to store the date when the user called the certain endpoint because then we know that this is done and the user is actually verified okay so this is for the verification and now already for the password reset feature or forgot password password research forward password it's the same thing in essence we wanna use uh well password reset token and this is essentially exactly the same thing right but the date time property here has another function this will actually be the the exp the expiration date for this password reset token maybe this should only be available for one day just out of security reasons right okay so that's it we've got an id email password hash insult verification token verified at password reset token and reset token expires though this is our model of course you can do much more here but i try to make this quick i think this tutorial will take some time nonetheless but uh you know just wanna give you a jumpstart tutorial here so uh you just get the idea pretty quick okay so this is our model and now let me already use code first migrations with entity firmware core entity framework core here so we've got this boilerplate here out of the way first thing we need are nuget packages so right click the project manage you get packages click on browse and then entity frame work i don't need the tools just entity framework could also install this along the way when we create the data context but let's do it this way for instance this time so entity framework or it is and then we also need design share the shared design time components for energy framework core tools all right and then since i want to use sql server we will also need this thing here microsoft entity framework core sql server so these are the three and then we also need the ef core tools and for that we open the package manager console you can do that with view other windows and then where is it package manager con so there it is all right and then [Music] make sure to change the directory to your actual actual project right so here you see the project file and then we can do that dotnet tool install dash dash global and then dot net ef for the enterprise core tools you see it here it's already installed in my case but for you guys i uninstalled this and then install it again and now it's here 605 even got a new version isn't that nice and with dot net ef we can double check there it is all right and you see this here database db context and migrations are the commands we that are available again got videos about that to go or where we go much deeper for now let's just create a data context next and then use the migrations here all right so we've got all the packages we've got the dotnet tool and now for the data contacts that enables us to access the database where we then want to store a user and then see the verification and the password reset token this is why i'm doing this so we can i can really show you how these tokens look then in the database so for that we add a new folder to be a bit organized at least so data it is and here we add a new class we call it data contexts and this inherits from or implements the db contexts all right and now we can use you can use microsoft nd framework core let's make this global maybe and also move this to the program cs great feature of c-sharp 10 global usings well let's see if it's really that great i think you might have more experience by now with these global using strides is it is it maintainable to use global using directives i don't know but in our case in this tutorial this should work we need a constructor here so enter ctor hit tab twice then the argument here is a db context options data context call this options we use our base constructor next step is the data set this is important so with prop and then db set of type u almost user yep that's the one and let's also move this to the program cs so global using [Music] all right let's call this users and usually you just pluralize the name of your entity for the table name because this is the table name and now what i'm going to do you see there's a warning here and i hate this and at least here in the data context so let's just use a set here and then the warning is gone and the last thing this this time i'm doing it here the connection string for our sql server express database in my case and we can do it with the app settings for instance so adding it here a connection string and then using the connection string here or we can do it like that we use overrides and then it shall be on configuring so protected override void on configure ring and here now what we do is options options options builder use sql server that's correct and here now we enter our connection string and this is i guess the only thing where you really have to pay attention because this might be different in your case but if you installed sql server express totally forgot to tell you you have to install sql server of course on your machine or your server wherever wherever you want to do this here and let me let me just google for sql server maybe right so your sql server i know it's on the other screen here it is sql server express this is what i googled for and here is the first hit it should already be the right one and please use here this one you can also use the developer edition or express download now and you're good to go and then there's also another great tool which is the sql server management studio this thing here right so you can download this stuff for free as well and with that then you get this thing here just open it connect to it i've got some databases here already but we will create a new one and then you're good to go and if you do it like this you've got sql server express then your connection string should look like that so server equals and then sql express and then the database name let's just call this userdb for instance and then trusted underscore connection is true all right so server is sql express database is the user db and trusted connection set to true and then you're good to go and the last thing regarding uh the entity framework core boilerplate is registering our db context with builder services and then add db context and we want to use our data context here and this shall be it actually all rights and let's make this global as well okay so this should be it this is now all the ef core stuff and now we can run the migrations so back to the package manager console again make sure to be in the project directory and then we say dot net ef migrations at initial for the initial migration and the build failed awesome.net build let's see what's what's wrong here db context options could not be found okay this is interesting and the frame recorder does not exist but we got it here all right maybe we rebuilt the solution we go back to the program cs and all of a sudden the errors are gone let's try that again but succeeded you're my witness i changed nothing i had to rebuild this and i think this version here 17.1.6 is not a good version visual studio 2022 worked better at the community edition community edition worked better with the previous version but that's just my opinion but maybe you've got similar experiences here so if so please tell me that in the comments would be really interesting if you did so now with that migration we've got this folder here initial and you see we will create a table users with an id that is incremented by default automatically and all the other stuff primary key is the id and in case we want to roll back the migration then this table would be dropped so now let's enter dotnet ef database updates and with that the database will be created even though this command is called updates and now let's refresh our database server and there it is our user database with this table here this table you can be ignored ef migrations history this is just for entity framework but here now we see our users table and of course this is empty but that was already a lot in i don't know 15 minutes maybe and next is actually registering a user and for that we first create a user register request model so right click our models folder at class and then user register requests that's the one and i just want to use an email and a password all right so we've got the email address here by default string empty and then we've got another string with which is the password all right also string empty and then another one called confirm password so we make sure that the user entered the password the user wanted to enter and now let's use also some annotations so we can use the following attributes here and the web app ui web api will check that for us we need another namespace here system component model data annotations if you're wondering what i'm doing here i'm just pressing ctrl and periods this is the same as using the quick fix menu here actually there should be a light bulb but now there is no light bulb i don't know why so you can also just press oh no there's no there it is so using system component model data annotations this is the one i'm looking for also we can add email address so we check if this really looks like an email address now the password of course is also required and we can also say that the minimum length should be six characters for instance and now here confirm password of course you want to check if these two strings are the same so we enter required and then compare and then the name of the other property which is password and with that the web api will then check if password and confirm password are exactly the same so that's great and this is already our user register request model and now to be able to test that we need another controller we've got our weather forecast controller here already but now let's create another one so at controller it is we create an empty api controller full control here for us no generated code well not much generated code and let's just call this user controller and i know i i already can see the the the hate comments in this youtube video i'm implementing a fat controller here i'm not using services and not injecting the services we will inject the data context of course but again i just want to make this quick and don't use any services here but if you want to see that then please have a look at my other tutorials or courses there of course we will use at least i try to use best practices with thin controllers kinda well let's not call it stupid controllers but simple controllers that just forward the requests and then inject other services so usually you would for instance use here a constructor of course and then inject another user service for instance or an authentication service or whatever do all the logic there and then the controller would just forward the request and return the response but here now let's just put all the logic in there and i will push this to kit up of course so you will get the complete code i get the idea i know that this is not best practice but with this disclaimer i hope we're good all right okay so first there it is the constructor we need the data context so let's just inject this thing and here we just call this context and i want to create and assign this field here add an underscore and again also i know that we can configure visual studio in a way that it will add this underscore here by itself but with every update this configuration is gone and i don't know why i don't like that so i'm too lazy to configure it again and again and again but if you have a tip for me uh so that this this configuration here stays with every update then please again tell me that in the comments thank you all right so we've got our constructor and now we can already create our method for registering a user so uh not prop public async task i action result that's okay let's call this register we will use the user register request object called this request and let's also add the http method already which is http post and like that we can enter the endpoint name so change that to register so the complete url would be api forward slash user which is the controller name and then forward slash register all right okay and now the actual method well what we want to do is first we want to check if this user already exists so maybe there is this email address in our database so we don't want to register this user again and we check this with context users with that we can access all the users and then with any and a little lumped expression here u for user and then email if this is jesus equals equals so if this is request email then we just return a bad request and then user already exists and by the way i will use these things here more often as you will see in the next couple of minutes and i will try to to remember to tell you that again it is not that smart to return too much information like that for instance when we try to log in the user and then we say hey can i find the user the email address must be wrong or hey we've got the email address but the password is incorrect maybe this information you shouldn't well you you should tell this the user that is that is trying to log in because this might be an attacker and if an attacker knows hey this email address exists that's great then i can be sure that just the password is wrong and we can run a brute force attack or anything else because we know that this email address is at least correct right so you should not tell this the user although i think it it's a better user experience of course but uh well there are people out there that want to use these information and do bad stuff or fun stuff i don't know in their opinion at least okay and with that out of the way we can create our password hash and for that we need another method but let's write this method here array create password hash and this looks like that we will use the request password and then we will use two out parameters and this will be our byte arrays for the password hash and also the password salt and maybe we can put these in new lines let's try to format this doesn't work yeah of course because the function is not there so let's write this method first create password hash so what will this look like what will this be private void create password hash again this gets the passwords as a string so this is the one from the request and again the out parameters password hash and out bytes password salt okay and this formatting does not work all right anyways and this is pretty simple what to be or small simple and simple i don't know it's it's really simple but it's a small method we will use a cryptography algorithm so using and then bar hmac i call this hmac because we will use the hmac shar 512 algorithm like that and of course we have to use another reference system security cryptography and in here now what you want to do is you want to set the password salt which is the key of this instance so with this instance a key will be generated you can see it here instance of the hmac share 512 class with a randomly generated key so this will be our salt and with that salt then we can create a password hash with hmac compute hash and then a system texts encoding utf-8 get bytes and then password and now you can still not format this and now we get our password hash now a short hint about that why are we doing it like that why the salt well the thing is if you would just use the algorithm without a salt or with the same salt every time we use this algorithm then the password the same password would result would always result in the same password hash and i already talked about some people that want to do bad things here and these people might want to use the password hash and get to the plain text password with that there are algorithm that are not that secure anymore i think md5 is a good example it's always this one way and as a password would always result in the same hash so i don't know if you use one two three four five use the password the cryptography algorithm then the hash would be abcd i don't know something like that and another user uses the same password and then the password hash is also the same so you would see that these users have the same password and again from that hash you might get to the plain text password but this is different with the salt if you use assault and this is in essence just a random series of characters again or of here you see there's a byte array then this would also be put into this algorithm and then the hash looks different it's another hash although the password might be the same okay i hope you get the idea now and this is why we use a salt and a hash and the salt will also be stored in the database because we need the salt to then verify if the given password on login is correct all right enough about that we've got our password hash and password salt and now we can create the user finally as i told you this tutorial will be a bit longer so here is our new user and with that we can say our email is this thing password hash is password hash password salt is the password salt and then the verification token we can already set this so this is maybe a new if you if you know my other tutorials this is something we didn't do or haven't done before create random token this is a function we have to write again so now let's create this function here and again this one is pretty small so private string create random token and here we simply return convert to hex string or base64 string in essence doesn't really matter hex string there's no information in this token so as i said it's not similar to a to adjacent web token for instance where you then store some claims or something it's just a random series of characters and that's why we can use that random number generator and then let's say get bytes and then for instance 64. all right so this will be a long token and we can use it here and we will see how this looks in a minute in the database but with that now we've got our object and now we have to uh store this user object in the database with context users at user and then await context save changes async and after that we return ok well we could return the user or we just say user successfully created all right so let's let's test this i mean it's half an hour but also only half an hour for a simple registration process right so this is actually pretty great i guess we see no user here all right now let's try to register one but first maybe we can we can check the annotations so let's try this out this is the great great thing of swagger here you already see uh the object here for instance the user register request and also a suggestion here so what we can do for instance first let's try to use a wrong email address here so let's hit execute and it says the email field is not well it's not a valid email address great it's totally correct now let's say we use this as a password it says the field must be a string or array type with a minimum length of six all right it's true totally true and now it says confirm password and password do not match now of course you can customize these messages here just real quick we can for instance just enter error message please enter at least six characters dude all right it's rebuilding and now let's see we remove this it executes and we get two error messages confirmed password is not the same and please enter at least six characters dude great love this and now let's just use user x at example.com string string we hit execute and user successfully created awesome there it is and now let's refresh this there is our user we've got the email address password hash installed and this is the token this is how this thing looks like right beautiful beautiful stuff okay so registration works and now the next step is logging in so back to virtual studio we need another model and this model now is called a user login request and this essentially can be copied copied copied copied here let's go back required email address is true required is true here as well but not the minimum length and this should be it already let's also add the using directive yeah this should work and now we can also yep you want to rebuild we can add or implement the login method i'm a lazy guy so let me just copy this and we call this now login and also here login and we use the user login request now we wanna let's just remove this stuff here because this is kind of new then what we want to do is we first want to get the user right so bar user is await wow context users first or default async yep that's totally right nice intellicode at its best okay maybe we can remove this yeah so now you can see everything and if now the user is null and this is what i what i talked about earlier here now we can return a bad request where we can say user not found and again this might be too much information but for this tutorial here for the learning purposes let's just do it like that because we can test this and see does it really work right as we want it to the next check here is already verified at we just want to see is there a value and if there is no value this simply means that the value that the user is not verified and we return not verified okay and add a semicolon of course and now the last thing [Music] is now what am i doing is now the verification of the password and for that we need another method so let's just copy this thing and call this now not create password hash we call this a verify password hash and this now takes also the password but these are no out parameters anymore and in here now we say using bar hmac and then we give this thing the password sort okay i hope now things become clearer and with that we've got our salt of course so we don't need it here now we try to compute the the password hash so let's call this computed hash computed hash all right and this is hmac compute hash so the same thing in essence and now to check if the new computed hash and the password hash are the same we return computed hash sequence equal we have to use sequence equal here because these are byte arrays so with that we compare these two by bytes the simple equals would not work and then here the password hash all right so this is yep this is true we have to change the return type to bool and now this is our verify password hash method and you know we use if verify password hash with the requests password and the user password hash and the user password salt so if this returns false then again return bad requests and we say password is incorrect for instance or wrong password something like that and again maybe too much information but for the learning purpose here i think this is good and if everything is all right and then we simply return something cool like welcome back and then the email address because we have no username so user email nice all right so this is our login methods and i would say we can test this as well although of course this will not work because the user is not verified yet we have no endpoint for that so maybe let's put this here so we can at least check if this works right user not found password is incorrect and if these two are okay then we should get the not verified so let's save this and there we are we can use the same stuff here in a sense so let's try this out what about user 1 at example.com user not found correct what about string1 execute password is incorrect all right and now both not verified awesome so this is the login method for now and maybe now and we we get to the function that you are waiting for and now after maybe 40 minutes we will implement our verify method okay so again let's copy this and paste this here this is now called verify also here verify and now the idea here is totally up to you in essence we can use another request object and another dto where we then put the verification token or we just say string token and get this from the query parameter this should also work and again the idea is that upon registration you send an email to the user with this token or even better the complete url where you put this token in the query parameters all right so this this would be the the crucial step send an email again if you want to know how to send an email check out last week's video on my channel pretty easy with mail kits and then you can you can design your email and just send it with the well with the with the url or at least the token you need for verification okay all right and when you did this then we want to get the user but this time not with the email address we want to check the verification token and also here at token and this is not a request object we just have the token so this would be it then we can check for the user if we do not find one then this means the token is embedded so invalid token is a proper error message and after that we say user almost user [Music] verified at is then date time now and we changed the user so we have to save this again context save changes async and then here let's say user verified okay this should be it let's try that i'm just restarting it manually just to be sure we've got our verify method here so let's try to log in again got our default email password and it still says not verified nice and now here you see it here we have to add a token so this is our endpoint now let's go back to the database this is the token i just copy it paste it here and let's remove the b first in with the token nice that's totally correct you see the the complete url now here with the query parameter and now i add this character again hit execute user verified we go to the database we see no date here but now we refresh and there we have it now see here this is late for me it's late all right and now we can try to log in again let's just hit execute welcome back nice so this works already the verification is done and now the next step is the forgot password feature or reset password feature whatever it is well in essence it's more like forgot because you can set a new password yourself it's not reset automatically but anyways i think you get the idea so this works and now the endpoint for forgot password the the the plan here is that we have a method or an endpoint for the user to tell the application hey i forgot my password what should i do and when this thing is called we will create a password reset token and then we need another endpoint where we'll where we will use this token to reset the password all right so first the for got a password endpoint and this will look like that we call this forgot password also here and we enter the email address here and then we say we want to get the user with the given email we can say here user not found again maybe too much information [Music] we can also just return true but nothing happens because the implementation here the complete implementation should actually send an email again to the user with the password reset token because here now we say a user password reset token is again create random token and by the way if you want to be absolutely sure then in this method here you would check if you find a string like that so the created string already in the database probability is pretty small i guess but to be absolutely sure you would create this string and then check it does this string already exist in the database and if so just just run this method again and again and again and again might be the case that you run into an infinite loop but again this probability is also pretty pretty tiny okay just as a side note all right where where we create random token this should be it and then we say use uh user user user reset token expires is date time now and then maybe you've got one day to do this otherwise you have to call this again save changes async and then we just say you may now reset your password nice let's test this you see it here password reset is now and the expiration date is also null and here is our endpoint it is tested user one at example.com we had execute user not found nice and now [Music] you may now reset your password and let's double check there it is nice and they they're not the same we're really lucky okay not the same great and we've got one day all right so we've got this end point covered and now the last thing is actually resetting this stuff and uh for that first we need another model and this is the last one and we call this thing reset password request and this is actually pretty similar to the register model so let me copy this and it's not an email address that we need we need a token here so this will be our reset reset token and the rest is actually the same so it's your job or the whoever is building the front end this is it's the front end the client's job in essence to create another form where we then send the token but also enter the password and the confirm password value here all right okay so with that we've got our request object and now let's create the last endpoint so i am copying this again and now we call this a reset password also here reset password with the reset password requests and now here we check for the re no it's called password reset this will be our request token [Music] and now here let's check if the user is null or user reset token expires is smaller than date time now and if so we just say invalid token and then it looks similar to the registration well a little at least because we say now create password hash again because we've got a new password so it'll be request password and again out bytes password hash and out bytes password salt all right and with that then we say user password almost user password hash is password hash password salt password salt and then we also say password reset token is now and the same for the reset token [Music] this is also null and then we save the changes and here we then say password successfully reset okay let's try that last time restart our app there it is and we say reset password try this out and now what's happening when i just execute this email token absolutely true now let's say i copy this and i change my date to where is it adjust the time and change that to [Music] this thing here i hit execute again invalid token correct so let's change the date back nice and now i want to use this as a new password password successfully reset now let's double check with the login we try this with the old password it executes password is incorrect and now string one hit execute welcome back nice and in just under an hour we've got a verify email and forgot password implementation i'll put this to github now check out the video description for the link and then you can get the complete code there you have it register user lock the user in verify the email address and then also a forgot password feature i hope you liked it and you learned something and i hope this resonated with you and finally you got what you have been asking for for a long time i guess if you liked it and learned something i would really appreciate it if you click the like button subscribe to my channel click the bell icon you know the drill thank you so much for that it does make a difference don't forget to have a look at my newsletter i'd really appreciate that for these videos here you get them earlier in your inbox and also you get early access and more information about upcoming courses and other stuff so maybe this is interesting for you and the last thing again my coffee tea mix thank you so much i love you guys forever thank you so much for your support really means a lot to me and now the last thing i can only say is maybe you want to watch some other tutorials as i already said maybe the json web token tutorial is interesting for you how to register user and create json web tokens with claims and roles and all that stuff so there is a series about that on my channel and maybe there's also another video you are interested in then just click on this thing and watch this video and the next one and the next one and the next one to get all this dot net and blazer web assembly knowledge so thank you so much for watching thank you so much for your time and i hope i see you next time take care
Info
Channel: Patrick God
Views: 45,053
Rating: undefined out of 5
Keywords:
Id: 2Q9Uh-5O8Sk
Channel Id: undefined
Length: 56min 33sec (3393 seconds)
Published: Tue May 31 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.