GitHub Login With React (GitHub APIs, GitHub OAuth 2.0 Authentication)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on guys it's Cooper codes and in this video we are going to create this full GitHub login system this system allows you to authenticate users with GitHub and also allows you to make calls to the GitHub API such as like you know managing the repos and stuff like that for this video we're going to have a simple login with GitHub it will redirect you to a GitHub login screen that will authenticate you for a certain oauth application that we're going to create through GitHub so you can press authorize here then we're going to see that we get access to a token from the user that allows us to make actions on the user's behalf for example we can get data of a certain user for example I'm on the Cooper codes account right now and I can even go to the link to my profile and see my profile picture from GitHub alongside a bunch of other data so let's say you're like a social media application and you want to do a GitHub integration you could show a link to the profile on someone's social media page for example and would go to a link like this and as you guys will see it will link to my GitHub here let's get started by looking at a diagram of the system we are going to create in this video in this video we are going to create a a system which consists of the react front end a proxy server using Express that's going to then interact with the GitHub API proxy servers can be confusing one of the main reasons why we use a proxy server or an external server to manage our GitHub API requests is because GitHub API uses a client secret we do not want our client secret to be exposed on the front end and so if our front end makes a call to the proxy server for example and then the proxy server uses the client secret our front end never sees that client secret for example but it's also important to understand that our react project is going to hold our client ID you can kind of think about the client ID as a username and the client's secret as a password so the client ID is non-sensitive and it identifies our specific GitHub oauth project let's look at the path of how data flows when we authenticate a user so when the user logs in we want to get access to a token for a certain user on our front end we are going to get something called a code from that GitHub login screen with that code we can then get an access token from our proxy server we are then going to ask the GitHub API for a certain user's access token passing the client secret to the call that's why that's important there is it keeps everything secretive from the front end so they can't see our client secret GitHub is going to have something like slash authenticate user for example and this slash authenticate user grout is going to send data back to the proxy server which is then going to send that access token which we want our proxy server is then going to finally send that access token to our react front end and then we can do things with the GitHub API in this video we're only going to do a simple get the data for a certain user but we still get access to that access token which allows us to make calls to the GitHub API on the user's behalf hopefully this explanation was helpful in understanding this system now let's get building we can get started by initializing everything we need from the GitHub side of things so go to github.com and then log in with whatever account you want to own on the oauth application we can create an oauth application by clicking here in the top right and going to settings scrolling all the way down from settings and go to developer settings on the left here inside of developer settings we are going to then go to oauth apps inside of here we can register a new application we can name the application I'm just going to call it login with GitHub for the homepage URL I'm going to put in localhost 3000 this is where our react application is going to be hosted on and then for the Callback URL I'm also going and then for the Callback URL I'm also going to use localhost 3000. there's a three-step process to understand is that we press the login button and then we are going to go to the GitHub login page from the GitHub login page when the user gets logged in successfully it's going to send them to whatever this link right here is so if you want to do something else for example localhost 3000 success you can totally do that for this callback URL but for this video I'm just going to send them back to localhost 3000 for this video I'm not going to be working with Device flow so I'm not going to to enable that and we can register our application so you should be at a page that looks like this this means that we are good to go with the GitHub stuff when we need the client ID and client secret I'm going to run back over to this page then so make sure you keep this in the background let's get started by creating our react application let's get started by opening up an empty folder and then going to the terminal and creating a react application by saying npx create Dash react Dash app and then name of our application which I'm just going to call client we can go to the client folder by saying CD client so now we're in that react folder that we just created I'm going to do a somewhat controversial thing for this video but I'm going to provide an explanation as to why go to the source folder and then go to index.js just to make this tutorial more simple I'm going to remove react.strict mode one thing that happens with react strict mode is that it re-renders our application twice so why could this be an issue well the GitHub oauth gives us a code which can only be used once so here's what happens is we get the one time code and then on the first render we use the one-time code and we get an access token which is what we'd expect right on the second render we use the one-time code again the same exact code and we get an error from our server saying that that code has already been used to try and get an access token there are ways where you can pretty much do like an if else and try and get out of these errors but to make this tutorial nice and clean I'm just going to get rid of the react strict mode by removing it here it's important to also understand that react strict mode does not run in production it is something used specifically for development environments and so if we're developing and we are finding that it's causing us a lot of issues then we can make a kind of educated decision as to if we want that react strict mode to continue in our application so make sure that your router render just has the app inside of it and then we can head over to app.js so now we can get started by creating the initial Logic for logging in a user so let me explain in detail what's happening during the user login to log in a user with GitHub oauth we are going to forward the user to the GitHub login screen and GitHub knows it's for our specific client because when we forward the user we pass in the client ID so that's how they know it's us user is now on the GitHub side and logs in so they're on like you know github.com login whatever that might be and so when user decides to log in they get forwarded back to localhost 3000 because that's the link we told GitHub to redirect us back to there's a very important thing here localhost 3000 is going to have a variable attached to it that's going to look something like this code is equal to you know whatever the code's equal to from GitHub side and so when this code exists in our link that is when we know that a user has logged in because the only way we get that code is if GitHub redirects to localhost 3000 with this code attached to it and then we can use that code use the code to get the the access token but only allows us to get the access token and the code can only be used once it's really important that I fully explain this because as I do the forwarding and stuff like that I want to make sure that everyone's on the same page so let's go back to our GitHub application here and grab this client ID I'm going to save the client ID at the top of our application by saying const client underscore ID is equal to this and so a super easy way to forward a user we can kind of put the forwarding logic in one function I'm going to say log in with GitHub is to say window.location.assign this navigates to the given URL is Visual Studio this is telling us here and so we can then pass in a URL for the window to go to this is a URL that's defined by GitHub and it's going to be https github.com login slash oauth slash authorize then we can add in a parameter to the end of this by saying question mark client underscore ID is equal to and then we can add that client ID cons on the end and that's all we need to forward the user which is pretty nice GitHub handles all the logic for us pretty much so let's go to this returned code and get rid of everything except the header and that div I'm just going to keep the header here because it gives us a nice styling and we can make a button which is going to trigger this login with GitHub right here so we can say button log in with GitHub and if we want to call that react function we can say on click login with GitHub so when the user presses this button it's going to then assign their location to this login link so let's npm start our application and see what's going on Amazing so we get access to this login with GitHub button if we press it we're then going to be forwarded over here I can authorize my account by pressing this and you'll see when we get sent back I'm being sent back to localhost 3000 with a code parameter at the end of it so we can make some basic code to kind of see if this code parameter exists when our react application gets loaded so let's go do that we can go to the top of our application and we can import use effect from react one of the things use effect allows us to do is it allows us to run code once at the beginning of our application so we can Define the use effect Hook by saying use effect passing in the parameter for the use effect which is going to be nothing and then Define the Callback function by using an arrow and then braces for the logic of the function then at the end of the logic we can pass in a second parameter to use effect that's why we have the comma there and we're going to pass in an empty array we use an empty array here because you pretty much only want the use effect to run once it's a simple way of thinking about it and so if we want to see if this code exists kind of like here so I'm just going to bring this comment down right here because this is kind of what we're looking at is this we can get these string of our query by saying const query string is equal to window.location dot search so what's kind of in that search bar we can then get the URL parameter so for example code like this by saying const URL params is equal to new URL search params and we can pass in the query string here and so we actually get access to extra logic from URL search Paramus to make that whole process of grabbing those variables way easier so if we want to get the code parameter we can say const code param is equal to urlparams.get and we can say code we can console.log the code param here in order to see if we're actually getting this parameter out of our URL so let's go back to our localhost so we still have the same code from before and if we refresh our page you'll see that it's being logged in our console right here which is great news that means we can go and use this code to communicate with the GitHub API although this is where we are going to create our proxy server so we can use this code to get the access token and as I described in that initial diagram we are going to make a call to our proxy server which is then going to call the GitHub API so let's get started with developing our proxy server I'm going to create a split terminal so the terminal on the right is going to be for our server and make sure that this new terminal you create or you can use the same one if you want is outside of that client folder so we want to be on the outside right here and we can start by adding in a file called server.js and then in our terminal we can say npm init dash dash yes this is going to initialize a package.json for our server to use we are going to need a couple of packages for our server so we can start by saying npm install the first package is going to be body dash parser this allows us to parse data from the front end as it goes to the back end we are then going to need cores which is going to allow us to enable cores for our Express server so it can get requests from any origin so any anyone can request our server I'm also going to install X Express which is that library that allows us to make an Express web server with JavaScript and also no dash fetch so we can use fetch on our Express server so your package.json should look something like this just so you can see that and so let's go and do server.js and we can start by making two consts the first con is going to be our client to underscore ID which we can either grab from our front end or we can go back to the GitHub so I'm just going to do that so we can get the client ID by going here so copy your client ID bring it over to the server.js and we're also going to make a cons for the client secret because we are going to be using it when we call the GitHub API directly so go over here and press generate a new client secret it even warns you make sure to copy the secret now you won't be able to see it again but you can always generate a new one if you mess up but copy this right here bring it over here and so now we have the client ID and the client secret which is great news so now we can get started by defining all the different libraries that we're going to need for our Express server to work we can first save our R Express is equal to require Express this allows us to use the express web server we can also say VAR cores is equal to require cores rarely do I ever say this in a tutorial but the logic for grabbing fetch when you don't have access to import and you want to use require statement instead is very strange so just copy this for now const fetch is equal to dot dot dot args so you're using spread operator on the arguments here and then you're going to pretty much import node Dash Fetch and you can use a then here which again I wouldn't worry about understanding this logic it's not really helpful to understand and all we need is fetch working at the end of the day so I'm going to go point to an arrow which is going to call Fetch with dot dot args we have to do this weird logic because inside of our server.js we're not using Imports we're using require statements and so that's why this strange logic has to be introduced but I would say don't stress about understanding this then we're also going to import the body parser by saying VAR body parser is equal to require fire body Dash parser there we go we got all these required statements out of the way so now we can start with actually getting coding we can Define our Express server by saying VAR app is equal to express and then we can tell our Express server to use certain like middlewares for example by using app.use we can then tell our Express server to kind of use different ways to handle data for example app.use cores is a great example this allows requests to come from any origin and also app.use body parser.json this allows us to send data to our Express routes in a Json format and then we can start our server by saying app.listen on Port 4000 and we can do a little function logic here to call once this app.listen is successfully ran and we can say console.log cores server running on Port 4000 and so we can even npm start this just to see that everything's working at this point boom core server running on Port for a thousand so that is great news that means we have a server actually running locally that we can start to add more functionality to so we can start by initializing a get request which allows us to get an access token when you have a user's code for example so this thing is going to require that there is some type of code being passed from the front end and so we can make a get request be defined in express by saying app.get then the route we want to use I'm going to say slash get access token I'm going to make this in a synchronous function because we're using fetch in the back end here which is going to use the await statement we get access to the request and the response from Express so now here's where the actual authentication happens in our back end we are going to have some type of code that's coming from our request which is going to exist in the request.query object and I'm going to pass it in through the dot code so this app.get isn't going to work unless we have that code defined here we can now Define a fetch saving that's going to access GitHub directly we can say await Fetch and then the GitHub link for getting an access token from a certain user's code which you can say is https slash github.com login slash oauth slash access underscore token this fetch statement is going to require a bunch of parameters on top of this URL I'm going to Define parameters as a variable just so this fetch statement right here isn't like 100 characters long so you can say it's equal to the question mark which means we are going to start entering URL parameters and then we can say each parameter which the GitHub API request us to have the first one is the client underscore ID which we can set equal to the client ID const we made above right here just so you guys know where it's coming from plus and then and which means we're going to Define another variable next one's going to be client underscore secret is then going to be equal to client underscore secret like this and finally we are going to need to give the code as well to this request which you can say is and code is equal to the request query dot code which is something that our front end is giving to the request when we access the get access token here I'm also going to console.log therequest.query.code here so you guys can see the data kind of moving through our Express backend so we can add the parameters to the end of the string by saying plus params and then we can Define the logic of the certain fetch requests for example we want it to be a post request to the GitHub backend and we also want the headers to be of type accept application slash Json this allows us to get the access token back in a Json format and so the process is Json format when the fetch request is fully done we can say dot then take the response from the server so the GitHub server now and then say return response.json which turns it into a Json JavaScript can actually manipulate so we can say dot then data and this data here is just going to be the return statement of whatever is being passed in the previous dot then and to give the Json data back to our front end we can say res dot Json data because this res is what defines the response of our Express web server so the response is defined right here and so this is actually the full get access token logic if we also want to see this data in the console we can say console.log data right here this is just going to be nice because if you can see everything in this console right here for you know what's happening in the back end while we're in the back end I'm just going to fully Define our proxy server by creating the second get request that we're going to need which is going to be the get user data for get user data the access token is going to be passed in as an authorization header and so that's how we're able to access the access token from our backend so let's define the query here by saying app.get slash get user data again asynchronous because we are going to be calling the GitHub API here I'm going to get the request and the response as normal then Define the logic like this oh my bad Define it like that getting a header out of a request is different than getting a parameter for example with this query.code so if we want to get a certain header we are going to get it by saying request dot get and the name of the header so authorization for example so let's define our call to the GitHub API to grab the user data which we're going to find by saying await fetch then https slash api.github.com and make sure you get that API Dot and we can say slash user so this is some logic from the GitHub API that allows us to get information from a certain user by passing in their access token and so we can Define more things about this fetch by saying that the method we want to use is of get and then the headers here are going to be of authorization and GitHub wants our authorization headers to be in this very specific format where we say rec.get authorization like this and I think just to make something very clear this authorization header is being passed in as Bearer and then the access token here and so that's how most authorization headers are expected if they're of the bearer type is to be of say this Bearer first and then the access token afterwards so we're passing in that same Bearer access token at this line right here so once this fetch is done we can do the same exact thing where we're going to take the response of this Fetch and then return response.json so translated to a Json format we can then work with then say dot then grab the data and again I will console.log this data here so we can just see it in the console kind of learn from that similarly we're going to take the response set the Json to data like this so just to explain what this is doing one more time is we can call get user data from our front end and from that call we are going to pass in the authorization header which is going to be of Bearer access token it's going to look like that we're then going to fetch data from the user API route from GitHub once that data has been fetched we're going to translate it into a Json type we will then take that Json and then return it to the user by saying res.json data so make sure to go to your terminal and then restart your server just so it has all that New Logic inside of there so now we can go to our front end and work with the server so for this video I'm going to be using local storage to store the access tokens of our user I know there are security concerns when it comes to local storage so I'm going to say this I have a video on my channel talking about HTTP only cookies it's not an Express video It's actually an Apollo server video but if security is a super concern or you feel like you might be exposed to attacks where someone could grab your local storage you can also send HTTP only cookies from your server for example one reason why local storage is nice is because it allows us to persist to log in and so someone can leave our webpage for a while and then they can come back and still be logged in with GitHub and I've kind of been hesitant to make local storage videos because there are obvious security concerns with it but I think it's really cool to show in this video that someone can continuously be logged into our website for example it doesn't always make the most sense from a security perspective so I already see the comments coming but I think it's interesting to show the logic of how we can work with local storage for early least one video So within our local storage we are going to have an item that's going to be called access token and so we are going to Define some logic of we want to log in with so we want to get an access token under one very specific condition when our application loads and so that's why I'm over explaining this if statement if we have the code param which is that we have an actual parameter in our URL that is a code that means we probably just got redirected from GitHub right and importantly our local storage.getitem of access token is equal to null which means we do not have anything in our access token we then want to grab the access token from our backend so that's kind of the logic of this if statement here so if we have this code param and we also have no access token let's go and grab the access token using this code from the user because we are going to use an await statement to fetch our backend I'm going to make an asynchronous function defined right here called get access token and we are going to call the logic of the function so we might as well do it right now at the very end so this allows us to use the await keyword anywhere inside of here and so we can use await to fetch our back end so we can say weight fetch HTTP slash localhost 4000 slash for example get access token which is the route we just defined we can go back over to our server.js and C get access token here make sure we've installed it right there we go looks good and we can add a parameter to this request by saying question mark code is equal to we can add the value of the code param to the end of that this is how our server.js gets access to the request.queryparameters dot code that's how it gets accessed right there and then just to make sure I'm going to Define this fetch having the method of get even though I think that's the default it's still nice to 100 make sure my bad you don't want to close the fetch right here you want to grab that and then put it over here we can then go dot then so when this fetch is done we want to take the response to the Fetch and we want to return response.json we can then take that Json object that was created and we can work with it over here we can even go to our backend right now and look at the get access token what does the data return well if you go to the bottom it says res dot Json data data is going to be a block of data that's coming from the GitHub API that's going to have an access token property in it so we can console.log that data so let's just say we were totally unfamiliar with what it returns we can always look at our console to see the different data inside of there but we can see if data dot access underscore token so just to make sure in case there's like you know maybe github's having issues that day where they didn't put the access token in our data for example we can then save this access token that's provided to us from GitHub to our local storage by saying local storage dot set item then it's the name of the item so access token and then the value of the item which is going to be data.x access underscore token so an important react concept so if you guys are getting this far this is a cool little thing to learn about react setting our local storage does not force a re-render on react for example if you already set a state that would force a re-render we might want to show that a user is logged in or not logged in because of this new local storage.set item right so in this example I'm going to show an easy way to force a re-render in your application we can go to the top of our application and also import use state from react we can Define our state at the top of our application by saying const re-render and then set re-render is equal to a use state of false and so this is kind of a nice way to use State 2 force or re-render and so we can take this set re-render and we can just set it to the opposite value of whatever re-render currently is and so we can actually go and make sure to npm start our application here and check out this login logic so something important to understand is that when you press login with GitHub it's then going to cache whatever account you log in with initially if you want to get rid of this for example and you're testing you can revoke all user tokens over here if you just want to see the login screen again but just understand when you log in with GitHub and you're on a regular localhost 3000 it's going to then going to put the code in there and that's going to run all of our code like expected and so this is using fresh data it's just that GitHub is smart enough to remember your kind of session with who you are and so that's why that works and so we now have access to the access token inside of our local storage and so if you want to go to this menu you can inspect element go over to application and then that's how you see all your local storages you press over here and then you can see everything stored in your local storage so now we have the access token which is great news we can now make the functionality for first of all changing the UI just a little bit to show that the user is logged in and also calling the user data so let's get into that just to make things simple I'm then going to make the function for grabbing user data data under our use effect I'm going to say async function get user data and so we can make this function run on a button click for example which is what we're going to do and we're just going to do a simple await fetch just like before so it's going to call our back end by saying HTTP localhost 4000 slash get user data and then going to Define this as a method of get then the headers here are going to be of authorization so there you go because remember if we go to our server.js and we go to the get user data we're expecting that authorization header and we're expecting it to be in the format Bearer and then access token so we can even put a little comment here bear access token that's what we're expecting so we can put in the bearer string like this and then we can add the access token to the end of it by saying localstorage.get item access token we can then do another dot then statement as you guys will see very repetitive here we take the response and then we return that response into a response.json which we can then manipulate with JavaScript so we can grab that finalized data there and this is going to give the data of the entire user for now I'm just going to console.log the data like this so we can go and add in some logic to our front-end components here one of the first things we're going to do is make a little Turner statement where if local storage dot get item of access token if that exists we're then going to want to show a certain component which I'm just going to put a little racked fragment here then we can use a little colon to say else if it doesn't exist we want a different component to show for example we want this button to show in the not logged in so you can imagine this if else as logged in not logged in kind of like that and just to make things obvious we can even have a little H3 here saying user is not logged in just so we're super sure about what our application is doing so from here though we can do a little H1 that says we have the access token because we we can only get here if that access token exists locally and we can even create a little log out button and so you might think like logging out that sounds like some crazy thing going on well pretty much we are managing our login logout State pretty much just by having this access token here so we can call an on click function when we click the log out button to pretty much say all right Define some logic here where we say local storage dot remove item access token this is pretty much how we log out in our application is just saying no more access token means no more user no more user means they logged out it's the simplest way to think about it oh and make sure you spell access token right and again we are going to use that set re-render to force re-render application and I'm just going to use the opposite value of re-render like this again this is because when we mess with local storage we change the values around it does not force a re-render enter application so we kind of have to do something to force that like this and so amazing this button is going to clear our logos storage with the access token and then Force our react application to re-render which is great we can now we'll make a little H3 here which is going to say get data from the GitHub API I can even specialize and say get user data and we can make a little button that is going to allow us to say on click get user data which is that function we defined right here and so this get user data is going to return a huge block of data from our user and so you can imagine this block of data is going to look something like you know name Cooper codes date of birth okay I don't know if that's in there but it's like you know someday just a bunch of random information related to your user right and so if you want to save an object one thing we can do is create a use State and react to save this huge object so let's roll up to the top here and create a new state to handle that user data or that user object which is that large object of data that's relevant to the user that we're getting from the GitHub API then you can set the user data as well it's going to be equal to a use state of an empty object we can then set that state to this data object and if it wasn't clear enough data is going to be equal to something that looks like this so we can set our user data object to this data that we're receiving from our backend and this allows us to do something very cool if we have user data we want to show it to our front end one way of saying if an object has data inside of it is we can use the object object in JavaScript by saying object.keys user data and we want to see if it has keys to pretty much data inside the object that has a length that isn't equal to zero and we can even use another ternary statement where we can say if this is true show this react fragment so this is good practice with these else show this react fragment which I'm just going to make an empty fragment right here and so then inside of here we can even do things like say hey there user data Dot Login and so login is how you get like their login name for example you can get access to a bunch of different user data which I'm then going to add more here as we see what information we're getting back from a back end so let's make sure to save our app.js and go over to the front end so you guys will see if you're in the same boat as I we already have an access token that was stored in local storage from before so since we already have an access token we can actually grab user data from the GitHub API right now for example I logged in under an account called Cooper codes test and so if you go over to your console you should see this large block of data this is everything that the api.github.com users is returning to us so we can get the amount of followers we can get their bio if they have one their Avatar URL and so you can really make some cool stuff with this for example we can grab their Avatar URL to show that and we can also grab their you know HTML URL to their profile for example so let's go and add that to our front end so we can add in an image and I'm going to force the width to be 100 pixels and the height to be 100 pixels because GitHub actually gives you a decently high resolution image and we can say that source is equal to the user data so that state of all that user data we just saw on the console dot Avatar underscore URL and we can also do a link to their profile for example which we can say is equal to userdata dot HTML underscore URL and this link I'm going to make sure the style is of color white because links are initially like a weird purple color I'm just going to Define this as a link to the user profile or let's say GitHub profile so if we refresh our application go back to localhost you'll see we have access to the profile picture which is pretty cool and also a link to their profile so if we can hop over here and so one cool thing that you guys can see is that I can actually press the back button here and I'm still logged in under the same account boom so I'm still logged in right here and I'm still getting the user data which is pretty awesome I can even log out again for example and so if you go over to your uh application here and you see the ax token if you log out access token is going to go you can log in again it's going to pass in the code and boom you're going to get another fresh access token so this is a great example of the full authentication system working I know this is a lot of setup especially just for working with GitHub if you guys want to see me use other API routes with this access token or kind of discuss the GitHub API in more depth let me know for sure but I think this is a great starter project if you just want to initialize GitHub authentication within your applications hopefully this video was helpful and thanks so much for watching
Info
Channel: Cooper Codes
Views: 23,831
Rating: undefined out of 5
Keywords: react, github, github api, github login react, github oauth 2.0, github oauth, github oauth example, login with github tutorial, log in with github react, react login authentication github, react github, react github api, github oauth 2.0 example, authenticating with github api, github api javascript, github api login javascript, github login oauth, github tutorial
Id: rRn2EisxPl4
Channel Id: undefined
Length: 34min 49sec (2089 seconds)
Published: Sun Oct 09 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.