Build a Complete Register/Login System on AWS with React.js and a Serverless API - Part 1 (backend)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everyone welcome back to another episode of aws tutorial and today i'll show you how to build a complete register and login system with react.js in the front end and the serverless api with the dynamodb on the backend and then we're going to host everything on aws so at the end of the video you're going to be able to build a website that looks like this where you have the home page that you can access with the without authentication and then you have a registered page where you can sign up for an account and then you can log in with the credentials and then finally you have a premium content page that you can only access after you log in and if i'm not logged in and try to access the page you just redirect me to the login page and even if i type in the uil it's not going to let me get there and right now let me register for a new account and log into the system i just call it felix and then email let's say test email.com and then username felix password just to abc all right he's telling me the registration is accessible and now let me log in with the credential nope username felix and if i type in the wrong password it's going to tell me password is incorrect and if i type in the wrong username let's say that and it's going to tell me user does not exist so let me fix that and hit login and now i'm logged into the system and this is the premium content page that is able to get my name and telling me that i'm logged in right now and if i log out it just drag me back to the login page so this is gonna be a two part series and this video is gonna be part one of it and where i'm gonna build out the back-end system with the serverless api and a dynamo database i have a separate video that talks about what serverless is and its advantages over non-serverless apis i'll include a link down below so you can check it out if you're interested but in this tutorial i'm going to focus on the implementation of it and the logic on how to handle the authentication so without further ado let's get to it all right so right now i'm on the homepage of the aws console and step one is to create a dynamodb table to host our user data so i'm going to type in dynamodb open that into a new tab create table give it a name i just call it geneminster users and then for the partition key i'm just going to use user name but you can use other things if you want i'm going to use the string as the type and then use other default settings create table all right so it's done and now we're ready to create a serverless api but before we do that we need to create imro for the lambda function to use so i'm going to type in iam open that into a new tab i'll click rows and then create row we're going to choose lambda because the lambda function is going to use it and now we need to attach two policies to it one is for the cloud watch because we need that to see our logs on cloudwatch and then the second one is dynamodb because we need to access our data in the dynamo table so i'm going to type in cloud watch log full access and then dynamo db i'll give you full access as well for this demo then hit next next give it a name i'll just call it login backend raw great all right so that is done and now let's create a lambda function for the api so just type in lambda open that into a new tab create function from scratch i just call it login backend we're going to use node.js for permission we're going to use the row that we just created i believe it's that one and then create a function all right so it's done one thing i'm going to do before i move on is that i'm going to increase the timeout and reserve memory just in case in general this is enough but i'm not exactly sure how long it's going to take so i'm going to increase it to maybe five seconds just in case and then memory i just do 500 that should be more than enough so hit save and now let's create a api gateway that acts as the front door open that into new tab and then make sure that you choose the rest api because that's what we're going to use so rest api builds hit okay i'll do new api give it a name i do log in back in gateway i'll leave it as original and then create api and now let's create some resources so the first one we're going to do is the health so create resources this is for the health check all right so this is very important make sure you check this because if you don't when the front end client calls it it's gonna error so create resources and then create a method which is a get method hit check we're going to choose lambda function and make sure you check this as well because that's going to give us all the request attributes by default and then select the lambda function that we just created i think we call it log in back in and then hit save then hit yes all right let's create a few more the next one is the register endpoint that we're going to use to register new accounts check this create resources great method this is going to be a post let me check this and then choose the lambda function hit save hit okay and then the next one is the login endpoint that handles all the logins great and then we're going to create a method that is also a post check this and then choose the lambda function hit okay and then lastly we're gonna we're gonna create another endpoint for verified because we need to check if the access token is still valid and not expired so we're gonna call it verified of course great we're going to create another method that is also post hit check is saved hit okay okay so we have to find all the endpoints right now let's go back to root and deploy the api deploy new stage i just do a prod deploy all right so that is done and now let's go back to the lander function and create some dummy return object for each of the methods so come here delete everything what we're going to do is we're going to define some path parameters so the first one is the health path that is just health and then the next one is register rest register path that is just register the next is login path and then lastly is the verified path and inside the handler first thing first we're going to cancel the log to lock out what the event is and then we're going to define the response variable to return to clients and here we're going to have a switch statement that we're going to check if the method is get and if the path is the health path we're going to set response to be 200 with an empty body we're going to define this method later and then break and then do the same thing for other endpoints just for testing purposes just to return it to 100 for now post register path post login path post verify path and then we have a default response that's going to say 404. now found and then finally we're going to return the response to the client and now let's define this method the function that takes in a status code and then a body object and it's going to return an attribute is status code and then the head is the first one is access control allowed origin to be everything this is very important because this allows our clients to call this api because it has a different endpoint to enable course and then content type to be application json and then the body is just gonna be a stringify version of the body object because that is what api gave is expecting a string all right hit deploy and now let's test our dummy api go back to api gateway and copy this uil and now let's go to postman paste that url here and then the first one is the get method for the health check does it go it's 200 and then post register 200 so that's working as well and then log in 200 and then finally verify all right so it all seemed to be working now but the problem we have now is the api right now is open to the world um anyone can access that and we don't want it to happen so we're gonna configure api gateway to require an api key in the headers in order to do the request so let's get back to the aws console so api gateway scroll down so api keys action create api key i'll just call it gene meister client auto generate saved alright so that is the api key that's auto generated and now let's go back to the api scroll down usage plans create i'll just call it test plan raid just 1 500 1 million why not and then next add api stage we're going to choose the api back-end gateway that we just created stage prod we only have one stage hit a check mark hit next and then now we're gonna add the api key we just created is that one i have a misspelling over there but whatever check yes and then hit done all right now let's go back to api go back to the api gateway and then for each method we are going to enable api key required true hit yes and then same thing for this edit true check mark true check mark last one and now make sure that you deploy the api again otherwise it's not going to work so action deploy api choose the product stage all right so i think this is going to take about 30 seconds to process so i'm going to pause the video and then come back in a couple of minutes okay so it's been a minute so right now if i go back to postman it was 200 before and now if i hit send again it's going to say 403 forbidden and the same thing is going to happen to other methods 403 forbidden all right so it seems like it's working and now let's use the api key to get access so scroll down api keys that is the key show just copy that go back to postman that is x api key and then post it here and hit send again right 200 log in alright it's working as well all right so it seems like the setup is working and now let's move on to the final step which is the radical for the lambda function to handle the logics for register login and verify i can write a code in the aws console but i don't like it a lot so i'm gonna do that on vs code and then upload the package so i'm gonna open vs code and have an empty folder open first thing first we're going to create a package.json file because we're going to use node.js for the lambda package.json and then define our project name i'll just call it register login system backend author felix and then version is 21.0.1 and then dependencies we're going to use two libraries one is b bcrypt.js that we're gonna use to encrypt our password and i believe that is the latest version and then the other one is json web token that we're going to use to create our session token for our users when they log in and next let's create a index.js file and then go back to the lambda function and copy the skeleton code here okay and then we're gonna create a folder we're gonna put all the services in for example login register and verify so let's create them now one is to login that obviously handles the login logic and then register that handles the register logic and then finally verify now let's go back to the index we're going to import all the services so the first one is register service service register and now let's do the register logic first we're going to first extract the request body from the event dot body and then we're gonna use the register service to register our new user we're going to define that method later register body and since that is going to be dealing with dynamic operations so we're going to define it as a async function so this has to be a weight so now let's define this function in the register file first thing first we're going to define aws aws sdk and then we're gonna update the region to be us is one because that's where our table is usb1 and then we're going to define our dynamodb client dynamodb and then we're going to define our dynamo table called user table and i believe we call it gen minus the users and then we have a an async function call register that's going to take in user info as an input and then const the user input is going to have a name email username and password second we're gonna extract all that name email username and then password and then we're going to check if any of them it's empty or undefined we're going to return it for one because all the fields are required return all right so i'm going to do one thing i'm going to create another folder called utils and then inside the folder i'm going to create something called u2.js so that i can move this function inside a youtube file so they can use that in other files as well so you too and i'm going to do module exports w yep and inside index.js i'm going to use that okay so this is gonna be [Music] your turn your tail your tail and your tail okay now let's get back to the register one we're gonna require you to two levels up newton newton and then we're going to do detail that would be response i'm just gonna i'm just gonna use 401 but you can pick your number and then a message that says all fields are required and then if it if the user defines everything we're going to check if the username is already registered in the past by someone else i'm going to do constant user equal to await get user we're going to define this method later it takes in a username and if something returns and it has a username we're going to say i just default one for simplicity with the message that says username already exist in our database please choose a different username all right and then next if the user selects a unique username first thing we're going to do is we're going to encrypt the password because you never want to save the password in plain text in the database and we're going to use the library called bcrypt.js so i'm going to do const decrypt i do const encrypted password is equal to decrypt hash sync we're going to input the password but before we do that we're going to trim it first just in case we have some white space and then 10 rounds and then we can define our user to save our database for later use name is going to be for the name email so we go to email of course and then username what i'm going to do is i'll just save that as all our cases just for simplicity sake and then trim that as well and we're going to do that when we check if the user exists and the reason i do this is that i think if a user name is felix or felix i consider them the same they shouldn't be different but you can do it your own way if you want and then password we're gonna use the encrypted password and now let's save the object to the to the database we're going to do const save user response save user and we're going to define the function later and if we get back or if we don't get back the response we're going to return 8 503 because there's an error with a message that says server error please try again later and then if everything's successful we are going to return a 200. let's return the username back to the user and now let's define these two methods get user and save user they're both dynamic operations and they're both async functions so async function get user that takes in a username we're gonna define a params table name which is the user table and then key remember when we define our table we use username as our primary key so that is our key and then let's return await dynamodb dot get just get a single item for rams response we are going to return the response item and then if we have an error just cancel that lock it out there is an error okay so that is the get user and now let's define the save user function save user that takes in user same thing we're going to define param table name user table and then item we're going to save this user and then we're going to return wait put the promise that then return true and then if there's an error saving user getting user okay all right so that is done and finally we're going to export the function so that other modules can use it we're only going to expose the register function okay so this is done now let's go back to the index.js so that is done now we're going to do the login logic and same thing first we're gonna extract the request body login body and then we're gonna use the login service to do the login logic now let's define this function inside login the same thing we're gonna define the aws stuff so let's take this take all that and then we're going to define an async function call login that takes in user as the request body and then we're going to extract username user that username and then password that is also coming from our user input and first thing we're going to check is if user is not defined or username is not defined or password is not defined we are going to return 401 it says username and password are required and then we can do the normal logic we're gonna first try to get a user dynamo user equal to await get user that takes in the username and if there's nothing comes back if no dynamouser or dynamouser does not have a username we're going to return a 403 response with a message that says user does not exist if the user exists we're going to check the password and see if it matches with the one that is in the database so we're going to use bcrypt for that compare sync password with the password let's return from the dynamo item if they don't match we're going to return a 403 as well with the message that says password is incorrect and if everything matches we're gonna define a user info object and return that to the user along with the along with the access token so we're gonna do user info username enter the name as well for the user one thing to note here is remember what we had before was we do a lowercase on the usernames but we leave the name of the customer or the client the same as what was input in the register so that's gonna be shown to the customer and then we're gonna create a token for the user and actually i'm going to do that in a different file so i'm going to go back here let's do it in youtube auth.js and we're gonna use the json web token library for that to create a token oops jwt and then function generate token that takes in user info if it's not defined null customer user info username we're going to use the email for the hashing but you can use other attributes if you want and then we can return jwt sign using info and then we're going to pass in a secret for the token i'm going to use an environment variable for that in the lambda function that we're going to use that we're going to define later and then we're going to set the expiration time i'll just do one hour this one if you want you can just when you can do something like my secret but i don't like hard-coding secret stuff i'm just gonna use the environment variable later on okay so this is done we're gonna export this and in the login file we are going to import that and then in here we can just do auth generate token user info oh we already have user info here that means inside the auth we don't need to define this that should do it and now we're going to define a response body call user user info and then the token to be token and then we're going to return a 200 response and next we need to define the get user function which is the same as the register one so i'm just gonna copy that over okay so finally we're gonna expose the login method all right so that is done and now let's go back to the index.js file and lastly we're gonna handle the verify path and same thing we're going to first extract the body and then we're going to use the verified service to verify the token and see if it expires or if it's valid and now we're going to go to the verified.js file to define this function so it's going to be a function verified request body and if the request body doesn't have a user or it doesn't have a username in the user or it doesn't have a token we're going to return a file one so you too we're gonna say verify to be false and then a message to be incorrect request body and now let's handle the normal request user we're gonna have that from the request body and then token as well and then we're gonna see if it's verified verification all right let's define this in auth file as well so go back to the auth and then define a function called verify token that takes in a username and the token and then it will return jwt dot verify token and again we're going to use the secret from the environment variable and then the callback function is going to be like this if error we're going to return verify to be false and then a message it's going to say invalid token but if it comes back but the username is not equal to the intended username we are also going to return verify to be false and then the message is going to say invalid user and then finally if everything is successful it's gonna say verified true and the message to be verified and then we can export this so in our verify file we can just import that and use it as is auth verified token username and then token so if it comes back and verified is true or verifies not true rather we're going to return a forward with a verification response but if it's verified successfully we're gonna return it 200 with the token verified is true message i just say and then we're gonna return back to user and the token as well module export okay so everything is done you have the index that calls auto login register and verify functions okay so after i finished writing this i found a few mistakes so i'm going to go through and fix them one by one so the first one is under auth we changed the name of the parameter but we didn't change it here and then the second one is under register that we have a misspelling in here that should be camo case and then on the bottom here that is not correct it should be like this and then the next one is inside the login.js where here it should be generate token not get token and then the last one was insideindex.js there's a typo here should be verified oh there's one more i think under verified that should be not and that should be everything and now let's install the two modules and then upload the package to our lambda function to test out things so i'm gonna do terminal new terminal and then do npm install all right so what it does is that it just installs what whatever we specified under the dependency attributes and then save that in a node module folder and if you don't have npm installed in your machine you can just go to the web page and then follow the instruction to download that and now i'm going to navigate to this working directory and then zip up everything and upload that to our lambda function so this is my directory i'm going to select everything compress and now let's go back to the aws console go to lambda upload from zip and then navigate to the directory of the zip folder it's in here and then choose the zip file that's our deployment package that has everything hit save okay all right so the code is updated and we need to do one more thing remember in our code inside auth we said that we're going to set this as an environment variable and now we're going to do that so i'm going to copy this go to configuration and the environment variable is on the side here hit edit add let's just do chin meister secret hit save all right so it's done and now let's go to postman let's check the health first all right successful and now let's do register which is a post method and we have the api key let's go back to the dynamodb to make sure that we don't have anything here first it's too refreshed it's empty so in the request body i hit raw json we're gonna have a name attribute let's just do a felix and then email test email.com and then username let's do felix lower case and then password abc and then hit send all right so it's successful and now let's go to our db and see our user object yup so everything is successful and the password is encrypted and if i try to register this one more time with the same information it's going to tell me that username already exists so it's working as we expected and now let's try to log in with information just to login and then we're going to give it a username and password he sent it's successful logged in it sends back the user item and then the token with it as well so if we do let's say the wrong password it's going to tell us password is incorrect if we do the wrong username it's going to say user does not exist now it works again and now let's try to verify our token i believe it takes in a user item that has a username inside and then token to be the token isn't it successful it's verified and then if we changed it a little bit it's gonna say it's invalid token and if we do this it's going to say invalid user all right so it seems like it's working properly one thing you can test out is inside the auth file in here you can change it to like 10 seconds and test out the token being expired after 10 seconds but i'm not going to do it here i'll just leave it for you to experiment and that is it for part 1 of the tutorial i hope you have learned something and if you like this video please give it a thumbs up and i'll see you in part two of the tutorial
Info
Channel: Felix Yu
Views: 6,105
Rating: undefined out of 5
Keywords: aws, serverless api, react.js, register, login, jwt, node, bcrypt, api gateway, lambda, dynamodb, s3, node.js, aws lambda nodejs, signin page, full stack, web app, authentication
Id: mgkgQtMplPY
Channel Id: undefined
Length: 45min 24sec (2724 seconds)
Published: Fri May 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.