OAuth2.0 React + Passport Course | Full Dev & Deployment

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on hope everyone is doing well so today i decided to put together a long video about using passport locally as well as using the oauth system that they have so that we can authenticate users on your application using third-party applications so oauth the meaning of it is going to be that third-party services can access and exchange your information without you having to give away your password this is very appealing because a lot of people don't trust your login page and they would rather use google or facebook or github to authenticate themselves on your application i know i've used oauth a million times on other websites and i think it's honestly incredibly vital to learn something like this because um this is something that whatever project you're building is going to be nicer if you can just implement this i haven't seen any videos implementing the oauth plus local authentication and then deploying it you know this is like something i just could not find a video on but thankfully i was able to put it together figure out how how to do it functionally and i think it's going to answer a ton of questions i got on my previous youtube videos i obviously asked hey what what video should i do next and i just continuously was seeing do oauth oauth oauth and i thought okay well let's put these to rest and let's do oauth and then let's do local on top of that and then let's deploy the thing to heroku so that there's you know we've sealed the deal with passport like we know how to use it so um hopefully after this course because it's so long of a video it'll be a course um you guys will understand how this system works and be able to implement any strategy you want and authenticate any user using javascript and passport so let's see getting into it we're obviously going to be wanting to use the passport library and we are going to pick three strategies just because i've chosen these you can choose whatever strategies you want but i'm going to be using twitter github and google as my third-party applications to authenticate users right so getting into this we're gonna have two directories as we always do we're gonna have a directory for the back ends and then a directory for the frontends so i'll make the frontend directory then i'll make the back end and we do this because these are gonna be running on separate servers technically so the back end is going to run on a separate server than the front ends and you'll kind of see what i mean later when we actually deploy this but that's kind of why this is practice but anyway now what's going to happen is i'm going to cd into the into the front end and install react there so i'm going to run the create react app typescript template and install in the current directory which is client then in the back ends i'm just going to initialize the back ends with npm y oops let me try that there we go so we've initialized the back end with a package.json now in this nodes file here i have a huge list of the dependencies that we're using and why and then the development dependencies we're using and why right here so i have the dependencies that we need for this project and why we're using them and we'll just sort of use these as time goes on and i'm going to be updating this file so it's not perfect right now but um i'll be adding to it as we go along so yeah you can check this out if you want an explanation on what packages we're using and why so the first thing i'm going to do in the back-end folder to build this out is to make an src folder just because it's a little more organized and then to fill it with um a typescript file so that we can just get the thing started i'm going to install the express package so that we can get the basic routing setup and then obviously because we're using typescript we're going to need some typescript related dependencies so i'm going to install typescript and then the express types package that you see here and then on top of that i'll install the compiler for the development dependency which is going to be ts node so that we can actually compile the typescript and run it and all these are going to be development dependencies which means that we don't use them in production we just use them to write the software but we're not going to actually need them when we build the application and convert it to javascript so all that's going to get us started with writing the basic essential which will just be our um you know something like a hello world so i'm going to do my const app equals express as always so now the the app is going to be an object that sort of holds um a ton of different methods on it we're going to call it get method and we're going to say on the home page render hello world sure that's good enough and then i'm gonna make the server start by running the app.listen command and when the server starts we'll just log out server started and again if you guys are super new to all of this and none of the express stuff makes sense to you go watch a few videos on it i recommend anyone there's tons of people who make awesome content on how express works but it's not difficult and when you're done with that come back and you can follow this tutorial a lot easier i noticed that when i personally learned this stuff i needed to start really simple with brad traversing a few other people and just kind of understand how the back end works in express works and then i was able to do the more complicated stuff like authenticating with passport that's a more advanced feature so once you have all of this down we're going to actually compile it and launch it so we're going to go back to the package.json and i'll create a development script so i'll just call the scriptdev and i'll do tsnode index.ts so there's actually a couple things that we have to do to get this to actually run and the first one is is that we actually need to move into the src folder to grab the index.ts because we put it inside of there but more importantly what we need to do is add a ts config.json and that's because at runtime ts node uses the tsconfig.json to parse everything so let's go and add that so i'm going to paste in a default ts config and check the description below right now and grab the file and just copy it and paste it into your ts config.json and then once that's done we're going to be able to compile this and everything should run as expected so let's just run inside of the back end directory yarndev and we're going to see servers started which is what we um what we call when we uh start the server so if you navigate to localhost 4000 where we're hosting the server everything is up and running as expected now because i'm going to deploy this to production i'm going to add a few scripts so that we can build and turn the typescript into actual javascripts so that when we're actually running it everything runs as expected um in production so what we're going to want to do is add a start script and then a build script because later on we're going to be building our typescript files into javascript and then running that and you'll see what i mean later on when we're actually deploying this thing into production but essentially the browser cannot read typescript it can only read javascript so we need to build and convert our typescript code into javascript so that the browser can actually read it and understand what's going on so with the build script all we're going to want to do is run the tsc which is going to be the typescript compiler and then we're going to build everything that is in our directory so we're just going to put a dot and then real quick we're going to want to add the p flag to it so dash p build everything in the directory so now if we run the build scripts what we're going to get is this folder is going to pop up with everything that's built and this is going to be built with the ts config.json configuration which says our output directory is going to be in the build slash dist folder so you should get this which is essentially the converted typescript file into javascript and then to actually run this javascript all we have to do is go back and say start is going to be the build directory slash dist slash index.js and so to start it let's also put node because node is going to be the um runtime so node builddist index.js will be our start scripts so let's try it and our server is started so what we're seeing here is that we're actually building our typescript code into javascript code and then we're able to run it as javascript and this is going to be crucial when we are using production and you'll see what i mean later but when we're using development we're just going to want to build it and start it on the fly with ts node so now that that's all set up we can move on to actually coding the back end and let's just hop into the src index.ts and let's let's start the project so i've made a ton of videos on passport in the past and this video is not going to be very different from them so but essentially what we need to do next is connect to our database and you can use whatever database you want if you want to use postgres if you want to use mysql whatever you want but i'm going to choose to use mongoose because or mongodb and that's because i think it's really really beginner friendly and it's super easy to connect to so all we have to do to connect to it is first off import the package or mongoose package so if you go over to the notes file i made i have the mongoose dependency listed here and it's an orm to access resources for the mongodb database so let's go ahead and install mongoose so in the back end folder i'll do yarn add mongoose and then i get the actual types the type definitions for mongoose we're going to want to add yarn add at type slash mongoose dev so that we can get the types for mongoose so now that that's done we are going to want to go to the mongodb website and create a cluster once you've created a cluster and you have it all here press the connect button and then you're going to want to click connect your application put the driver at node.js which is what we're using and go ahead and look for the uri string here so i'm going to copy this uri string go back to my application and we're going to be using it here so now i want to do is do run the mongoose.connect the first time to import the package so i'll do import mongoose from mongoose once that's done i can go down here and say mongoose.connect paste the connection string and then after it you can see we have some options to include so i'll put an object for options and then we can have a callback function so put another comma and write an arrow callback function this will be called when everything is run successfully so we've reached the callback function because our application has connected to mongoose so i will just log in the callback function connected to mongoose successfully okay and then in the configurations i'm sure we have to add a bunch of stuff but we'll just run this and do that later and for the password because in the string here it doesn't fill out our password for us i'm going to put admin and then in the db name the database name i'm not entirely sure i'll just put um i'll put oauth uh i don't know o off and then let's run yarndev so now it's going to say we've connected successfully obviously if you put your password here um correctly everything should go as planned and it's warning us to add some configurations like the use new url parser and the use unified typology so we'll go to the configuration object for mongoose and we'll just set these to true like that and then if we go ahead and stop it and start it again we're going to see everything go through without any warnings hopefully cool so to actually get the server to restart on its own we're gonna add the nodemon dependency so let's go ahead and get to that so we'll do yarn add nodemon.dev once we've added nodemon in we can come back to the package.json and change the development script to be nodemon so that it should run nodemon tsnode src index.ts when we do the development script and this will restart our server on every save so let's try it so we're actually getting some errors and it's because we need to add the dash exec flag for node want to execute this script here so nodemon execute this script so let's try that again so everything starts as we've expected and now when we save it's going to restart the server for us so now that that's done let's actually use the env package to separate our connection string up so it's more secure and this will actually look secure inside of production okay so for this next part we're going to actually use the package called dot env so let's go ahead and add that yarn add dot env and this is so that we can add environment variables to our application so to import it we just do import dot env from dot env and then to initialize it in the beginning of the application and actually get the variables we run env.config and this will load the variables from our env into our actual application so that we can use it so now let's add the env file so that we can add some actual environment variables so we're going to split the string up in a bunch of different ways so that it's really hard to to crack and there's a bunch of ways to do this but i personally prefer splitting up splitting the string up into four segments and i've done this before i have the start segment i have the username segment i have the password segment and the end string obviously this colon here i'm going to leave out so here's what you should have mongodb srv your username password and then the end of the stream so let's start naming them so i will name i will call this start mongodb equals mongodb username mongodb password and then i will do and mongodb you can call it whatever you want but i just prefer this as my default and then obviously we deleted the colon here so we're going to need to add that when we actually put the string together so back into the application we're going to turn this into a template literal so that we can put our variables here so first thing we need to add is the start mongodb from the environment variable so let's add that so we'll do process dot env dot and then we'll paste it then we need to add our username so we'll do the exact same thing process dot env dot username then we won't forget the colon let's add the colon there and then we'll add the password so process dot env dot password and then we'll do the end mongodb string which is process dot env and then the end everything should start and run successfully and the reason we put them into environment variables is so that people can't look at the source code and see your credentials so that when you host this publicly nobody can see what your mongodb credentials are only the environment that's running your application knows what they are and you can only grab them from the code so this is a secure way of putting credentials and stuff into your application so now let's just run the dev scripts everything should run as expected so as you can see servers started and connected to mongodb successfully with no errors but now we're using the environment variables so now let's actually move on to the other parts of this project so i've done this section many times um in my previous videos in all of my previous videos it looks exactly the same but we're going to add some middleware to our application and i'm just going to paste some code here and go over it but this middleware is going to essentially just be some configuration settings we need to set up so that everything goes smoothly so first off we're going to use the course package we're going to need to install that so let's do yarn add cores and then we'll add the type definitions then we'll import it so then we need to use express session so that we can create sessions in our application okay so we'll do yarn add session it's actually called express session then we'll do yarn out at types slash express session all right and then we'll import it like so then as you can tell we have cookie parser not going to need that but we have passport initialize and passport session so now last but not least in our middleware we're going to need to install passport so then i'll do type slash passport and i just realized that i installed some of my dependencies without the dev flag so i'm going to take my type definitions and move them from the dependencies to the dev dependencies because i just forgot um i forgot to do that when i was installing them so just ignore that and make sure you install those as dev dependencies so now once we import passport we should have our middleware section covered and now that that's done our middleware is going to work and the express is going to create a session and we have passport initialize and passport session all set up all right so for this next portion we're actually going to want to go into a react project which is stored in clients and let's go ahead and just start our clients react server and get started working on it so we're going to want to build the front end and the reason for this is because we want everything to be in order and then we can implement the login options so now if you look at localos 3000 you can see that everything is up and running smoothly and what we're going to want to do from here is separate everything out into folders and add some react routing to it so the first thing i'm going to do is make a new folder and call it components and in the components folder i'll make a component for home page oops i'll make a folder for home page and then in the components folder i'll make a component for login page and let me fix this real quick all right so you should look like this components home page and login page so in the home page we're going to want to put our javascripts or typescript file homepage.tsx same thing with the login page we'll put loginpage.tsx and then we're going to use css modules for this project so do login page dos module dot css and the reason we're using css modules is because it's significantly easier to use a large amount of css in your file and work with it across multiple pages so we'll do the same thing for home page homepage.module.css okay now in these pages i'm going to use my react snippets and just do rfc and get a default functional component to fill out my home page with something i'll do the same thing with login page i'll do a react snippet and i'll get my login page here and so once all that's set up we can move on to actually going to this page our app page and adding some react routing so we can include these components on different routes so i'm going to stop the server and i'm going to install react router dom so let's install react router dom like this and then after that i'll install the type definitions for react router dom because they don't natively come with typescript support like that and this is going to be a development dependency meaning we don't need it in production we just needed to build the typescript code and so once that's done let's go and get rid of this big block of code and let's even get rid of everything inside of here let's import browser router from react rotor dom and i have videos explaining some other features of this but this is just basic react and in react routing so then we'll import react rotor dom here and we'll put all of our links into the browser router component like this so now we'll add a route component for the home page and then a route page for the login page so let's do route path equals and we'll do slash component equals and we'll do homepage like this like that okay same thing for the login page and we'll store that one on dash login all right so now if we actually open our application we should see they're on separate pages let's add some content to our home page so i will just add a h1 that says welcome to my website then on the login page i'll add an h1 that says login all right so now on the homepage we see this and on the login page it's going to actually render both components because we forgot something let's go back into our app and then let's just add the exact keyword on the home page route and this will keep us from rendering both pages at once so now the home page should say welcome to my website and the login page is going to be rendering the login component so they're both log they're both rendering their own components so let's go ahead and do some cleanup here i don't need this app.css file i don't need to test the file i don't need this logo.svg and i don't need this index css file all right and i also don't need to set up tests.ts file because i'm not going to be performing any unit tests this time so now let's remove our unused imports and then back on the index page we'll remove our unused import here now everything should be good we can even remove the web vitals because we won't be using it so let's delete this report web vitals file delete it here delete it there and now we should have a very simple looking clean file structure everything should render the same like so so now on the login page let's start actually building a login button so i want to build a button that says login with google because i want to pretty much create something that looks like this and so all i have to do is just make a div put a tag in there that says log in with google and i want to put the google logo next to it so i'm going to go and get a google logo so as you can see i've already googled this before google logo transparent and i'm just going to grab whatever i can find i feel like this looks fine you can just go to my github page and get whatever file i picked um but i'm gonna choose this one so now let's save it in our folder in our src folder and i'll make a new one called assets then let's save it there so in visual studio code you can see the image has been downloaded and i'm going to change this to call it google image like so alright so now that i have my google image i'm going to import it at the top of the home page or actually login page sorry so the import google image from assets google image dot png like so and then i can put an image and plug it in here so we're gonna create something that looks like our example so it's complaining it wants an alt tag so let's just add an alt tag cool so now all we have to do is add some styling so i'm going to give this a class name so i'm going to give this a class name of google container and because we're using css modules i'll import the styles from this page and i'll plug it in here and you'll see what i mean so do import styles from and then link to the css module file we created which is here and this is a really effective way of separating our css code so it doesn't become bloated and shared over multiple pages so i have to do is just include an import like that for css modules and then plug the styles in like this class name equals styles dot and then whatever you want to call it so now if we just define google container here we can add styles to our page without having to include them globally so that's the benefit of css modules so i'm just going to paste some styles in that i've already pre-written and you can grab these from github but i don't want to write css live because i think it's a massive waste of time and it just requires too much fine tuning so go ahead and just copy this over from github and paste it in and what you should get sorry let me save the files and what you should get is a login with google um button so we're gonna see something like this which is fine for now so now that we've added this button here the next thing we want to do is we actually want to center this button and make it look like this form here so that we can add multiple um third-party authentication methods and stack them on top of each other so the way we do that is we put a div here which is essentially going to be our container for our methods and i'm going to give it a class name of um let's see login form or something like that all right and then now what i want to do is add some styling to it but first i'll add a class to the parent um div and i'll call it login page oops styles.login page okay so now if we go into the css we can add some styling for a login page and the login form so login page needs to be a centered box so that it can center everything and so we would do that by width 100 viewport widths and then add some properties to the center everything so i'm going to do flexbox align items center justify content center like so and then on the form we're also going to want to center everything and then what i'm going to add is let's see a max width of 600 pixels and a min width of uh 40 viewport widths that should be fine and then what we need to do is add a flex direction to the login page of column and that's going to give us a layout like this so now what we can do is let me add a height property of hmm actually i'll just leave this blank but i want to add a border so i can see what the login form actually looks like so the login form currently looks like this and as we stack methods on top of each other it's going to expand the page so what i think i want to do is um i'm going to add an h1 inside of the login form and then just say log in that should be fine and i'll delete the login page thing so that's going to leave me with a decent looking result oh let me just add flex direction column to the login form okay so now just make sure your code looks like this here's my other page and you should be left with something like this so this will be our login page so now that that's done we are going to want to actually add a navbar at the top so that we can cycle between our different pages easier than changing just the url here so we're going to build a navbar component so come back over to the component section and we'll create a folder for navbar so i will make a file inside of the navbar folder called navbar.ts x actually tsx and then we'll make a css modules file like that let me just plug in my react snippet rfc and then we can import the styling import styles from navbar.module.css there we go and now we should be set up with the navbar all we need to do is plug it in over in the app.tsx file so what i'm going to do is create a switch statement to actually hold our routes like so let me import it and then what i need to do is then add the nav bar at the above the switch statements like so and so now the nav bar is going to be displayed on all pages so when we actually add something to the nav bar we should see it at the top so let's go ahead and try and add something um let's just build a basic navbar i guess we'll make a ul list here and then i'll add an li for the home page i'll just call it home and then one for login and that should be fine for now so we're gonna see this snap bar up at the top now let's add some styling to it all right and then i'll make a div above the ul and i'll title my divs class name navbar wrapper so now let's add some styles to the wrapper which is going to be our parent comp apparent element sorry i know that some things are camel case and other things are not so just for the sake of this i'll just keep it consistent with camel case instead of pascal case so i'll keep this as camel case as you see here so we'll style it add a width so it stretches all the way across like that all right and then we'll add a display flex to it and then we will now customize the nav bar here i'm going to also add flexbox to it so add these three lines all right and let's see how it looks now yeah so we're going to want to put the justify content at space evenly see actually we'll do space around flex direction row and what a width and height property i'll just do width actually with the hundred percent so as you can tell this looks terrible i'm going to keep it at space evenly so now your css fault should look like this and this will work and now that that's done we're going to remove the dot here by just styling the li inside of the nav bar and add a list style property of none like that and that's going to leave us like this so we have a home page and a login page and i'll even change this to be a pointer of cursor like that so make sure your css file looks like this or you could have just copied it and it doesn't matter and come back into the nav bar and we will add a react router inside of here to actually link to the different pages so i will do import link from react router dom and then i'll add the link inside of the li oops link and then we're going to close it like that and then i'm going to add a path so i'm going to say link to slash which is home let's do the same thing with the login and the path is going to be slash login so your nand bar should look like this so once that's done we're going to get this weird purple color and we can fix that because if you actually inspect element you'll see that by default the nav bar comes with a or sorry react router route component comes and it creates an a tag for us so all we have to do is go back into our style and style the nav bar lia or sorry navbar a anchor tag and change the color to white and that should fix it and then we'll we'll delete the underline by saying text decoration none that'll fix that for us so now it should cycle us between pages like that and that's going to be just fine for this application we don't need to style it and make it look super pretty it's going to be good enough alright so now we can actually implement some of the strategies and passport inside of the back end so that when we click on this login with google button it actually will take us through the google oauth login setup all right so what i'm going to want to do is actually kind of fix this so that the font looks a little better and i'm going to do that by using the pop-ins font that i have in the login page so i'm going to copy this guy and i'm going to go into my src folder and create a new file and call it global styles import this and let's give a styling to all of the text all right that should be fine for now and we'll do a fall of poppins and then fallback of sans serif okay and then let's import it into our app.tsx import global styles dot css all right and that should load every um everything to have the pop and spawn cool so that looks better now what i want to do is actually want to make this button work so we should be able to authenticate and log in with google by clicking on this button and so we're going to need to go into the back end to do this so open up the backend folder and we're going to start working on this index.ts file what we want to do is add the google strategy for passport so go over to my to the repository linked in this notes text the google oauth 2.0 repository go ahead and click on it okay and then inside of here we can just follow their guide at setting up the google strategy and it's unbelievably simple it is so simple to set this up first off install the passport google oauth 20 package so let's do that yarn add password google oauth 20 and then i'm going to add the type definitions passport google oauth20 like so and then once that is done we can just import the package up at the top which i've already done and you can tell so um let me just erase that and i'm going to copy their import statement and let's paste it in const google strategy equals require passport google oauth 20 dot strategy so now what we want to do is actually copy this setup function so this is to create the google strategy with passport so all we got to do is go down below the session and let's add our strategy so passport use new google strategy and we have this set up here so what we need is a is a client id and a client secret and a callback url and we can get all of this stuff over from the console.developers.google.com and once you're loaded into the api console we're going to want to create some oauth keys and we need to do that by first of all i think you have to create an account and then once you've created an account you need to actually make a new project so i will make a new project i will call it oauth 2.0 google video something like that whatever and make sure they're just hyphenated no spaces all right whatever i'm just going to call it google video because it seems upset once that's done we're going to need to go into the credentials page and create some credentials let's create an oauth client id and then for the application type of web app i'm going to name mine passport oauth video now it's asking for the authorized javascript origins this is going to be your back end so put your back-end url so my back-end url is currently localhost 4000 then for the authorized redirect urls this is going to be called on a successful authentication or actually it's going to be called on a response of an application so let's just put our back in url slash all slash google slash callback you can put whatever you want just make it consistent but i'm going to choose from my callback url to be this because i think it just makes it looks the best and it makes the most sense so now we'll create the keys this is going to give us a client id and client secret so let's copy them and put them into our application so here we go that's my client id and here's my client secret oops now i have this callback url so what did we name the callback url we did localhost 4000 off such google slash callback so let's just put it like this our current url google slash callback that'll be our callback nice so now this function gets called on a successful login or a successful authentication so once this is called we're going to want to do some logic like put a user into the database so i'm going to say insert into database so for now i don't want to do that i'm just going to do something really simple so that we can all understand what's going on and then i'll come back and fix it so i'm going to put a callback of null which means no error first parameter is error and then i'll just put the profile okay typescript doesn't like that i don't have type definitions and i don't know if this package has any so i'll just put everything as any all right so once that's done let me fix the spelling once that's done let's actually implement the rest of the strategy and i see that um we forgot some uh parentheses here so you should look like this this is gonna work and let me also just console log the profile so we can see the user profile and kind of like understand what it's sending us on a successful oauth login now let's go back to the repository and let's copy over these two request handlers let's paste them in and so what's going to happen is when the all slash google route is ran when a get request runs on it we will run the passport authentication google strategy and we will put the scope to profile now if you actually read what the scope is i don't know if they specify it in this repository but the scope essentially is how much data to give to the person to give to the back end and we can look at the oauth 2.0 google scopes here and we're going to be using the profile scope which it shows you here all it does is gives you your basic profile info we could put email open id we can even put urls here for the scope but all we really want is the person's profile so that's what we're going to put scope of profile all right and so on a successful authentication we redirect home so what's going to happen is we'll run a get request it's going to authenticate you using the configurations that appear and then it's going to call this function on a successful authentication and then whatever happens it runs this callback function so remember that order make a get request authenticate the user do something once they're authenticated and then if there's a success or an error we run the callback okay so now what we do on a successful authentication that we've shown here is we redirect home alright so now that that's taken care of what we need to do is actually implement the serialized user and deserialize user functions on our password setup and we're going to write that like right down here and what this is is that passport.serialize user if we hover over it maybe it gives us a description let me try it no i guess not so what it does is it takes in a user and then a callback so i'll make this an arrow function and all we have to do is every time a user gets put into the session we need to serialize it and you can read it here so in a typical web application the credentials used to authenticate the user will only be transmitted during the login request if the authentication succeeds a session will be established and maintained via a cookie in the user's browser each subsequent request will not contain credentials but rather a unique cookie that identifies a session in order to support this we need to serialize and deserialize users to and from the session and if you actually google this you can write some stack over you can read some stack overflow stuff about it so when we run this serialize user we save the user to the session which means that if we call the request.userobject will get that request.user and then on the deserialize user we get an id passed to us from the cookie and then we take that cookie and we find the user from the database and we put it into the session okay so you'll see what we mean later on when we actually implement this so for now i'm just going to return user i'm just going to return done no error and then user and then for the deserialized user i'm going to copy over the entire user object which you should not do but we'll fix it later user done and i'll return done null user and so we're going to be doing this in the initial part of this application and we'll fix it later you should only store ids inside of this cookie you should only store ids inside of this cookie not the entire user object but we will fix this later okay we just want to do this for now to get a working build and now that that's taken care of let's go ahead and start the back end with yarn run dev and we should be good to go all of everything um all of our passport google method should work now that's all we need so what's going to happen is when a user runs to a get request on the alt.google we are going to run the google strategy and we are going to authenticate the user with google once that's done on a successful authentication we're going to insert a user into the database preferably but for now we'll just return the user and log whatever it is and then it's going to return it's going to run this callback and it's going to serialize the user and store it into a cookie so all that's going to happen and every time we make a request we'll take the cookie and deserialize it okay so hopefully you'll see what i mean later on so to actually implement this let's go to our login page and all we have to do is add an on click event listener for our google container which is our google button so add it on click equals let's make a function and on the actually let me name this google login and on click of the google container we're going to run the google login function and all we need to do is run window.open and let's put the name of the backend url google handler which should be off.google let me check right so then we need to do add a string of just underscore self that should be all that's required so now let's just click on it and let's try authenticating with google and let's see what happens so we'll go to login and then log in with google as you can see this pops up and we can log in and if we actually look at the back end this is the profile that we're logging we get all of this data when a user logs in and then if we actually check the cookie which is in the browser so we go to application cookies localos 3000 you're going to see this massive cookie which is our session id so now the user is stored into our session and we've authenticated with google alright so now that we've written this configuration we actually want to check to see if the user is logged in and collect his data so that the front-end can write conditional code based upon the status this user's data so what we can do is i'm actually going to make a context hook and we can build that out by just saying i'll just say context dot tsx and we'll turn this into a functional component of course and up here we'll create the context variable that holds it on my context equals create context like so and we'll import it see and it wants something to initialize with and i'll just do an empty object so now in the return value let's return mycontext.provider like so and then we'll open these curly brackets and we're actually going to put the props.children and we can do that by importing the props and then running props.children here and this wants a type so i'll put the type of any and then on the provider i'll put a value prop and we can pass whatever value we want and anytime we render something inside of the context we are able to access this value so now actually i want to fetch the user's data from the back end take the data and store it inside of this value so that all of my components that go in here can access this data so what i'm going to do is install the axios package oops and the reason i want to do that is so that i can make my http request to the back end so this will install and then i need to install the types for axios and that's going to be a dev dependency and so let's go ahead and import it import axios from axios you can do upper case or lower case it doesn't matter i'll do a lowercase so now what i'm going to do is make a use effect hook so that we can actually get the user's data so now let's run the get request so i'll do axios dot get and i'll put the name of my back ends endpoint to fetch the user's data once i have it fetched i'll have a promise with the response and i'll say if we have a response dot data i want to store it in some state so let's make some state and i'll call this user object set user object equals use state like so and we need to import that and the reason i'm doing this is because i want to store the user's data that we get back from the api into some state and then pass the state into here that's the correct way to run the use context hook when we're fetching data so now let's run the set and we'll pass the res.data let's make sure that this has a type definition we'll just leave it as axios response for now okay and so now let's pass the user object into our value so now what we have to do is actually set the endpoint so that we're fetching this endpoint we're getting a response we're saying if there's data on this response then let's store that data in our state and then we'll pass that state to our value so that all of the children that flow through this can access this value that's the way our use context works it's really tricky super confusing and it's definitely an intricate topic but once you do it enough times anything is easy so now what we have to do is actually set up an endpoint that has our users data so we can do here is i'll make a app.get for let's just call this get user and of course we have a request and a response objects as a callback function and what we want to do is just say res.send so let's send a response of the request.user and now that's all we have to do to actually set up this endpoint it's super simple but there's a lot of complexity going on behind the scenes the request.user property has all of the values of the user because it gets attached on the deserialize user function so our user gets attached to the request.user and we can access that value here so even though this is a very very simple line of code there's a lot of complexity going on behind the scenes so now let's just call this endpoint so i'll call http localhost 4000 getuser i'll start my server oops i forgot to write that name correctly there we go and to actually get this used context hook to work what i'm going to need to do is i'm going to need to go into my index.csx and wrap my app inside of it so we'll do my context or actually we'll just do context like that and that's all we have to do now our app has access to our value property we created here so now let's go into the app and we can grab that value property i'll just call that variable user object and it's going to be use context and i'll call my context which is the name of the variable that's holding the context so let's export this inside of the context and then in our app we'll import it so i'll say import my context from context and this is going to need to be in the src i accidentally made the context file in the nav bar so the context should be in the src folder and the very last thing that we have to do before this actually works is we need to add a configuration object right after we run the axios get and we pass the first parameter and we're going to pass with credentials to true to this configuration object which pretty much says axios make sure that the receiver is aware of the cookies in your browser so pass those cookies from your browsers to the server that's what the with credentials is going to do so now if we actually make our request to the get user endpoint we're going to be able to see the object which we are logging inside of our window so we are logging this object out over here so we're using the my context hook to fetch the get user and then store it in state and then this state gets passed to all of the children props so now we can run the use context hook and pass it to it and we can grab that value from it so if we come to our axios get request and we just log out what we're getting back you can see that when we get when we run the get request we get back config data headers request status and so the data we're getting back from the server is all of this so we're taking that data we're storing storing in state passing it to the value of our context and then we can use it in our different application in our different pages so here we go here's our user object that we're logging out so now we have access to all of this stuff from a user just logging into your website with google alright so now that we have this functional login with google button i want to do the exact same thing with github so to make a login with github button i want to make something that looks exactly like the one we had before but a few things changed so what i'm going to do is first off erase this background color from the image that looks better then i'm gonna duplicate it so i'll just take it and i'll copy paste it so i call this one github login with github github icon i will even make a new function for it so i'll call it the github login and i'll just comment this out for now and now what i'm gonna do is i'm going to use some template literals to make multiple classes so i want this a github one to carry over the exact same styles from the google container but also have its own class name so we'll do it like this make a template literal and the first value we'll put in will be the google container and the second value will be the github container like that so now it has two classes the google class and the github class so now let's actually get a logo to put in there so i'm just gonna do github logo and i'll save this one i'm going to store it inside of that same folder but just call it github image and now i'll import it at the top okay there we go so now we should have we should have a separate button so now let's add some styles to it so i named my class github container so all i'm going to do is right down here i'll just do dot github container and i'll just add a background color of dark gray and i'll make it even darker so i'll just i'll put a value of 56 5656 all right and let's check it out so it looks good we just need to add some separation between the buttons so i'll go to the google container and add a margin of 10 pixels alright so now we have a login with github option so now let's do the same thing with twitter so what i'm going to do is just duplicate this and just say login with twitter i'll put the alt twitter icon and i'll make its class name to be the google container which is going to be the default class and then the twitter container and then i'll make a function as well for it and i'll call it twitter login like so and then we need to get an icon for it so let's go get an icon for twitter so i'm going to grab this one let's save it as twitter image let's import it and we'll plug it in down here and then i'm going to make it have a different background color all right and i'm going to put the background at 0 0 a 2 f 4 and that should look fine so now i should be good to go so as you can see we have the login with github google and twitter all is viable options for us to authenticate a user with obviously it's not perfect in fact i think that this can be a little smaller yeah something like that would look better but this is just sort of what we're gonna do is a rough shot and i'm going to modify the css file just one last time and i want to change the width of the images to be a little smaller like that looks fine i think the twitter logo should just be a bit larger so let's do that twitter container image and i'll do width of 15 and then i'm going to add a left property of 8 pixels so now here's our buttons and what we're working with and these are the three authentication methods we can choose from all right so now that we've implemented these buttons here i'm going to actually write the logic so that we can log in with twitter and the github api as well as i'll implement the database so that we can store users into a database so we're using a bunch of different oauth systems so i'm going to try and just get the data that we can from the different platforms and then store that into the database and i'm just kind of like winging this but i'm thinking that we're going to want a first name a last name of oauth system and we'll store this in the database later but first let's get the twitter oauth system working so to get twitter's oauth working i'm just gonna go go ahead and google twitter oauth passport i'm going to click on this one on github and all we have to do is install the package passport twitter so let's go and do that i'm not sure if they have the types package for it but it's worth installing anyway just in case they do but i honestly doubt it so then to import the package we're going to do exactly what we did up here all right and this should be good now if you actually look at the documentation for it we're going to do exactly what we did with the google strategy but now it's just for twitter so let's go right below our google strategy and let's just paste it in as you can see they want a consumer key and a consumer secret as well as a callback url so i'll leave these three strings blank and then for this lower portion down here i'm just going to copy over the code we have up top okay and so this is just going to leave it as simple as possible so that when we authenticate a user we are just going to return him and then we're going to log him as well so this is all we have to do to set up the twitter strategy so now we actually have to populate the consumer see a key secret and url and we can do that by signing up to the google we can do that by signing up to the twitter developer account so to do this you have to submit some information for twitter and you have to verify your email and you should be able to sign up with a twitter developer account then what you have to do is make a new project and then in your project you have to make a new application so i'm going to make an app and just name it would breakdev oauth twitter application that should be fine and then it's going to give us an api key secret key bearer token so for right now just go to the app settings in our app settings we are going to want to enable three legged oauth and we're going to want to enable this so that we can get the information from a user without actually having them to do two-step authentication so go ahead and enable it and then in our callback urls we're going to put the localos 4000 off twitter callback and we'll choose this to be our callback url and for the website url i'm just going to put localhost 4000. i'll make up some names here and this should be all we need so go ahead and save it looks like i actually have to type in a valid website url there we go so now that that's done let's go ahead and get our api keys so i'm going to go to keys and tokens and the api in secret i'm going to view and copy this over so the api key we have here i'm going to copy and we're going to paste in the consumer key and the secret i'm going to copy and paste in the consumer secret as well my callback url it's going to be locos 4000 slash all slash google oops twitter slash callback like so and that's gonna do it for setting up our strategy it's that simple now all we have to do is actually add the routes so let's scroll down a bit and just paste them right below our google routes so now what's going to happen is when we hit this endpoint we're going to run the authentication we're going to hit the callback and then we're going to be logged in and so this is actually all we have to do to go ahead and get started with authenticating using twitter so i'm going to go back into my login page and for my twitter login i'm just going to submit my endpoint to local 4000 alt twitter which is going to be this route we actually have to do is make sure that our redirect redirects us to localhost 3000 so that when everything's done and said we get redirected back to where we started so let's try it out now okay so everything worked exactly as planned and if we look we have the contacts getting stored all of this information that we are getting from twitter so this is all the data we get from twitter when we authenticate so passport now has a setup and we have a session user using passport so now what we have to do is stop this from opening a new tab when we press the login with twitter button and even though the self tag we see here should stop us from opening a new tab it's not so what i'm going to do is just say window.location.href equals and then i'm going to put it to have this string so this should just open it in the exact same tab we shouldn't be opening a new one so let's try it everything works as planned and the request.user has the session stored there all right so now that that's done let's do something really simple and let's start storing these into environment variables so i'm going to go ahead and start making my environment variables all right so what i've done here is i've just put my environment variables so that i have the client id set to the google client id and the secret set to the google secret same thing with twitter so now let's plug them in so we're using environment variables over actually using hard-coded strings okay all right so as you can see i've put everything into environment variables and now everything's going to run the exact same i'm going gonna go ahead and remove the console logs that are inside of my code because i think it's bloating everything up all right there we go and now we're good to go so everything's gonna work exactly as before but now we're using environment variables so let's go ahead and let's implement the github strategy and then we can move on to actually putting this into the database all right so the next part is going to be using our last strategy which is going to be the github strategy so we're going to head over and check out the passport github repository and we are just going to need to use this first one looks like this one is made for enterprise so that's interesting but this right here is going to be our oauth setup and this is going to be using the oauth 2.0 api which is more secure and has a bunch of new benefits to it so first of all we're going to need this import statement but we're going to need to install the packages first so i'm going to do yarn add password github and then we will do the types package like so and then over here at the very top let's copy over that import statement paste it in there cool so now we're actually going to get into using the strategy so let's copy over this code here and just paste it in i'm going to replace this bottom section with my bottom section so that all it's doing is just running the callback function to move to the next step with the entire profile so we're not shortening it like we should we're just gonna pass the entire profile right now obviously we have the client id client secret and the callback url so to actually get these you're gonna need to go to your github page you don't need to do any fancy setup and just go to the settings once you're in the settings you're gonna click developer settings and then oauth apps so now let's create a new oauth app i'm gonna call it woodbury dev actually i'll just call it oauth application test like so my homepage url will be the localhost 4000 which is my back end and the application description i will just say this is a video test of the oauth functionality inside of the awesome passport library build for node js all right and so the authorized callback url we're going to do the back end which is localized 4000 slash off slash github slash callback so now register the application this is going to give us a client id and we can create a client secret so i'm going to enter my password and i'm going to get a client secret so let's copy over the client id and paste it in same thing with the secret we'll move these to environment variables in just a minute and the callback url is going to be localhost 4000 slash all slash github slash callback which will just run our route that we're going to create in just a second so once everything authenticates it's going to hit that callback function or um the callback route i should say so now that that's done we are all set up for github so now what we need to do is just grab the routes here and just paste them in so let's paste our routes right under twitter so auth dot uh just runs the authenticate github function now on the callback all i'm going to do is just change this to res.redirect and then i'll do the home page of my react application so when everything is successful i will just put us back in our react application this should be all we need let's just move these to environment variables now because it's going to look a lot better so i'm going to take my client id and client secret and move them over to my env file oops let's just paste this in we don't want this in a string here we go all right and now let's plug in the client id and client secret and i'll just copy this over and let me double check make sure i did that right everything looks good so let's go ahead and start the server and try it out the last thing we need to do is just go into our login page uncomment this out and change this to github so we're hitting the github route we just created which is this route all right and as long as both files have been saved which they have over here the env file is correct and the login page is linking to that backend route then we're going to be able to click on the github and it's going to take us through an oauth process we can press authorize and it's going to redirect us to the home page so just like all of our other routes we should see some context here so this is what github is giving us when we log in with them it looks like the difference between this and the other strategies is that github doesn't give us a display name instead it only provides a username so that's going to be interesting because the database is going to need to be able to work with that we have a username here so let's see all right so the next step in this is going to actually be implementing the database so when every person logs in with either google twitter or github we should create a new user in the database and i've kind of found a solution that's somewhat okay but essentially the difference between these strategies is that google only gives you your actual full name it doesn't give you even a username or your email so the google strategy is different because twitter gives you a username github gives you a username so we're trying to find relevant consistencies between these so we can store users in the database consistently so what i'm going to do is i'm just going to store a user by their you know username and an id that's going to be it we don't have any more data we can possibly add to it we're just using these oauth systems so i'm going to make a username and an id so let's actually go into building the typescript interface so i'll make a new file called types.ts and let's start building the typescript interface so i'll make an interface and i'll call it i user and the reason i do that is the i stands for interface and it's an interface for user so inside of the interface i'm going to want to make an optional google id and this is going to be type string same thing with twitter optional type string and the same thing with github and then i'm going to want to have a username of typestring this should be all we need for the interface so let's go ahead and save it and let's move back and we need to create the model for the mongoose setup so let's make a new file and call a user.ts so now what we're going to do is import mongoose and we're going to make a variable so i'm going to call it user it's going to be a new mongoose schema and so what we need to do inside of here is actually put the different fields that we can store for our user object so the first thing we're going to have is a google id then we're gonna have a twitter id and then we're gonna have a github id and then we want a username so the google id is going to be optional because not everyone's going to log in with it spelt that wrong okay same thing with the twitter that's not required but on the username it is required because all strategies have a username so then what we need to do is add a type so i'll do type string twitter it's going to be type string same thing with github and the same thing with the username so this is going to be our schema that we actually use when we are creating a user let's do an export default mongoose.model give it a name and then give it the actual value and this should be lowercase looks good now let's move back into our index and let's actually start creating a user when someone logs in so the first thing we're going to want to do on a google strategy on a successful authentication here is we're going to ask is user created in our database so we can do that by importing our user and we'll say find one and what we'll do inside of here is for the google strategy we'll find one by the google id that matches the profile.id so what we're doing is when we log in with google we get this object back where we have the id the name photos everything and we're going to be comparing this value the google id right here so we have uh find one google id if it matches the profile id that's going to give us a callback of error or documents and we're going to want to say if there's no document present then let's create one okay so what we'll do is we'll actually fill this one out and we'll say this is going to be a type of i user let's go ahead and import this up at the top like so and i user is going to be exactly what our document looks like inside of mongoose like this and so if there's no document we will create one so i'm going to say const new user equals create equals new user and we'll create a new mongoose user and we're going to say it has a google id of profile.id and it's gonna have a username of let's look at this object we're getting back i'll do name dot given name so we'll do profile.name.given name like so and so this will create a new user because this is an asynchronous function we need to call it as async and we need to say await new user dot save and this is going to wait for it to save before we move on to actually running this callback down here so if there's no user in the database we're going to create one now the type up here is going to be type of error for mongoose and we need to make a statement for that saying if there's an error with our mongodb connection or something so we'll say if error return and i'll do callback error null meaning return the error from mongoose and then null meaning there's no person coming back okay so everything should be good from here this will create a user inside of our database now to test it let's go ahead and let's save the file and let's run it through so i'll go ahead and save and i'll go log in log in with google and now what we're gonna do is let's check the database so i'm going to refresh my cluster and we see the oauth table has been made or the oauth database and then the users table and we have this new user inserted so let's do the exact same thing with our different strategies now the only thing that needs to change is the object we're going to get back from the oauth authentication is going to be a tad different for each strategy so all we got to do is just go ahead and copy this so i'm going to copy here let's scroll down and let's paste this inside of twitter so we're going to do user find one by the twitter id and then i don't know what the object coming back looks like so i'm going to log in with twitter just so i can see so it looks like the object we get back is pretty similar we have an id and a username on this that now so i'm going to say find one by the profile.id and if there's no document we'll create a new user by the twitter id and the username we get back we will just do profile.username because the the object we get back has a username property so now we can actually save this to our database and that's all that's necessary to create a new user when the twitter authentication is used so now let's move on to the github strategy and we'll do the exact same thing so i'll say user find one by github id let me check what the github id object looks like so it appears that we have an id and a username on it as well so not much is going to need to be changed for this method so we'll find one by the github id if there's no if there's no github user then we'll make a new user we'll put it it's github id as a profile.id its username is a profile.username this is all you're gonna need to actually start creating users every time somebody uses oauth so now if we actually run and we test this out it's going to be creating new users with every time we have someone log in and if somebody already has an account we'll just use it so right now let's go ahead and let's check let's do login with twitter and let's check our database as you can see we have an object with the twitter id and its username is saved as the twitter username let's try it with github and if we refresh here we can see that we have a github id saved with the username of the github username so everything looks good right now so now we're actually saving and storing users every time somebody logs in so now let's grab this user from the database and start storing it in our session instead of the entire profile object we're getting back so to do that we're going to need to modify the serialized user and deserialize user functions so if we look at this gorgeous visual flowchart here you're going to see that when we call the serialize user function it's best practice to only serialize and save this user id here so let's do that and then on the deserialize what we should do is actually grab it from the database so let's look around for a good example yeah here's a good example so on the serialized user we should only be serializing the user id and then on the d serialize we should be taking this id grabbing the user from the database and then storing that as the request.user object so let's go ahead and let's implement this we know the user we're getting in the serialize user function is going to be this huge profile object so the first step in implementing this is we're going to want to change our callback methods here right now we're returning the entire object we're getting i don't want to do that i want to return the new user we've just created or the user that already exists so that we can get a consistent callback every time with consistent values so what i'm going to do is i'm going to take this callback function here and modify it a little so i'm going to go ahead and remove that i'm going to say if a document doesn't exist let's run our callback function here with the new user okay and then if a document does exist we'll run our callback with the document so i'm just going to implement this for all of our different strategies scroll down and let's implement it here so if a document exists let's run the callback with that so if a document does not exist we'll run our callback function with this new user we've just created if a document does exist we'll use that and what this is going to do is it's going to make it so the object we're actually getting in our serialized user and d serialize user function is consistent and looks exactly like this so when we serialize and deserialize we know our object looks like this so we're going to be getting consistent values back on every callback this is a little complex and i don't expect you to understand it the first time but i'm sure if you make your own project you'll realize this and you'll be able to do this yourself so it's not as complicated as it seems at first let's do the same thing here let's make sure we're using the callback with that new user or with the already existing one and now on this serialize user function we're going to be getting back the user from the database because that's what we're calling back here so we're literally going to get a user back that looks like this okay so what i'm going to do is only serialize its id up here so what i need to say over in the serialized user function is i'm going to say return done and then the user's id like so okay and it doesn't like that because we haven't told it that it has an object so i'll just put any so all we're doing is we're just grabbing the user from our mongodb database which we're doing here and we're serializing him but we're only serializing his id okay so then on the deserialize we're going to grab this dude from the database and return him so what we're going to do is we'll say we're getting back an id see right here we're returning done with the id so on d serialize we're gonna get back an id because we're gonna be grabbing this and then we're just gonna run a find operation so we'll say user dot find by id pass the id all right and this will give us a callback of either error or document and we're just gonna say return done with the entire dude that comes back so now if we run this we're going to get back the user from our database so every time we log in with google we're going to create a user it'll create a user in mongodb and then we'll run the serialized serialize and what this is going to do is grab that user from the database and return him so this is the way to do this safely okay so now let's actually check this out in our application so if we log in with google we're gonna just get back the google id username version and id literally the exact same things as we have in our database okay so instead of returning the entire profile object we're just returning the user from the database okay so now we have this user that's getting returned from the database so if i log in with twitter i should see the same thing i should see an id twitter id username and version same thing with github so now we're actually linked to a database and we are creating users if they don't exist and if they do exist we're fetching users and storing them into our session so this is a way to connect passport to a database and use oauth to interact with this database create users and grab them if they exist so a lot of complexity going on in this fairly simple code so now that that's done we can move on to the next step alright so the very last thing i want to do is i want to fix some of the interfaces here so what i'm going to do is i'm going to go to where my types file is and i'm going to make an interface for what the mongodb user looks like like so among the db user i'm gonna make that an er have and i'll make that have an i in front for interface so mongodb is just a tad different from the interface up here if we actually look at what the mongodb object looks like we're going to see that we have this id property and then we have a v for version so what i'm going to do is implement that here so i'm going to say underscore underscore v is going to be a type of number and then the object id is going to be a string okay so we'll do this underscore id oops and this is going to be a type of string so when we have a mongodb user it's going to look a bit different and so now let's plug this in so every time we're running the fine operation the document we're going to get back is going to be this mongodb user okay we can also write an interface for the profile we get back from google but i just don't think it's necessary for the sake of this video the next thing i'm going to do is add underscores for the parameters i'm not using and it looks like i actually have to put a type to those i'm going to do the same thing up here so this is going to be a mongodb user when we serialize the user we're going to be getting a mongodb user i'm going to paste this here and paste that there so that we're not using the first two parameters because i believe those are for jwt or something but we're using the profile and the callback this is going to be a mongodb user and then what i want to return to the client over here and the deserialized user is you might have noticed that we don't actually need this interface because we're not using it in our application but if we wanted to we can implement this interface and we can remove these values and only send the client this information because that's all they need but for the sake of this video i'm just going to keep the interface for the mongodb user so all of this is going to be what a mongodb user looks like and we're going to be using this interface multiple times throughout our project so now that that's done we have a back-end system that's written in typescript and all we can really do from this point is separate things with the router and to put these into different pages but i don't think that that's necessary because i just want to keep this as short as possible and make it as simple as i can and there's really no complexity in adding things to other files i think you can do it if you prefer that so we're going to remove this type up here and now everything should be good to go and it looks like i forgot one last time so this is going to be in mongodb user so now we should be good to move on alright so now after the new implementation we just added if i go to the login and i log in with any of the auth providers what's going to happen is you're going to see that the details come back in this assortment that looks exactly like our mongodb database we have the google id username version and id so what i'm going to want to do now is implement a logout functionality and this is going to be incredibly simple we're just going to pretty much get an li i'm going to make it say log out and we'll add an on click event listener we're going to say on click we want to run a function called logout and now what logout's going to do is it's just going to post to this endpoint actually logout is going to be a get request we're going to want to make a get request to localhost 4000 which is where our backend is currently located and we're going to do dash auth slash logout this is going to return a promise so we can put a dot then and we'll have a res okay so then we'll make an if condition we'll say if the response.data so if there's a response back that has data on it we're going to say res or actually i'm going to say window.location.href equals homepage so on log out if it's successful just assuming there's some data that comes back which is very poor um of a statement to make uh but it's going to work then we just want to redirect to the home page so now inside of the index what i'm going to do is just make my logout endpoint and inside of this endpoint i'm going to say if there's a request.user present on the request i'm going to do request.logout and then i'll send success back so that's all i'm going to need and now i'm going to be able to log out so that's a super easy functionality we're just going to run the logout method on the request that's been added by passport and that will delete us from the session and we'll be good to go and so the next thing i want to do is i want to add it so that it says welcome back and then the person's username so what i'm going to do in this case is i'm going to say let's get the context so i'll say const context equals we'll run the use context hook and we'll pass in the context we made and we can do this in a numerous amount of ways but i'm just going to decide to say here's a variable set it to you know the context and we'll say welcome back and i'll put context.username now what we're going to see is that the property username does not exist so what we need to do is we need to define contexts type so what i need to do is make a new folder for types so inside of the src i'm going to make a folder called types then i'm going to make a new file called maintypes.ts whatever you want to call it now i'm going to make an interface for what the user looks like and the surprise here is that the user looks exactly like the database does so i'll just call this i user and i user looks exactly like this if we go to our types here we can literally just copy over what a mongodb user looks like and just paste it in and change the name now all we have to do is come back in here and we can assert the type and say that the type is i user and that's going to run perfectly and now let's just make it an if condition so we'll say if the context exists oops we need curly brackets we'll say if context exists then we will render out this h1 here if it doesn't then we'll render out welcome to my website so if a person is logged in it's going to say welcome back with their name and if they're not logged in it's going to say welcome to my website so now this should work perfectly and let me see i'll just make this uppercase and an accident i made over in the navbar.tsx file is that in the get request we're going to need to include the options parameter and occupy it with the key with credentials and a value of true so that the express server can access my cookies and see which user and which session id to actually log out so that's fixed now and as well when we're logging a person out right here it looks like if there's a response then we just go ahead and redirect them i don't want to do that so let's go into the back end and where it says app.get log out we're going to log them out and then we'll send them back done so then on the front end we'll say if the response.data is equal to done then we'll redirect them home as well this response should have a type of axios response so just go ahead and copy this over to the code and to make this consistent because we use auth every time we're handling authentication on the endpoint i'm going to say that the endpoint is slash auth slash logout so now if we view this in the browser we're going to see welcome to my website and then if we log in with one of the auth providers we're gonna see welcome back and then the name of the person so now let's move on to actually rendering the pages conditionally so that the logout doesn't appear unless a user is logged in and the login only appears if a user isn't logged in alright so to conditionally render out this navigation bar what we're going to say is we're going to say if the user is logged in then we don't want to display this anymore we want to display this though and if he's logged out we can display this but we don't want to display that so what we're going to do is we're going to get the context and again we can pass it via props okay but i don't necessarily want to do that because i enjoy actually writing out the context just for the sake of showing you guys it so again we'll run the use context hook and we'll pass in the context and because it's nested inside of this context element then we're going to be able to access it so this user object is going to contain a user if it if he exists again i'll run type assertion so that it doesn't complain that it's empty and what we're going to do is we're going to say on the login page if well we first need the curly braces we'll say user object we'll say if there's a user object then we don't want to display anything but if there isn't we want to display this and what's interesting is that we can put anything we want to conditionally render in this so we'll say if there is a user object we want to display this okay and so this looks pretty ugly so let me format it something like that i guess that's easy to read so if there's a user object we want to show the log out button but if there's no user object we want to display the login button so this should be good now let's clear out some of this white space here and let's check it out so as you can see because i'm not logged in i have the login button so now if i do log in with google i'm going to be able to log in and you see the login button disappears but there's a log out so this is exactly what we want the last thing we want to do is make it so that we can't do this and access the login page so we don't want to render the actual login page if a user is not logged in so we need pretty much the same logic but we need to put it on the react router so over here we need to say user object if it exists then we will display oh i'm sorry then we'll display nothing but if it doesn't exist then we'll display the login route so now if a user is already logged in he can't access the login page so let's check it out so now if we try and go to login it doesn't exist as you can see it's kind of bugging out but this will be fine for now so now that that's finished we want to try and put this into production environments and host this somewhere so that we have this production application and everything works in a production environment so we have a dilemma here we wrote all of our routes let me see we wrote all of our http requests with the hard-coded backend url as you can see here so we're gonna have to modify this url so what we're gonna do is actually host the back-end first so i'll put this up online and then we have to go to all of our oauth providers and we have to modify the callback url and so that's going to be a pain but we can do it so let's go ahead and let's start hosting the back end first alright so the very last thing i'm going to do is i'm going to change this callback url so that it doesn't actually have a definite callback it just goes from its current address but to slash auth twitter so i don't want to specify the url is what i'm trying to say so that that way it'll work across different platforms okay so that's going to fix it what i'm going to do now is i'm going to put this into a git repository so we can actually host this on heroku so you're going to need to create a new file and title it dot gitignore and then just add the files we want to ignore which in this case is going to be everything in the node modules and our env file once that's done we can go to github and create a new repository i'll call my repository oauth video and it'll be public and i'll press create now it's going to give us a bunch of commands that we should run so what i'm going to do is i'll just go ahead and go back into our back-ends and i'm going to get admit i'll do git add and then add a dot for everything and i'll say git commit dash m and i'll say first commit once that's done we can say git add origin and we can specify the origin like so and then we can push to that origin main branch okay and i'm gonna need to enter a little bit weirder of a push command because i've already done this but you should be fine just entering git push origin main to push to your branch so follow the steps here and so that we can add all of our code to the repository so if you go ahead and refresh you you should see all of your code has been put up here in fact we don't even need to upload the build slash dist so i would even delete this if i was pushing it and i really and i really cared about it so now that that's finished let's make a new heroku app so go ahead and log into heroku or create an account and i'll make an application called oauth video backend so let's press create app and now we're able to deploy to the application using the heroku cli or we can just connect to github which i'm going to do so it wants us to specify a repository connect to connect to so let's connect to the repository we just made all right and so now what i'm going to do is fill up the environment variables so our environment variables can be found in the settings and then config vars so what i'm going to do is just add all of my configuration variables that i've created over here and there's a lot of them so this might take a minute all right so at the end of adding the configuration variables it should be the exact same as you have in your file here so i just grabbed the values and i pasted them here with their um key name right here so all of the environment variables have been added so what i forgot to add is in the scripts tag we're going to want to specify the heroku pre-build and the reason for this is is because before heroku actually builds and executes his build script we want to install all of the packages so i'll run yarn install here and then once a roku pre-build is finished executing then we can actually convert our typescript to javascript and then run the start command and now something i forgot to add was the tsc compiler so what i'm going to do is i'm going to say yarn add tsc i'll do dash dash global or the big g flag so this is going to install the tsc compiler and then we can just add it to github so we'll commit and then we'll push and now because we have a conflicting problem in the ts config i want you to go ahead and add the skip lib check and what that's going to do is it'll skip through the libraries when we're running the compiler so let's also commit that so i'll do git add commit and i will do skip lib check now let's push and so now we should be able to deploy with heroku and the very last thing we need to do is we need to have the app listen on the environment variable port so we'll say app.listen and i'm going to say process.env.port or 4000 because in production they're going to give us a different port and so we want to listen on that port instead of the one we specified so now let's go ahead and add this and commit okay and we'll push that to github and we will deploy with uh heroku now so now once you press the deploy button it will go ahead and install everything with the heroku pre-build and then once it's done installing everything it'll run the tsc compiler and it'll build our javascript files from our typescript so now that that's done it'll go ahead and run the yarn start and it's going to open the javascript file that it just built out for us so now if we open the application it's going to show us the hello world so now that that's done we can connect our react application to this endpoint and we need to change our authentication providers to say listen for a callback on this url all right so what we want to do is we want to go to our auth providers which we have google twitter and github and we want to go to that page where we're specifying our oauth application and we want to change the url to be this new endpoint that we've just created and we want to specify that we want this new endpoint that we've just created with heroku to be the new url so what we're going to need to do is over in github i'm going to change from localhost 4000 to be this new url now check it out i'm going to keep this https alright hyper text transport protocol secure and the reason why is because cookies don't like to be passed when it's not https you will run into all kinds of issues all right just trust me you want this to be https so make sure to paste that in then off slash github slash callback is going to be the callback url now let's go and do the exact same thing with twitter so in twitter we got the callback urls here let's go ahead and let's our endpoint up in there so we got this new endpoint looking good and that's all we need for twitter twitter is surprisingly very simple um and then on google we're gonna add another uri and we'll do this endpoint we'll do this end point here and then for the authorized redirect we'll do the endpoint slash slash google slash callback and now again i'm giving you a massive heads up that the https is absolutely essential when you're working with this um i'm sure you can do an http uh but that would really go against what we're about to get into in a little bit so let's go ahead and save and save and save update application twitter i guess saves automatically and let's move on so back into react let's go ahead and let's open up our pages and let's just change our endpoints all right and so here is the url that we currently have localhost 4000 we're going to want to modify that so let's take the backend url and just literally paste it in here now check this out it actually has to be https this time it's the first time it's needed to be secure and there's a really solid reason for that and it can cause a lot of people to trip up and mess up and take forever with passport but we have to keep it https and i will explain why in a minute so let's make sure all of the urls that we change to for the back end are https so in the context this is our last endpoint so the cookies can't actually work unless it's https your application will not run unless you do this https so very very important step ensure that this is your endpoint but everything we've done so far hasn't required https this is our first time we're using it all right so if we actually practice what we've done so far and we go ahead and try uh what's gonna happen is pretty interesting so let's go ahead and press login with google and we're going to get error 400 redirect uri mismatch and so then it's going to say the redirect uri and the request does not match the one and look at this this guy is not using https so what's going on here is that the cookie uh is in charge of this url a little bit uh and right now it's choosing http why isn't it going to https so to actually make this work what we need to do is modify some of the settings in our back end so we actually go to the backend index.ts see where it says app.use and then we're passing the session right here we need to create a new entry for cookie okay and we're going to configure the cookie so we get some properties to add to it like same site set this to none because we're not on the same site we're using a different site so the cookie needs to effectively transfer from our website to the front end so make sure that's set to none we got uh secure which is in charge of the https protocol so we'll do true and if we hover over it we can even read some information and so it says if uh secure true is a recommended option however requires an https enabled website our backend is https because we're using heroku and it comes automatically so ie https is necessary for secure cookies if secure is set and you access your access your site over http the cookie will not be set so this has to be true then we get a max age property all set and this one is going to be in milliseconds so we need to do is i'll do 1000 milliseconds times 60 seconds times 60 minutes times 24 so this is one day and i'll make it one week okay so now that that's done we have one more step that's just as important and that's that we're gonna run app.set so app.set trustproxy21 which means true so if this is set and you set your cookie like this everything's going to work phenomenally so let's push the code get add git commit update for https part 2 and then i will oh i forgot to save the file my bad and then let's push it to the origin main and inside of my heroku app i have the auto deploy on so if you actually look it says on my on my app inside of the deploy tab i have the automatic deploy set to true but if i wanted to just manually deploy it i'd press the deploy branch but i have automatic deploys on for every push to the main branch so if i check the activity we should see the build has started so it's compiling into javascript the build has succeeded and it's been released so let's open it and let's wait for the home page to load which will tell us that the app is actually online all right so now that it's up we can go ahead and try and access this from the front end all right so now we've switched all of our endpoints to use https and then the new endpoint and we got the same deal going on here okay and then on the nav bar i went ahead and switched this over to the new endpoint https new endpoint slash auth logout at this current step everything should work perfectly so if we log in we're gonna be able to choose an auth provider in this case google and it's going to log us in except we are using this other endpoint now the hosted endpoint the production endpoint and if we go to the network tab you'll see the get user is a request getting called on this endpoint now so if we want to emulate simulate whatever a different person accessing this endpoint besides ourselves let's just open a new browser in this case i have firefox open and if i refresh you see hey this is an empty user no one is logged into my website which is perfect so the front end shows we have someone logged in for the chrome browser and on mozilla no one is logged in so we're simulating a different user by opening a new browser if we go to login and let's go ahead and let's log in with a different auth provider in this case i'll choose github we're going to see welcome back and then a completely separate name and i just logged in with someone else's github not my own um and so you'll see we have two different sessions of users so it looks like everything is working perfectly and we can go on to actually hosting the front end and then moving that around so that the front end is in a production environment as well all right so hosting the frontend is super super easy so that's going to be this client folder here so what we're going to use to host the frontend is a service called netlify and it's free and i prefer it over heroku i think netlify is a significantly better platform for front-end builds so what's going to happen is react is going to build us a production folder and then it's going to run and open the production folder it's super simple so i don't know if you've ever hosted a front-end application before um but it's really not a difficult process so on netlife we're gonna need to go to the team overview whatever go to sites and then do a new site from git and then it says connect to a git provider and what happens is you need to go to github and make a new repository so i'm going to do oauth video front and like that okay and this is going to be public whatever doesn't matter and then press create repository and then once that's done let's go to our front end and let's go ahead and run the commands to push to this new repository so i'm going to run get in it get uh i'll run git add and then i'll put a dot for everything and then i'll run git commit dash m first commit so it went create mode uploaded all of this cool and then we'll do uh git branch dash main i'm not going to forget it this time and then we're going to add the remote origin so get remote add origin and then the name of the git repository and then we'll just push so we'll say get push upstream origin main and so that'll push all of our folder uh all of our files to github so if we refresh looks wonderful so let's go ahead and click on github here and then i'm going to click on my repository as being the oauth video front-end which i've uploaded so it's going to be deploying from the main branch build command is yarn build and the publish directory is build slash perfect so all we got to do is press deploy and this will deploy everything for us and we should have a ui posted at this end point that we're gonna get all right so this will build everything out and as you can see it's run the build command where is it right here and now it's going to create an optimized production build so then that's going to finish and everything should work so now we can press preview and there we go our react app is now hosted on an actual website cool so um if we go to this page our react app is now on this url if you have any problems doing it try and do it one more time because like the first time i did this it was kind of sketchy but just do it again if you have any problems and um you shouldn't have any issues with what we just did as you if your github site is hosted uh there's absolutely no issues you should run into so now that that's finished we're going to need to modify the back end so that the back end is connected to this url and redirects to it once a authentication is successful so let's go ahead and modify the back end so go ahead and open up your index.ts file and once we're in here all we have to do is just change the endpoints of the front end to the new endpoint so this react app so right here on the course origin i'm gonna have to modify this and change it to the new url there's a way so that you can use both urls by setting up some middleware but i'm not going to worry about that right now let's just put the production url as the origin and anytime we call localhost 3000 uh we're going to want to put this new endpoint instead and we'll put the full endpoint with https as well because netlify comes with https already it sets us up with it okay so now that that is done we'll commit our changes by git add commit for production ui cool and i forgot to save the file so let me redo that and then i'll push cool so now the back end is going to redeploy and the front-end is going to be able to connect to it successfully so because the back-end automatically redeploys i'm going to be able to go into the activity and see that it deployed just a few minutes ago so everything should work on the front end so let's try it out we'll go to login on our production frontend we'll pick an auth provider in this case google and we are logged in and if you check the request um oh shoot let's log out and redo it so if you actually check the request we are picking the https endpoint of our backend which is sick so this is going to work for any user who comes to your website they can log in and everything's in production and the beauty is that any push to the main branch which is the um the main branch of your github any push is going to redeploy on heroku on the back end because all we have to do is just check the box and it's going to redeploy every push so i have the automatic deploy set up onto my front end so if i just publish any new changes it's going to redeploy and the production endpoint will get all the updates so we have some continuous integration built in so this is a very awesome project for getting used to actually working with passport and putting it into a production environment and kind of going around the difficulties of that so that is pretty much everything i know the ui isn't very gorgeous i know that everything could have been a little more styled but this is a big deal this is a difficult tricky task to implement authentication with different auth providers and i wasn't able to find any youtube videos actually describing this and teaching this so if you saw a benefit from this video if this showed you something and you learned something new from it please like the video and subscribe for future content and drop a comment on the next thing that you would like me to make any sort of tutorial for because i'm open to creating tutorials for anything i work with a ton of different programming languages if you want an introduction to go rust anything um just let me know but yeah this is it we can use all of our different auth providers twitter github google and uh yeah so thanks so much for watching and uh have a great rest of your day
Info
Channel: Nathaniel Woodbury
Views: 7,360
Rating: 5 out of 5
Keywords:
Id: cD17CYA1dck
Channel Id: undefined
Length: 138min 27sec (8307 seconds)
Published: Tue Jan 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.