Full Stack Tutorial with MERN & Stripe Integration, Passport Authentication, Sessions, etc. [PART 2]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on guys so this part is going to be the express back end initially i wanted to combine the entire video with the stripe the express back end and then the react app but seeing that this video was going to end up being three hours long i knew a lot of people wouldn't be happy with that so what i decided to do was to decide to separate the introduction with stripe away from the actual express back end because a lot of the stuff that we're going to be doing in the express back-end it's going to be nothing to do with stripe really we don't really get to the straight part until like the very end so this really makes sense to just have you guys sit through everything and then you know wait for the straight part so instead i know i promised you guys a full snack tutorial on how to set up authorization authentication so here it is if you guys want to learn how to integrate the app with stripe watch the other part of the video it will teach you everything to know on how to create a payment a subscription and etc all right guys so we're going to set up our project right now so we're going to worry about the back end first so the back end we're going to use express we're going to use uh i think we're all i think we're going to probably use mongodb just to make things simple i did essentially want to use type rm with my but i feel like um i think it'd be easier with mongodb and i don't want to you know have you guys worry so much about a bunch of different things type arm isn't that hard but we're just going to use mongodb just to you know make things simple we're going to go ahead and just make a directory so let's do mr and let's go ahead and do stripe payment tutorial a little cd into here now this is going to be a single directory that's going to have two directories the front and the back end all the code will be in one repository so you guys can check it out i'm going to go ahead and create a new directory call this a stripe back in and you can also create the project up manually if you want but we're gonna use the terminal for that okay so i'm gonna just initialize the folder and i'm going to install express because we're using express uh let's see what else do i need to install um we're going to need to install express sessions because we're going to need to persist the user that's how we're going to make sure that they don't have to log in over and over and over again uh we're going to install mongoose that's the rm for mongodb um what else do we need i'm trying to think connect for the session store and i think that should be it for now we are going to need the stripe api libraries but we'll worry about that stuff later okay so i think this should be uh oh let's install dot and as well okay uh okay that should be fine so let's go ahead and create a new folder let's call it source and we will create an index.js file okay uh we're going to go ahead and import express so express and we'll create the app just like that we'll call the express function uh we're also going to need to set up a port so i'm going to do that inside the dot and file so we'll set the port equal to 3001. so now if i want to reference that environment variable i can just simply reference process process.env.ports in case of that environment variable is not available i'll just manually set it to 2001. sometimes it might not be available because if you're deploying to heroku for example or sometimes i think amazon ec2 i think it might not give you that port but i think with ec2 and amazon web services it should be fine buying a heroku they give you a dynamic port uh so we'll listen to port 3002 so we'll start listening to requests and just log a message all right great so now this should work if you are to run this app it should work just fine i'm gonna go ahead and set up a simple dev script with nodemon so if you don't have nodemon i recommend you install it it's very easy to install just do npm hyphen or npm i hyphen g nodemon it basically will speed up development for you instead of having to manually restart your app it will just do automatically whenever you make a change to it so we'll just do node mod source okay so this will pretty much run this index.js i don't need to specify index.js because by default it will just run index.js if there's uh no file that was specified but i'll just leave it like that for now okay so let's run it and let's see what happens i always want to test our code just make sure it works perfect all right great it works just fine all right so now let's go ahead and opt into our middlewares because we need to make sure that we have certain middlewares in order for our app to function okay so what exactly is middleware well middleware is basically just a you can think of it like a small piece of a function that will alter the request it will do something with the request before it reaches the final request and response handler function so for example if we were to set up a simple route right now let's just do app.gets all right press okay this function over here is known as the handler function and that's what handles the request so we can send a response back if we want to but sometimes we might need to do things right before we reach the actual handler function okay now instead of just writing all the code inside this handler function what we want to do is we want to write more modular code and that's why middleware exists because we can pretty much just inject that middleware anywhere we want in our application and it will work just fine okay so the middlewares that we'll need to opt into let's opt into the first one which is going to be for serializing uh requests whenever we make them so this is very important because by default express will not serialize any payloads for you so for example if you make a post request like let's say you try to send a request body that has the username and password if you don't actually opt into the middleware it's going to have that object as an empty object and i'll show you an example when we set up the application with postman so let's go ahead and reference app.use and we're going to reference express dot json so this is going to serialize the uh well we're not really serialized but you can think of it as parsing it's going to take in the the payload it's going to parse into json and it's going to attach it to the request body object so this is where sending json to the server now if you're sending a url encoded form data which is basically whenever you go in the html form and you click on submit right it's going to send that payload as url encoded so you need to make sure you handle that so we'll do that by simply doing express dot url encoded and we'll set extended to false i think if you send extend it to true that allows you to send objects in the uh in the query string i think i'm not entirely sure because i never uh really looked super into it but i just i remember looking it up on stack over long time that's what they said okay so now let's go ahead and let's set up a simple post request and we're going to open up postman okay so i'm going to just simply console.log directval body and i'll show you what happens so let me open up postman all right so we're going to test our api right now with postman so i recommend you guys download it it's free but we're going to make a post request so let's select post you can see that they have a bunch of different uh http verbs that you can go through we're gonna go ahead and do port 3001 just type in the url so we're going to make a post request and let's send a request body so let's send raw and let's select json and we'll do hello world so remember we're we have it as json you can set it as text or raw or actual uh html if you want but make sure you have json though so let's send you can see that we actually have the object over here now if i go ahead and if i get rid of express.json you're going to see that it's going to be empty okay now the reason why is like i said because we don't have the middleware now let's try url encoded right now and let's just send hello world so we're sending url encoded so remember this is the html form and you can see that it says hello world but if i get rid of that middleware if i send it again you're going to see that it's empty so that's why these middlewares are very important i just thought i'd go over it real quick because a lot of people tend to not really understand these middlewares okay but they're very important and you want to make sure you register your middlewares before you have any of your routes being set up because if you have these middlewares like right over here it's not going to work just make sure you have it up there because again the middlewares are basically registered in order so if you were to have it underneath over here it wouldn't affect any of these routes it wouldn't even work at all okay but hopefully that makes sense all right so the next middleware that we're going to set up is express session so express sessions are going to allow us to persist our application so it's very important because we don't want the user to have to authenticate over and over again and we want to be able to identify every request and who is making that request especially when we have an application that requires authentication so sessions allow us to do things like that so we're going to go ahead and simply just just clear this install express session okay i think i did install it already actually i think i yeah i think i did install it but just in case you guys missed it make sure you install it again express hyphen session and we're going to import it up here so const session equals require session express session and what we'll do is we will simply uh register the middleware right over here so let me leave a comment over here uh registering middleware for parsing quest bodies and we'll do registering session middleware okay so we're going to use the app.use function and the session over here this uh this variable this is actually a function so we can pass in and options and we're going to pass in cookie value which is an object and for this we're going to need to pass in the max age so this specifies how long the session or the cookie should live for so we'll probably do just one day so we'll do three million six hundred thousand times twenty four okay that should be pretty much it you can also other values too so if you want uh secure sign the same site etc but i'll leave you guys to worry about that we don't need to worry about those things at least right now i'm just going to worry about the minimum things for development let's go ahead and set save uninitialized to false so this will allow the session to only be saved if the session object has been modified because if you have this set to true it's going to save the session every single time even if the user has not logged in or registered and you don't want that we'll set resave to false as well this will prevent the session from being resaved okay and we will also i think the secret is next so this is going to be some random string that you need to set in order to actually encrypt the cookie you want to make sure you keep this secret because if an attacker gets a hold of that secret they can decrypt a cookie and they can actually uh do a bunch of terrible things so just make sure you keep the secret secret so for a second tutorial i'm just going to place this inside a string over here you could put this inside a dot and file if you want but i'll just leave right over there okay and i think that is it for the session okay now before we continue i'm going to briefly show you guys how it works so that way when we actually get to the authentication part everything will really make sense okay i really want you guys to understand all of this so i'm taking the time to explain everything let's go over to our let's get to this post because we're not going to need anymore let's create this uh or not create let's go inside this gate request the handler and let's go and do if session or not session if rec dot session okay so you can see that we actually have this uh property session on the request object and we're going to check to see if rec.session.authenticated so right now this session object will not have the authenticated object okay or i'm sorry not authenticate object the authenticated property but what we're going to do is if it is there that means they've already visited the actual page okay that means they've already you know they've visited us they've logged in etc if they have not visited us yet they would not have this authenticated property on the session object and therefore what we're going to do is we're going to attach it and we'll just simply say authenticated and we'll just do something like let's just do user name hello something like this something simple okay and we will just simply say let's send and let's just do status 200 and then we'll do session session id direct.session id okay now if they're if they're authenticated we'll just do the same thing but you're going to see there's going to be a difference okay so let's go ahead and test this out so what i'm going to do is make sure we're running our app we're going to go into postman and let's make a get request so let's make a get so you can see right now that we are not authenticated but now we are right what happened was that we basically went into this request and said hey look if rec.station authenticated oh it's going to send actually you know let me actually console.log something user already authenticated so you guys can actually see the logs console.log user visited for the first time okay so i'm going to save and because we aren't using session stores the sessions are going to be white they're currently saved in memory but we're going to need to save it into a database later so if i run and you can see that it says user visited for the first time if i send it again you're going to see that it says user already authenticated okay see how that works so now you can see that right now every single time i make a request this session id belongs to us this is our unique session id so every single time the user makes a request i know who they are because of this session id on the front end on the client this session id is saved as a cookie okay now let me show you one more thing real quick be instead of uh i'm gonna go and just get rid of this condition so we're not gonna modify the session and i want you guys to see what happens so you can see we have our session okay you can see we have our session id let me see if i can zoom in a little bit if i send you're gonna see that we have a different id every single time okay and that's fine because we're not authenticated but when you're authenticated you want to make sure that session id does not change because how do you know which user is which you're going to have a bunch of different session ids that correspond to one user because that's not good okay so this is normal behavior because we have not yet authenticated but when we authenticate the libraries that we're going to use such as passport.js is going to handle that by modifying the session for us it's going to serialize the user to the session and it's going to say hey look the user just logged in and they're good to go so hopefully that part makes sense and that's going to be pretty much it for the session part so now that we have gone over the sessions and we've gone over the middleware for parsing request bodies the next thing that we're going to need to worry about is the actual authentication part so that's basically going to be logging in and then saving it to the database so in the next part of this video what i'm going to do is i'm going to go ahead and set up the routes for authentication all right so we're going to go ahead and set up authentication for application or the routes rather so we're going to go over to the source folder we'll click on a new folder and create a new routes folder and i'll just create an index dot js file almost at index.ts for a second index.js okay so we're going to go ahead and simply set up a router so const i'm going to import the router just like that okay and what we're gonna do is we're gonna go ahead and simply set up the router by just invoking that function and the router pretty much works the same way as the regular app over here let me close this so you guys can see the whole thing okay so i can do things like router gets i can even register middleware on the router too so that middleware will only be registered for that set of routes itself but the reason why we're using a router is because we don't want to keep all of our requests or all of our uh routes in just one file we're going to split everything up and that's why we're going to use routers so what i'm going to do with this router is i'm actually going to go ahead and set up this architecture where we're going to create a new router and for this i'm going to call this auth so this is going to be auth router and we're going to copy and paste the same code again okay so this auth router is basically going to have all of the auth routes so for example and i'll show you guys this in just a sec just send a simple message off route status 200 okay and we want to make sure we export this so module exports equals router so now this index.js is this index.js that is inside the routes directory it's not inside auth it's inside routes so there's two i know the naming is a bit weird but personally for me i prefer naming index.js inside of inside the folder itself you don't have to do this but you can if you want to so inside this index.js okay source routes index.js this is going to be the main file usually you can call this a barrel file that's what they call a barrel file we're going to take this router and we're going to register all of these subroutes okay so first let's import off routes we're going to import this from auth and we're gonna do router dot use and we're going to register the auth route with all these other routes over here okay so basically what we're doing is we're saying hey look we're going to import this router okay and this router is going to be registered all the routes are going to be prefixed with the slash off okay now we need to export this and dory i'm going to show you guys how this works so we're going to export this and inside the app.js or index.js i got that there's so many index.js files inside the the main index.js you know what let me actually name this to app.js normally i name it as app.js because it's getting really it's getting really confusing i don't want to make this so complicated for you guys um actually you know what i'll do scratch that let me let me go ahead let me just do this i don't want to make it complicated for you guys so i'll make it simple because normally i do this and i like it but i don't want to make it super complex okay so i renamed it from index.js and i got rid of the auth folder okay um all right so now in app.js what we want to do is we want to import our routes so const routes equals require now we want to import the router but which one do we want to import do we want to import auth.js or index.js well index.js is going to be the main router that we're going to register all the routes in so you want to make sure you import index.js okay so that's slash routes index okay but since it's index we can just do slash routes okay and then we will register all those routes right before or sorry an hour before right after we register all of our middleware so app.use and now for our main route we're going to prefix it with slash api routes okay so by default we have no router but what we're going to do is we're going to register all the routes for this router and that router is going to be this right over here so every route over here is going to be prefixed with slash api now inside this router we're saying hey look every route despite it being prefixed with slash api we're going to take the other routers and we're going to prefix it with slash auth as well so basically creates a prefix of slash api slash auth i know it's a little tricky but we're going to go ahead and test this out so you guys can understand how it works so let's go ahead and let's visit slash api uh oh we need to run there we go let's try it again and you can see we have the author out okay notice how it's prefixed with slash api if we try to do auth it's going to say cannot get if i try to do slash api cannot gets well slash api uh would be if you wanted to set up a route for api you could do that inside here because that's what is being prefixed over here so for example you want to do router that gets and let's say you're doing v1 for example let's do v1 we'll do v1 there you go we're not going to worry about that okay but you can hopefully that makes sense you can see that we have all these routes are registered with this slash auth prefix and then all of these routes are being registered right over here with the slash api so if i were to create another router and that router would be something like for payments and we are going to be doing this later so might as well do it now i'm just going to copy and paste everything okay and we'll call this payments route and then over here we will simply register slash payments with payments routes and we need to import it so we'll do that okay and now if i try to reference payments you can see we have payments route notice how in the actual router itself we aren't doing slash payments or slash auth that's because if we did that you'll notice that it's going to say cannot get but we have to reference slash payments slash payments okay so this slash over here is basically the route of payment it's the beginning of payments okay so just letting you guys know that hopefully this makes sense okay but uh yeah so that's going to be pretty much the architecture for our routing so let's go ahead and just close all of this okay so we have our auth routes so let's just set up all the routes that we're going to need so we are going to be using discord oauth 2 but you can really use whatever it is that you want it doesn't really matter you can use google you can use facebook twitter the important thing is is that you're using some provider that gives you access to the email address okay it doesn't matter what you're using or just make sure you have the email address because the email address is going to be the only piece of information that we need that's unique that we can use to identify the customer so i'm going to set up a couple routes so for auth i'll do uh auth slash status so this is going to allow us to check to see if the user is authenticated uh i'll leave this empty for now actually i'll just send like 200 we need routes where the user are going to visit to actually log in so we're going to set up let's do auth slash discord okay and then we're also going to set up another route for the redirect so right now we just have a bunch of routes but don't worry in the next section of this video i'm going to explain how the oauth 2 is going to work so you guys understand what's going on all right so i'm going to go ahead and just briefly explain the oauth 2 flow for those who aren't too familiar with it basically instead of having a local user and password where the user can authenticate uh what you want to do instead or you you don't have to but you can and i feel like oa2 is actually a lot more secure because you don't really need the user to use a password you want to like you don't worry about uh hashing the password but it also is it also makes your app dependent on another service uh but based with oauth 2 the user clicks on some kind of button and it visits the route it will navigate them to the route okay and that route is going to be this route over here this slash discord well it's actually going to be let me just leave comments it's going to be slash api auth slash discord when they visit that route this route is going to give them that screen right that little uh splash screen where they can see uh the authorized button okay and they can uh click authorize and it'll also tell them what permissions what scopes that the application has access to so for example they can either see your email address they can see your username your your guilds etc okay so you want to make sure that you set up this route okay that's going to be for this route now once you authorize what happens is there's what's called a callback url now that callback url is basically the url that the application whether it's discord google facebook that third party application is going to redirect the user who's authenticating to that redirect url now that redirect url is going to be this route over here okay it could be any route but you want to make sure that it redirects to your route because it'll give you the code it'll give you a code parameter and that parameter is what's used to exchange the access and uh refresh token and you can use that to retrieve the user details uh their email address guilds etc okay so that's pretty much just how things work underneath the hood but with passport you kind of need to worry about something different so we'll talk about that right now okay so let's go ahead and first install passport so we're going to install passport and then you want to install the strategy so the strategy can either be whether it's google discord etc so if you want to use discord you'd have to install password discord if you want to use uh google you can install passport google oauth 2 or 20 sorry oauth basically all 2.0 but it can't have the dot in between the 2 and 0 so it's passport hyphen google hyphen oauth20 okay they have a bunch of different passports you can actually go on passport passport's website let me actually and you can actually look at all of the different passports facebook twitter google are the most common ones if you want to do facebook you do passport facebook okay but they have a lot of different strategies that you can use you can even implement your own okay they have a whole bunch okay but we'll just install these two for now so let's install it and there we go so the first thing that we're going to do is we're going to go into our app.js and we're going to register the passport middleware but first we need to import passport so i'll import it right up here so const passport equals require passport okay and we're not going to import passport discord in here we're going to go ahead and simply do app.use passport.initialize then initialize passport and then we want to set up sessions with passport as well so we'll do that and there you go that's all you have to do okay now the next thing that we need to do is we need to set up our strategy so we're going to create a new folder and i'm just going to call this strategies because you might have multiple different strategies but i'll just set up a discord strategy so i'll just do discord.js that's the name of the file not the discord bot library and that was not intentional but um we're going to go over here and we're going to do is we're going to go ahead and import the strategy file or the strategy class so passport python discord there is a strategy right over here okay uh i think yeah i think that should be just yeah strategy you can just hit the dot over here and you can see all the different uh classes and functions that they have but since they only have like i think a few classes okay all right so what we're gonna do is we're going to import passport in this strategy file and let me actually move this down over here okay so we're going to do is we're going to reference passport.use and then we're going to go ahead and create an instance of this strategy okay so we're going to go ahead and do new strategy and you're going to see that in the constructor it's going to take in an options object and inside this options object this is where you want to pass in your credentials so you're going to always have a client id a client secret callback url and scopes so you can see client id there's client secret uh where is it called url and then uh scope scopes is usually an array now what you pass in to these uh these properties these values right is basically going to generate the uh url that's going to redirect you to okay but we're going to worry about that in just a sec okay i'm going to show you guys how to actually get those get those values for discord okay but the second parameter is going to be a function now this function is going to be a callback function and it's going to take in four parameters it's going to take in the access token the refresh token the profile so that's the user details and then a callback function okay and that is pretty much it i think yeah there's no other there's no other parameter that we can pass in okay awesome let me go ahead and just move this over here a little bit okay all right so now basically what's going to happen is whenever we visit this whenever we visit the uh the authorization url or authentication url it's basically going to invoke this strategy or should invoke the strategy okay and once we click authorize it's going to give us the access token the refresh token the profile and then we're going to need to call the done callback once we're actually done now what's important about this function is that this function itself is basically where we're going to take care of checking to see if the user is in the database if they are in the database we're going to go ahead and return that user object so that it can be serialized into the session if the user is not found in a database then what we want to do is we want to create the user and then we're going to save the user to database and then we're going to return that user so that it can be serialized okay so what we're going to do is let me actually go ahead and do this let me just simply console log the profile object and you can see that this profile has a bunch of different properties okay again we're using the discord strategy so we'll just uh save that real quick and i think what i'll do next is i'll show you guys how to bring in the i'll show you guys how to bring in the strategy so we want to make sure we import that strategy so we can go ahead and just do something like uh require strategies discord we don't really need to store this inside a variable so we can just use the require we'll basically just bring in this function you know right over here i mean ideally you could do everything outside over here but you don't want to like you know put everything in one file so it's just better to just create a separate file for it and then just import it okay i'll just leave it all up here since it's required okay um i actually also forgot to use dot end so let's do that real quick because right now this environment variable actually was undefined because i didn't actually invoke the uh the end config function so make sure you do that okay so what we're going to do now is we're going to go ahead and grab our credentials we're going to grab the client id client secret the callback url and then we're going to specify the scope okay so let's go ahead and do that okay now since we are using discord we obviously want to go to discord.com and grab it but if you're using let's say twitter google right just go over to their developer console and they usually have instructions on how you can get those credentials if you are having trouble with it just simply google how to find those things they usually have a bunch of articles that explain how to find those details but ideally you just want to make sure you look for oauth 2 credentials so you can go ahead and create an application i'll create new application i'll call this a stripe integration click create and there you go we have a new application and you can see we have our client id let me zoom in a little bit we have our client id we have our client secret and we have the public key okay so the client secret you need to make sure you keep this a secret the client id is okay that's public and since we're not working with a bot at least not right now uh we will be using the bot later but since we're not using the bot right now we're not gonna worry about the token you can see over here that we haven't added the bot yet but we're gonna copy the id and let me go ahead and place that right over here so i'll just do this for client id and i'll set that over here and if you accidentally reveal secret you can always regenerate it so let's just copy that scored client secret uh and i think the last thing we need is the redirect url okay so let's go ahead and add a redirect url so this is going to differ based on which environment you're in what i mean by that is right now we're currently in development but if you were to deploy your app you'd want to also provide your domain as well luckily with discord we can actually add multiple redirects which is great so we'll do that so what is our redirect url well if we look at ourauth.js you can see that this over here is the redirect okay so we want to basically make sure we have everything right over here with our hostname so our host name is going to be http localhost the port 3001 and then slash api slash auth slash discord slash redirect if you get an error something like redirect your uri is invalid double check this redirect url and double check your routes okay but this should be fine and we can also add another one if we want so if i had like a domain name i can place that over there if we have time i'll probably show you guys how to deploy this as well but let's go ahead and we can also select the scopes but i think actually we don't need to worry about that um let me actually see okay well so actually you can actually generate the uri yourself but the library is going to do that for us okay so we don't need to necessarily uh like see you can see how it generates this url basically this is the url the library is going to generate for us it's going to basically visit for us you can even go you can even go to the url right now if you want to and see what happens okay but let's go ahead and save and i think we are good but let's also copy the routes for the callback uri and i think you can actually just get away with passing in the the route itself you don't need to actually pass into host you can if you want to but i'm just going to leave it like that this should work just fine okay and like i said if you're using google oauth if you're using twitter oauth linkedin github it all works the same exact way it the id the secret callback girl it's it all works the same way it's the standard okay all right so now we can actually go inside our strategy file and we can actually reference our environment variables so process.n uh discord client id discord client secret process discord callback url now you also need to make sure that your config your uh n file has been invoked so i forgot to do it earlier but i did it already because if you don't your environment variables are going to be undefined and you also want to make sure you do it right before you import your strategy so right now if you actually let me actually console all this right now right now it's actually going to be undefined so if i run this you'll see that's going to be undefined yep you can see it through an error undefined okay the reason why is because we called the function after we imported this middleware remember middleware is registered in order okay so it's basically trying to invoke this function but since there's no value for the client id or sql to call that url it's going to throw an error so you should put this all up here and there you go okay very very very simple so now we actually have all of our credentials let's set the scope the scope that we want is we want email and profile now with different providers like google they have different scopes but i think with google it's just email i think and there's also profile as well i think it with google i think is uh actually sorry with discord i think it's identify an email i think with google it's uh profile and uh email i'm not entirely sure but like i said you can always just google it okay but yeah we want to make sure you specify the scopes okay and let's go ahead and let's try to uh test this out all right so we're going to go ahead and try to test this out so we're going to try to visit slash api discord so slash api slash discord now you're going to see nothing is going to happen it's actually going to stay loading for an indefinite amount of time the reason why is because we need to actually invoke the passport.authenticate method okay so to do that we need to go into our route auth.js right over here okay and we need to go ahead and for the base route discord we need to well first let's import passport so let's go and do const passport equals require passport and right over here in between the route name and the handler function we're going to pass in the middleware okay so passport.authenticate and we're going to go ahead and pass in the name of the strategy which is discord okay and you want to make sure you do the same thing for the redirect url all right perfect if we have time i'll explain how things work underneath the hood but let's just go ahead and leave it like this for now and we can get rid of this handler because we're not going to need that okay uh and inside the redirect for the redirect we do need it so we'll just send the 200. all right so now you can see now we actually have this page so if i go back here let's go back to slash api discord you can see we have our stripe integration we have our username and avatar the email address etc and we can click authorize now when i click authorize let's see what happens let's go to the console and now you can see that we have this object now what exactly is this object well if you go over to here you can see that we're logging it right over here now you'll notice that nothing is going to happen it's going to keep on loading it's normal right now because we haven't actually implemented the validation for our user we need to handle it by checking see if the user exists saving it if it doesn't and then returning it once we're done but you can see we have a bunch of different fields we have our id the username avatar discriminator the email address okay a bunch of different things and like i said if you're using google if you're using twitter facebook it might not look exactly the same but you'll definitely have a lot of similar properties such as the email address okay so i would encourage you to use your own strategy like use google if you want and then get the email and then save it to the database so the next part of this tutorial we're going to go ahead and focus on saving the user to the database while also making sure that the user has not been saved to the database ready okay so let's go ahead and get start on that all right so what we need to do is we need to get started on implementing the database part of this application so we're gonna go over to source we're gonna right click and create a new folder and i'll call this uh call this database and i'll create a new file and actually i'll create a new folder called models and remember we're using mongodb so i'm going to create a user.js and we're going to create a customer later or we can just probably keep everything inside user.js to be honest with you because we're not really using relational database so i think yeah i think we'll just use one model for now okay so let's model this out so let's first uh import uh mongoose from mongoose and let's create the schema so user schema equals new mongoose dot schema and we'll create the schema definition so what are we going to need we'll need the email this is going to be a string so type will be a uh string i don't think i can do string here but i think i could i think yeah i think it should be fine acquired true we need control because we don't want multiple emails in our schema uh let's see we'll get the discord id that's important and we will also do that as well i think actually let me actually uh get rid of that for now we'll just leave it like this we'll get rid of the uh unique just for now um let's see email discord id i think that should be it um later we'll create the customer schema and then we'll attach it to this but i think this should be okay i think that's really all we need you can add other fields obviously if you want but this is probably all we'll need for now okay um yeah this is fine so we're gonna do next is we're going to compile the scheme down to a model so we're going to do mongoose model user and passing the user schema and there you go okay so let's work on the customer one right now so customer schema now this customer one is going to be part of the user schema so for example we're gonna have a customer and type is gonna be customer schema like that okay now it's not gonna be required so i think default we can set it to null now for customer we're going to need a couple things we're going to need let's see uh we'll need the stripe id so in case if you forgot the stripe id is provided to us uh whenever we create the customer from the stripe api okay so that's going to be required so type string required true uh let me just set this to false uh we're going to stripe id we're going to need the i guess subscription so the user could probably have i guess it's up to you on how you want to implement it if you want them to be able to subscribe to more than one or you can also do things like upgrading subscriptions we'll do subscription id so this will be string and required will be false because they don't necessarily need to have a subscription even though they are registered as a customer um what else do i want um subscribe dates we can also just look at the uh we can look at the the data that's returned from the stripe api and we can you know see how it works okay but i think for now we'll leave it like this so this should be okay this uh user schema has a customer schema so it should be just fine hopefully should be fine i haven't used mongoose for a while so i'm kind of just like winging it but i know it should be okay i'm pretty confident all right so now we need to import uh the mongoose library to connect to mongoose so let's do constant mongoose equals require mongoose and we'll probably just honestly i'll just connect to it over here connect and we'll need the mongodb uri all right so i'm going to store the mongodb uri in my environment variable so mongodb uri if you're using something like mongodb atlas you would just copy the uri they gave you and place it over here uh but it's going to be my vb and then host and then by default it's on port 27017 and then we'll do stripe app you name it whatever you want that's the database name my local database does not have authentication so i'm not going to worry about that okay but like i said if you're using the mongodb atlas just paste in the uri all right so now we're going to go ahead and reference the mongodb uri and then we will simply just say then and i'm not sure if it resolves the value but i'll just console.log connected to mongodb and you need to make sure that if you're using mongodb um you need to make sure of using mongodb that you actually have it installed so please make sure you actually go on youtube or google and look up how to install mongodb otherwise you're going to get a connection issue so please make sure you do that okay so i have mongodb installed already so you can see that it connected just fine it's giving me a couple warnings so we can address those right now so use uh new url parser true use unified topology true um okay there we go perfect connected to mongodb all right awesome awesome awesome awesome okay and let me go ahead and let me try to connect to my mongodb there we go as you can see we're connected to our db database okay so that's fine so our database has not been created yet because we haven't saved anything but it will be created once we actually start saving stuff okay so now i think that should be fine we'll set up the session store at the very towards the very end because that's not really important right now okay so what's important is we save everything to database so we're gonna go ahead and let's import the user so we're gonna go to database models user and i think i had imported it as an export default so no no curly braces no destructuring that okay so what we want to do is we want to get the profile so let's see we want the email address so let me minimize this let me open this up on the side so i can see what fields i need so we need the email id and then i think that should be fine if you want you can save the access token basically you can use the access token to call the discord api to do things such as getting the users roles you can get their guilds and etc we'll probably worry about that later but i'm going to go ahead and simply just save these two for now and we're going to go ahead and just say continue user or actually wait sorry about that we need to check to see if the user exists so we want to search the user by i guess we can search by email um yeah we can search by email notice how i'm not saving the guilds though uh the reason why you don't want to save the guild to the database is because um that data can actually stale data basically if the user leaves the guild the database will not auto update not unless you manage that with your discord bot so whenever the user leaves the guild you search the database and then you delete that record from that array but i would probably encourage you guys to use the discord api with the access token instead which is why i said later i will focus on showing you guys how to do that okay but we're going to worry about just saving the email and the id so we're going to first check to see if we can find the user if there's user that exists by that email so we'll do const find user or i'll do i'll call userdb and we're going to use async await so i'm going to put the async keyword in front of this function and we'll do await user defined one passing the criteria and i want to see if i can find it by the id i guess i can do both i can do both so it's not like it's going to matter too much okay so we'll find it by id so let me actually also wrap this inside a try catch as well okay so if the user db was not found we're going to create the user however if the user was found we are going to call this done function that's a callback function and this function takes in an error user object and info object you can see there's three parameters we're only going to worry about the two so if there is no error then there will be no error that's thrown because we're using try catch so the error will be null and we want to pass in the user db object right over here just like that however if an error has been thrown we're going to catch it down here and then we'll return error and then null so just let me just double check just to make sure i passed in the parameters correctly so it's error first and then the user okay and in just a sec i'll explain what this done function actually does but for now let's go ahead and actually create the user so if the user is not found then we're going to go ahead and create it so i'm going to go ahead and just put a simple console log down here we'll just say user was found and then inside here i'll say user was not found user was not found okay and to create the user with the mongoose it's very very easy we'll simply do await user or reference the model dot create and then we'll pass in the fields so id and then email okay and i'm actually just going to go ahead and do this just so it's on the same line i think uh i don't think we need to save it i'm not sure we need to save it i forgot it's been a while but i don't think we need to save it um we'll check it out just a sec okay but let's go and test this out so let's just make sure our app is running let's see what's going on oh it's giving us an issue because we have customer scheme down here i forgot that these things are not hoisted so we have to put that up there okay there we go all right so let's go ahead and test our app so let's go over here so let's go ahead and authorize let's see discord id oh did i accidentally oh i forgot i named it i think i named it a discord id that's right whoops let me go ahead and fix that okay but let me just go ahead and mention something real quick you can see that we actually uh it actually went into this if condition and you can tell because it's saying that it was trying to create this is an error that is used so i think it's trying to create it trying to create the uh the actual thing but you can see that we don't have the discord id uh property we have id but don't worry we'll fix that um all right you know what i'm just going to change it to id just change the id obviously if i've multiplied these you would just name it but i'll just use it as id for now screw it all right let's try this again so let's go over here let's authorize so it says unauthorized that's fine let's look at the console so it says user was not found creating and you can see earlier said user was not found creating so it gave us the error because we had the wrong property name that's okay now you can see user was not found creating so now you can see that it has this log user was found okay so we'll don't worry about that for now so users now found creating we created the user now let's just double check our database just to make sure that uh it's been created so i'm going to just use the shell so let's just show these so we have our databases so use stripe app check tables db.users.fine pretty okay so it seems like i don't need to call the save function usually if you were to create an instance so if you were to create it like this so user and you were to pass in all the fields i think you would need to call dot save but if you just use user.create you're fine okay so there you go we have our record perfect that's great that's amazing so what we're going to do is oh i forgot to also return done so there's no error we're going to return new user okay remember we're returning new user inside this if condition because the user db was not found okay the user db the user was not found so you don't want to return user db in here that's null you want to return a new user the new user that was created okay i'm just going to delete these logs actually i'll just leave it there for for later in case we need it okay so let's go ahead and let's re-authenticate so now it says failed to serialize user into session okay so this is happening because we don't have the passport. and deserialize functions setup so this next part we're going to go ahead and set that up okay so first of all what exactly is serializing and do serializing when it comes to sessions well serializing basically allows us to choose how we want to save the user to the session so for example usually with the sessions you typically want to save any data that has to correspond to you know any kind of activity the user is doing so for example if you have a checkout form or if you have some kind of a shopping cart right you could save it all on the front end okay but sometimes a lot of applications save it on the back end and what happens is they get the cookie from the front end and that cookie is searched through the database and once they find it it will give them back all of the pieces of information that was corresponding to that particular session so again sessions you can think of it as a way to persist the state of the request so it allows us to keep track of what the user is doing now we need to serialize every single request or not serialize everything request but we have to deserialize every request so we know who exactly is trying to make that request okay so we'll set up two functions so passport serialize user and this is going to take in a callback function takes in two parameters it takes in the user object and it takes in done okay and you can see that right over here if i hover over it you can see the done takes in an error then the id okay all we're going to do inside serialize user is we're just simply going to go ahead and just call done and we're going to pass in null because there's no error and for the id so you can actually pass in the user id right over here so i'm going to pass in the user id just like that okay remember that id is the name of the property for the user right over here we changed it from discord id to id okay so that's just all we're going to do for serialized user we're going to call the serialized user this is going to take in the id and then done okay so notice how this serialized user takes in the user object but this d serializer takes in the id the truth is that whatever you actually pass into the second parameter for the done function inside serialize user that is what's going to be taken in as a parameter in d serialized user so it goes like this so user.id that gets passed into here hopefully that makes sense okay i can even console.log2 and i'll add console.logs just so that you guys can keep track of what's going on so serializing user and then we'll log the user and then we'll say the serializing user and and we'll say the serializing user and we'll just console.log id so inside the serialized user what this is responsible for is it's basically responsible for searching the database so what this deserialized user function is responsible for is it's responsible for searching the database to see if the user is found okay the reason why we saw the failed to deserialize user or serialization sessions because we didn't have the actual functions right but this function is used for searching databases c if we can associate this id that we were given with any user in the database okay so if the user is not found in a database it's going to return null which means that that user does not exist we there's no session to be created if the user is found okay that means we're going to be able to return it back and what happens is it actually attaches that user object to the request dot the request object and what actually happens is it attaches that user object to the request object and i'll show you guys that in just a second but let's go ahead and first let's actually make this an async function and we're going to do is we're going to go ahead and say const userdb awaits user defined one pass in the id and we're gonna use ternary operator so if userdb is truthy then we'll return done there's no error userdb and we're going to return the null and null now i'm going to go ahead and just wrap this in a try catch so if there is an error we'll just console log it and then we'll return done error null okay so let's go ahead and just look at what's happening and then i'll explain it again so you guys get a better understanding so we're going to authorize and now it says okay so let's look through the logs and let's see what happened and then we'll look at our databases see what actually happened as well in the database part so it says user was found we serialize the user okay and you can see right over here that we log these over here now i didn't call it deserialize user yet because this function is only for subsequent requests so if we were to visit any one of our routes for our api it's going to basically use this function every single time to check to see if that user if that session is good if that session corresponds with that user and if it does it's going to attach the user object to the request object okay so let's go ahead and let's see let me go into database let me see if any sessions were created nope okay so no sessions were created in the database because we aren't using a database store or a session store rather okay so right now if i were to restart the server uh nothing would work okay because we don't have a session store so let me actually show you guys something real quick so let me go into status so i haven't restarted server yet but let me go to status and you can see it says okay and if i go to the logs you're going to see this deserializing user now okay and if you look over here that's coming from over here and it's logging the id and because the user is able to be found we are good okay now if i restart the server right now let me restart it i'm going to go to visit and nothing changes because we didn't implement anything but you can see that it's not even deserializing the user because we aren't even saving any of these sessions to the database okay so basically the session only works right now as the app is running but if the app restarts then all of the sessions are gone and you don't want that because you know that would probably be bad for the user so instead we'd rather do is because let's say for example right let's just say for example if your server crashes and the user is doing something okay well all of their data is gone like their current session is gone if they're playing a game or if they're you know shopping for something let's say they have like 500 items do you really want them to have to add everything all over again no right you want to make the experience for the user as the greatest as possible like the best possible that you can possibly make so let's go ahead and focus on implementing the session store and once we're done with the session store that should be pretty much it for the authentication part okay so let's go ahead and go back to the auth.js file and instead of sending this 200 request why don't we send the actual user so i'm going to go ahead and send the user and i'll send the session id as well okay and why don't we also let me see can i actually reference the deserialized user or the session id here i don't think i can but that's fine so why don't we do this let's go over to status right now you'll see that right now we're not logged in and it's not giving us the user back well why don't we go ahead and log in let's click authorize and let's go over to status and you'll see right now we are logged in okay our sessions are currently saved in memory by default if i refresh you can see that i have the session id and basically i can use the app but if the server goes down if it goes back up my session has been gone because it saved the memory okay so what we're going to do in this part of the series or the video tutorial is we're going to go ahead and implement the session store and we're going to be using mongodb okay so session stores uh you can pretty much use whatever session store you want literally all it is is just a table in a database or a document in a database it's really nothing complicated really like don't overthink it all it is is really just a place to store your session ids okay so you can save it in redis you can save it in my sql mongodb you can save it in postgresql whatever database you want now typically what i like to do is i like to use my sql and i usually save the sessions in redis because it's i think it's a lot better to save in redis because redis is pretty fast and it makes sense to use sessions for that because redis you can also set a time to live for that session id so after let's say 60 seconds it will expire and the session is pretty much done in a database you have to be responsible for making sure that it's clearing sessions periodically sessions that are outdated okay but we're not going to over complicate it let's just use a mongodb so earlier i installed the package called connect so make sure you install that npm i connect hyphen and we're going to go ahead and just import that right over here so i'll probably just call this a const connect connect or actually i think i'll call it store and right over here we're gonna go ahead and do const store actually let me call a session store and we're gonna do constant store and we're gonna call session store we're gonna pass in the session right over here so that's this right over here okay and we're gonna do is we're gonna reuse the same mongoose connection or mongodb connection you can do that if you're using a mongoose so we're going to go and simply do store and then new store and then for the connection mongoose connection we're going to reference mongoose dot connection so notice how everything is in a specific order so we're connecting first and then we are registering the middleware okay so this should do the trick and now if we go ahead and let's refresh right now so let's go ahead and re-authenticate right now okay so we're good and now you can see that user was found let's go ahead and look inside our database to see if we have the session table and there you go we have it so if we go ahead and do db.sessions.find.pretty you can see that we just have an object and it has this session property and this session property has the cookie it has the uh it has everything it has the id it has the expires so you can see that it expires in literally one day this is in utc time i think it's a utc string uh date string or whatever you call it and yeah that's pretty much it so you can see how uh over here we have this uh passport field which has this user object and it has only the id the reason why the id is over here and only the id is because that's what we saved to the database you can save whatever you want okay uh and let me show you one more thing let me show you one more thing i'm going to open up my browser i'm going to click on application let's go to cookies you can see that right over here let me zoom in you can see we have this cookie and this name is called connect dot sid and you can see this is how the cookie looks like if i remember correctly the cookie is i think in base64 format i think sometimes you can tell as if there's this dot so you can see everything from everything after s percent all the way up to this dot that is the session id if you look at the database uh let's see oh wait i'm sorry not not the s percent it's s percent 3a and then you got the pl or pi or whatever so you have to yeah that's an l i think so pl six v so you can see it says p o six v and it goes all the way to c so if i want i can copy this and i can try to search for it and let me see if i can search for it like this i should be able to there you go i just searched for it okay i just do do more thing you can see that's empty but yeah we can all search for as well okay so this basically over here is the cookie that the browser or the client stores okay so since we're using a web app the browser is going to store this cookie and what happens is this cookie can be used to validate all of our requests if you were to clear this cookie okay i should have went to the status page first but now you can see that it doesn't work anymore it doesn't show our user let's log in again and let's go ahead and authorize and now let's go over to status and there you go we can see our cookie if we go over to the database you can see that we have another session okay 5 four five four e f five four e f right over here okay so if i refresh there you go if i delete the session so let me see if i can drop i'll figure out how to do that db.sessions not drop if i refresh you can see that i am no longer logged in because all the sessions were deleted from the database okay even though we have the session the cookie stored on the browser okay but we can always like i said re-login and then you'll create a new session all right so that's pretty much going to be it for the whole authentication we've pretty much already gotten everything pretty much good to go for authentication uh everything works the way it should so i think for the rest of this tutorial we can actually start working on the front end and once we get the front end stuff going we can start making requests to the back end and then we can actually worry about the stripe integration okay so i'm going to go ahead and get started on working on the front end part now
Info
Channel: Anson the Developer
Views: 1,431
Rating: 4.9245281 out of 5
Keywords: how to code, javascript tutorial, how to code in javascript, async, python, web dev, css, javascript, typescript, react, react native, react props, props, class component, react component, angular, vue, front end dev, front end tutorial, react tutorial, reactjs, react router, react navigation, react class component, full stack, web development, developer, software engineer, java tutorial, java beginners, java programming, java programming tutorial, computer science, java
Id: VGo2WbvHurU
Channel Id: undefined
Length: 77min 14sec (4634 seconds)
Published: Sat Nov 28 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.