How to create Private Routes and Authentication with React Router V6

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
foreign hey guys if you are building something in react then there's a good chance you're going to need to use authentication to manage what users can and can't see so in this tutorial we're going to walk through how you can create an authentication wrapper and how you can keep some of your routes private so what we're going to build is a simple website that has a home page and a page a login page where we can log in hit enter and then we have access to these private routes which show us some basic details so before we get started I'm just going to talk you through what we're going to cover first of all we're going to create an authentication wrapper for our app which will allow us to manage in a stateful item whether a user is logged in or not we're then going to add functions for logging in and logging out so that we can control that Authentication then we're going to create a login page we're going to add some private components that we only want logged in users to see then we're going to add those roots and menu options to our app and then finally we're going to walk through and test the application and make sure that you fully understand what's going on so that you can build one exactly the same now I am assuming that you're familiar with reacting creating components I'm also going to assume that you've taken advantage of the use State use reducer Hooks and use context Hooks and that you know how to use react router if you don't check out the rest of the videos on my channel because I cover up most of these items there if you're semi-familiar then you should be good to go because I will walk you through how we create each part of this app so what we've got is a starting point is a very basic app that's using react router so we have the browser router component here we're rendering a header a menu and Our Roots which is what we can see on the front end that's our header our menu and then depending on the path which route we're showing and at the moment everything's public um the render header is very basic the render uh page is just pulling at the moment the about page and the home page component so again very straightforward the rendered navigation is a little more complicated because this is going to make our authentication job much easier so I have a navigation object which is pulling through an array of objects that give us the path the name for the menu the element for react router and I'm saying is menu true or false and that's just going to mean that we can use this one array of objects to manage the menu and The Roots on the basis that some of our routes won't need menu options for example log out and then we have our render navigation component and this is pulling through those nav items and we have two components one is to render the roots for our app so again we're just looping through and generating The Roots dynamically and then we have render menu where we're checking that the object in navigation if I just flick back is menu is true and if it is it's outputting a menu item and I've preset a lot of the CSS Styles in here but I'm sure you'll have no problem generating your own so the first thing we want to do is to start at the top level and generate a wrapper for our app and we'll call it the auth wrapper that's going to hold all of our components and decide what the user can and cannot see so what we'll do is we'll go ahead and just create a new directory and we'll call it auth and inside of there we'll create a new file and we'll call it auth wrapper .js now for this auth wrapper we're going to take advantage of the use context hook which is going to mean that we have access to that context through our whole app to check if the user's logged in or authenticated and any user details we want to store in that stateful item so we will start off by saying const context equals create context so we're going to automatically pull through the create context hook and then we're going to export const auth data equals use context and then we're going to use the auth context that we've just created there we go uh sorry fat Arrow there we go so we're using the create context we're creating auth data and that's going to use the auth context that we've created above now we can go ahead and Export this as a component so we're going to call it auth wrapper fat Arrow and then we're going to create a stateful item to hold the details of our user and we'll do all of this in one item so we'll do user and set user equals use state import that in and we'll set the defaults of the name to blank and the is authenticated to false for now so within the stateful item we're going to manage whether that user is logged in or not we're not storing the name at the moment but we are presetting that the authentication is currently false and if we go down to the bottom and we'll just do the return for the moment or context dot provider so now we're giving we're providing this auth Tech auth context to anything that's within and we're going to say the value equals and we'll pass through the user there we go and then the next thing we want to do inside of this return is to pour through the components that we've currently got in our app so we've got render header we've got render render menu and we've got render roots there we go just hit save on that and now we should be able to go back to our app remove these child components and Import in our auth wrapper there we go so our app now is simply presetting the browser router so that we can take advantage of the routes inside and we're outputting our auth wrapper and the auth wrapper is providing the auth context we created at the top through to any child components of auth wrapper and you could stick anything you want in here in fact you could create one component that encapsulates the head of the menu and The Roots if you really wanted to the other things that we're going to want to export from this context are a couple of functions the first one being to log the user in so if we Define the function for login and logging is going to take a username and a password that we send through as arguments and then we will return a promise resolve or reject and we can say for now if the password is equal to and we're just going to hard code the password for now then set user and we'll say that is the name is the username and is authenticated true so we're simply saying that if the password that's passed through is equal to password then set the user as the name of username and is authenticated true and then we'll just need to resolve that with and we'll just say success there we go and then we could else so if the password is not correct then we will reject it and we'll reject it with a message of incorrect password for that so that's our login function and we'll need one more function for to log out and we won't need to pass any arguments to that and we can simply say set user name is back to nothing and is authenticated false so we've got our login function again taking a username and the password checking that the password is correct and this is really where you would want to hit an API to pull the user details to check once you've pulled that back and checked if everything's right resolved with success if there's anything wrong reject it with whatever the message should be so we're saying incorrect password it could be incorrect username Etc the final thing we'll want to do to make these login and logout functions available through everything inside of our context is to export them so we're going to export login and we're going to export logout and that's it for our authentication wrapper the next step is to create the login page so that we can control users trying to log into the system so within Pages we'll create a new file called login and we'll get started creating this page so export const login and let's go ahead and set the jsx for this to start with so we're going to return um just taking advantage of the CSS I've already created we'll have an H2 of login page and then we'll have some inputs inputs okay so within here we're going to have a div with a class name of input and then we can Define our first input field so we have input um type equals text and we'll copy that down and we'll have an input for our password there we go and then we'll need a button so if this button and we can define a button with the text of login okay so there's our basic jsx in fact what we could go ahead and do we'll do the error actually let's pop in a div class name of error and we can pop an error message in there when we're ready so this login function is going to need a state to manage the form data so we'll say const form data set form data equals use state so we can handle our input values there in fact let's use use reducer because we're going to be storing multiple items in the state so use reducer is going to be a bit more helpful to us and we'll pass the function in directly and we'll set the default items to be username there's nothing and password is nothing there we go and then our function will take in the form data and the new item and then we'll set it in here the form data overridden by the new item so we can simply go ahead now and say that the value of this input field is form data dot username and on change equals uh set form data and we'll pass through the username equals e dot Target Dot ID I'm not passing e through so pass e through there we go and then we should set the ID here of username I should put e.target.value sorry and then we'll simply just copy that down to the password set an ID of password the form data value is password and we're updating the password and we want a type of password there we go so that's our state and our input Fields handled now once we click this login button we're going to want to run the login function from our auth wrapper so we should go ahead and import that in so we'll input the login function equals auth data so that's now given us access to this login function that we created that needs a username and password set but we'll Define our own function here um of do login there we go and that means that we can now set the on click of our button uh there to on click equals do login and then when we do log in we are going to await so we should make this function synchronous await login and we will pass it the forumdata dot username and the form data Dot password and then after logging in we will want to navigate so we're going to set const navigate equals use navigate and that's if you don't already know pulling through from react router Dom which is going to allow us to navigate the user to a different location and we'll want to navigate them to the forward slash account page which we haven't created yet but this is going to let the user see their account based on their username and password now we probably should wrap this in a try catch block just in case we don't have the right password because we'll get a rejection from that promise we created so we can say catch um we'll set an error object in the state so error message and set error message and we'll set it to nothing for now but if we get a rejection from that promise on the login function here of incorrect password we can say set error message and we can set that to whatever error was passed back so with that error message set we can now wrap our error div with if there is an error message then show the error message else no so if we get an error back the error message is going to be displayed on the screen and so we should output the error message inside of that div like set and that's it for our login page so just to recap we're setting a state for uh we're using use reducer to set the form data State based on the input values of the form we're logging an error message if I login function which we're importing from our auth data context either is a success or a reject if it's successful it's navigating to the account page if it's rejected it's setting the error message and displaying it on the page so with that now done let's go and add this login page to our navigation so we can simply add a new item in here that says path and we'll say forward slash login name um is login and we can say the element is the login page and is menu true so we will want to missing a comma there so we will want to show this another one just tidy that up so we're now defining a login page that's going to Output to the menu because we've said this is true and show the login component when we're on forward slash login so with all that done we should now be able to go ahead and test this form on the page so if we flick back to the page itself you can see we now have our login menu option so we've got home about and login and the login page is if I flick back displaying this forum that we've created in the login component so we could type anything random in um just type some random text and hit login which doesn't equal password therefore it's wrong it's rejected it's it's sends us back an error message of incorrect password we set that in the state and we're displaying that if instead I type password and hit login it's going to redirect us to the forward slash account page so let's go ahead and create a component for our account page now we'll do this in the pages section so I'll create a new file uh called account.js and we'll go ahead and Define our function here so um export const account equals and then this would be very simple we'll need access to the user's information so if I pop back to the auth wrapper remember that we're exporting into the context the user from the state and the login and logout functions so on our account page we can pull through the user auth data there we go and then we can return div with the class name of page and we can say your account and we can pop in here uh what should we do we'll pop in there account name for example and we could just simply pull the user dot name and that again is going to pull the stateful item of user that we're passing through and allow us to display the user's name so if we hit save on that the final thing we'll need to do before we can make access or have access to this account component is to add it to our navigation so we'll now go ahead and say if we land on forward slash account and a menu item name of account show the elements of account and is menu true and what we'll actually do here is we'll need to set another item on these objects which is is private and we'll say that the for the account it is private and we could say is private false just to make sure everything's tided up um it's private false so these are all publicly accessible routes is private false so we've got the home page the about page and the login page are set to false for is private and we've got the account object as true for is private because we only want people that are authenticated logging in so again we're going to hit save and we'll just check where we are with the app so far now you'll notice that at the moment if I refresh the page will be logged out we've got the account showing and if we click it it's not showing any account name because although we've set the page to be private we're not handling that when we're outputting the menu items or the roots um but just to show you what's happening now if we set the username to John and set password and hit login it's an account name John so the actual authentication process is working perfectly it's taking our username and password matching the password is equal to password logging Us in setting the name and authenticator is true and on the account page it's showing us our username but we now need to make sure that any of these private routes aren't shown in the menu or accessible unless we're authenticated so if we flick back to the app the way we're going to do this is we're going to go to the render navigation component which handles both our routes and our news and we're going to add some conditioning to make sure that the root isn't defined if the user isn't logged in so there's absolutely no chance of them getting access to it so the first thing will be to pull in the user's information and status into the render Roots component and then so inside of our return we're going to map through the navigation items and just cut this out for a moment there we go and we're going to say if the root dot is private and the user.is or then authenticated then we can return the route else if the it's private so if the route is not private then we can return the route else return I'll say return true just to make sure we don't get any uh warnings so that's going to make sure that if the route is private that the user must be authenticated in order to show this route and if the root is public I.E is not private or is private is set to false then that's fine you could display the route well now we need to do the same with the render menu so on the render menu we're going to want to pull through the user and the log out functions and we'll pull through all Theta so there we go and just to speed things up I'm going to paste the code I've already got written and walk you through What's Happening Here so again we're mapping through the nav items and we're saying if the Root's not private and it is a menu remembering that from the navigation we're saying whether it's a menu item or not and we'll come back to that in a second then output the menu item and just pull through got a small component here to Output the menu item there we go which is just returning the div with the link um are we pulling through the link yes we are in the router Dom um else if the user is authenticated and it's a menu item then show that menu item else return false and then finally we're saying if the user is authenticated then show a log out button which is going to run a logout function which we're pulling through from our con use context our all data context component else if the user is not logged in show them the login link so now that we're showing the login link manually if the user is not logged in we can go ahead in our navigation component and say on the login is menu false and the reason we're doing that is that we'd only want to show the login page or the login menu option if the user is not logged in if they're already logged in we don't need to show them that option in fact we want to show them the log out option and that's exactly what we're doing here We're looping through all of the navigation items and setting a menu item if it's is menu true login uh has is menu false so we're not going to show that here but we're going to manually show that menu item if depending on whether the user is logged in or not so we can go ahead and save that finally just to show this working we'll go ahead and create one more uh page and we'll call it private.js and this is how you could then go ahead and add any other private routes so we'll say export const private and we'll simply return page name equals page with an H2 text of private page and a paragraph of this is a members area page so now we have this new private component the final thing to do is to copy the account object and we can say forward slash private the menu item name is private the component is private we'll then put that in is menu true is private true and hit save now I'm getting a few warnings down here because we've removed some components around so I'm just going to quickly tidy up these warning messages there we go and now we should be able to go ahead and walk through the front end of this application and check everything's working so if we flick back we've got the home page the about page the login page we can pop in the username of John and the password of password hit login which takes us to forward slash account and we can see the your account page and the account name of John we've now because we're authenticated got both the account menu option that we're on and the private menu option if we click that private page this is a members area page because if you remember we set in the navigation that this was a private page and we have our log out button because we're our logout menu option because in our render navigation we've got if they're authenticated to them the log out and if they're not show them the login and the log out is the the on click for that menu option is to log out which is the function we're pulling through from our auth data and if we pop back to that the logout function in the auth data or the auth wrapper is simply setting the username back to nothing and is authenticated false you'll notice there for if we hit the logout button we'll no longer have access to this private page and so nothing is shown if we try and manually go to forward slash account again nothing is shown because we're not authenticated So in theory the final thing for you to do would be to go into your auth wrapper and replace this login function with something that calls your API to pull the user's data so that you can check the password against live data from your database now if you're looking for a great way to be able to um create and generate hashed passwords and how to authenticate those hashed passwords for real live users then make sure you subscribe to this channel because the next video is going to cover a really great npm package called bcrypt or bcrypt JS which is the package that I use every time I want to handle usernames passwords and authenticating against hashed encrypted information I hope you've enjoyed this video if you have please smash the thumbs up button and if you want to see more tutorials like this make sure you subscribe to this channel foreign
Info
Channel: Kodie
Views: 10,002
Rating: undefined out of 5
Keywords: modern authentication, react authentication, react js app project, react router, react router 6.4, react router dom, react router v6, react routing, react routing tutorial, react routing v6, react tutorial
Id: irbrtSs8Dpg
Channel Id: undefined
Length: 31min 44sec (1904 seconds)
Published: Sat Oct 15 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.