React Protected Routes | Role-Based Authorization | React Router v6

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
react router version 6 will let you create protected routes with role-based user permissions kevin is a user but he does not have editor or admin permissions he can log in and see the home page but he can't access anything else dave is an editor when he logs in he'll be able to view the editors page but after that he'll attempt to access the admin page and he'll be unauthorized to do so he can go to the lounge where admins and editors hang out and now we'll look at jane when jane logs in she's an admin but she'll try to access the editors page which is only for editors so she'll be unauthorized for that however she can access the admin page and she can also access the lounge where admins and editors hang out let's look at the react code that makes all of this work [Music] hello and welcome hi i'm dave today we're going to create protected routes with react router version 6. these protected routes will also have role-based user permissions this is more of an intermediate level react tutorial than it is beginner ideally you will have already completed my react.js for beginners course or a similar course for getting started with react and i have separate tutorials for the login and register forms you'll see today as well as the node backend we'll use for authentication i put links to all of those in the description and i'll share a link to the source code for this lesson too now you can see i've got visual studio code open to full screen here and we're looking at the dependencies in the package json now while most of these dependencies already existed for the register or the login page one we'll be adding today is react router dom version 6. you can see i've got version 6.2.1 as of this tutorial now we need to open a new terminal window you can do that from the terminal menu or press control back tick like i did and then i'm going to type npm i and then react dash router dom the at symbol and the number six and now you would press enter to install that i already have it installed but that will let you get started and then after it's installed come back to the tutorial i'm going to close the terminal window and we're going to look at the index js now in the index js we're going to import several things from react router so we'll start with browser router and then we also need routes and then the singular route all from react dash router dash dom and once we've imported those we're going to start with the browser router and so we put that right after react.strict mode and before the auth provider that we have in there that was used in our login tutorial that is from the context api and we are using context to provide a global off state with the auth provider after that we need to apply the routes so after the auth provider and we'll go ahead and surround the app component with routes but then we're not just going to have the app component here we need to have a route and set the path equal to the root plus an asterisk because we'll have routes nested inside of it so the only way those will match up with the root is to go ahead and have the slash and the asterisk instead of just the slash and then let's go ahead and put the element attribute and inside this element attribute is where we put our app component and once we've done that we just need to close the route component and we're finished with the index.js file now let's look at the app component in the app.js file and you can see i have imported a lot of components already most of these will just be to navigate between to show the different user-based permissions but overall we'll look at a few of those in more detail now inside the functional app component itself with the return you can see we left this where we had the login tutorial with the main element class name of app applied and the login component inside we're going to replace all of that with a layout component so let's look at this layout component we're importing outlet from react router dom and then inside the functional component itself we're returning what mostly looks like what we had inside of the app.js we have that main element class name set equal to app but now we have the outlet component inside the outlet component represents all the children of the layout component so anything nested inside the layout component is represented by the outlet and that allows you to apply more things to your overall app if you want to you could have a header component in here you could have a footer and of course we can use more than one outlet as we create routing inside of our application too this is a fairly basic example for this tutorial so we just have the one outlet and everything will be nested inside of this layout component so now that we know how the layout works with the outlet let's close it out and apply that here to our app.js component so we need to import a couple of things from react router we're going to import routes if i could type there we go and route a singular again and then that is going to come from react dash router dash dom and now that we have that let's go ahead and remove everything inside the return and we'll start with routes and then nested inside the routes we'll put our first route and that's going to be a path equal to the root which is a slash then we'll set the element equal to that layout component that we just looked at once we have that we just want to put the greater than symbol to close the route and get a closing route tag because now we'll be able to nest other components inside of this layout route that is attached to our root path i'm going to scroll for some more room here and then i'm just going to paste in the other components and we'll discuss so now that we have all of these other components inside of the layout component we've got a group here that i labeled as public we'll want to keep these public we have the login page the register page a link page so we can just navigate and try out the other routes and then an unauthorized page that will show when someone is not authorized and then we have some routes that we want to turn into protected routes right now they're not but we have the home route which is once again just the root path then we have the editor the admin and then the lounge that should be accessible to both editors and admins and then we have a catch-all path essentially any request that doesn't match a path will go to this essentially a 404 page and will show our missing component for that so all of these routes should now be available publicly they're just not protected yet so let's save this open a terminal window again and go ahead and start our application with npm start okay and with our application started we are at the home component right now because it's not protected and we can go to the editor page we can go to the admin page we can even go to the lounge nothing is protected right now so all links are working we go to the link page here's the login we can go back and go to the register as well everything's available and this lets us know our route paths are working they're just not protected yet so now let's go back to visual studio code i'll close the terminal and we're ready to update how we're handling the global auth state we won't be putting the auth inside of our routes at all essentially because we want to keep this clean we don't want to have any of the conditional logic here we don't want to see if user and so on before our routes we want to handle this in a cleaner way and the way that's really recommended by the react router docs so that said we need to create another directory over here and let's call this directory hooks inside the hooks directory let's create a file called use auth with a capital a for auth dot js inside of use auth we're going to import use context from react we've got that now and now let's go ahead and import our auth context that we had created and that comes from the context directory and the auth provider then we need to define our hook which is use auth and this is a custom hook it's a very simple hook really it just saves us some time we'll have a return and have our use context and we'll pass in the auth context and then we need to set our default export so we will export default use auth and save so usually when we would use auth or use this context in any component as we'll see in the login component we would have to import use context import the auth context and then set our context equal to this use context auth context we can kind of eliminate those steps by just defining this custom hook so we can use auth and pull what we need from our auth context and we can see how this works inside of the login component so let's go to the login component and here we had use context imported so we can remove that we are also importing the auth context so we can remove that so now let's just import use off from our hooks directory and once we have that imported we find where we are actually using it in the component so we were bringing in the set auth function setting that equal to use context auth context so here we'll just say use auth and save and that's all there is to it and we wanted to do this because we're going to use this global auth in other parts of the application as well so this just makes it much easier and now we're ready to create the component that will help us protect our routes so let's create one more new component over here and we'll call this require auth with a capital r and capital a and once we have that defined we're going to import several things again from react router one is use location another is navigate with a capital n and another is outlet which also has a capital o to start out once we've imported those three things from react router we also need to import our use off hook and with those imports now we're ready to define the require auth component once i can spell again so require there we go auth and we're going to create two versions of this today the first version will be a little simpler more like it's a boolean basically whether the user is just logged in or not now later on we'll come back and change this and it will actually support role-based permissions for the users right now we just want to pull in the auth from use off and then we also need the location so we'll set that equal to use location and now let's create the return and inside of the return for the component since it's more like a boolean but we have an auth object we're just going to check to see if there is a user and that would indicate to us whether the user is logged in or not otherwise there wouldn't be in the future again we'll check roles but now just the user let's make this a ternary so if we have a user we're going to return the outlet now this is another outlet like the one that was in the layout component this one represents any child components of require auth so this require auth component can protect all the child components that are nested inside of it and so only if we have a user will it show these components after that let's have the false part of the ternary and here we'll have the navigate that we imported and we'll say two and we'll just send anyone that is not logged in to the login page but we also need to put a couple of attributes so let's have one called state and set that equal to two curly braces here and now from and we'll pass in that location and after that we're also going to set replace and that's because the user isn't asking to be sent to the login they wanted to go to another page but we found out they weren't logged in so we send them to the login so what we're going to do is replace the login in their navigation history with the location that they came from now there's something else we'll need to apply in the login component to make all of this work as it should as well but this passes along that value so we need that there as well too let's go ahead and put a semicolon there and we need to export default require auth and save okay now let's go to the app component and apply this new require auth component so then we need to import it as well and i'll put it just above the routes and route import so it's with the other components this will be require auth and it comes from the components directory and require auth and now that we have require auth we can protect these other routes with that component so here we'll say route and then we'll have element equals and we'll pass in the require auth component and after that we'll put the greater than sign once again to close the component and we get that closing route that we can put after these other routes that we want to protect so now let's save and all of the routes within this route that has require auth should be protected by require auth now let's remember these routes are home editor admin and lounge so let's go back now as we resize and check the links here inside of the browser so login and register still publicly available but we're not logged in so let's just check these routes to see if we can access them nope takes us straight to the login if we try to go home try the editors page straight to the login and the admin page once again straight to the login and notice how we were able to go back to where we were before and that is because we provided that extra attribute in require auth and i'll resize this so we can see it again that gave the from location and replace so let's temporarily remove these and save once again and see how the app responds differently now let's go to home and it took us to the login page and i'll click back and i'm still going back to the login that doesn't work the way we need it to so we really need this applied with those attributes and then if we reload and we can go back well there we are so now let's try once again it took us to the login and now if i click back we go directly back to where we were now in the future as i mentioned we need to do something to the login as well because then if we try to go to the admin page and we log in it will take us to where we want to go instead of just being dropped off at the home page and having to navigate again so it would kind of replace that history in the navigation and it would remember also where we were headed which is important as well not only where we came from okay before we apply the role based permissions and we're thinking about links and navigation and how the state from location and of course replacing that history in the navigation works let's go ahead and apply the changes that we need to to the login component as well so once we log in it can take us to where we were headed and of course it will remember where we came from at the top let's import three things from react router we're going to import link with a capital l use navigate and also we're going to import use location and all of that once again comes from react dash router dash dom and we'll save that much now if we scroll down just a little bit underneath the set auth let's put an extra line or two and here let's define i'll tab in let's define navigate set equal to use navigate then let's define location and we'll set that equal to use location and then we're going to define from let's set this equal to the location we just defined and then it has state and then we'll see if it has the from property and then we'll also see if it has a path name property and if it does that's what from will be other than that we'll set an or and we'll just set it to the root path which would take the user back to the home page otherwise but what we really want to do is get where they came from and then we want to scroll down to the handle submit function and change what is inside of there as far as where we're navigating our user to so after the form is cleared out then we want to navigate away so instead of just setting the success to true we'll put navigate here and we pass in that from value and then there's an object and we'll set the replace value to true and we can save this i guess i can put a semicolon over here to match so this essentially replaces that success page that was in the previous tutorial for the login so given that we can go ahead and remove the success and set success state that was in the login and we can also remove that display from the jsx so that removes our fragment and it removes our turn area there and we'll need to do that at the bottom as well and then we should be good to save and we're back to where we expect it to be so we have our form and upon success now we're using react router to navigate away and we're actually navigating to that from value which means where the user wanted to go before they were sent to the login page so now i'll pull over from the other window just so you can see this but i've got another instance of visual studio code and i'm going to install not install i'm going to start the back end node server with npm run dev this was created in my node.js for beginners course so you could go through that full tutorial and create this back-end server you can see it says connected to mongodb running on port 3500 and that's what i'm going to authen authenticate our users against and it's also going to send us roles but this will let us at least log in now even though we're just using essentially this true user response here for now and then we'll come back and add a little more to this so let's check our app once again when we resize let's say we want to go to the home page so now i'll enter in my name and i'll enter in my password and sign in and it took me to the home page so that is great let me sign out again let's say i wanted to go to the editors page because my user dave is an editor so i enter in my password and it takes me straight to the editors page even though i was redirected to the sign in page first and so that's why we're modifying that history with react router okay i'm going to sign out again but now i'm going to expand the web page then you can right click and choose inspect or you can do control shift i and let's look at the console okay you can see what i'm getting here in the console when i log in i'm getting sent back not only an access token but also roles today we're going to focus on the roles now everyone gets 2001. that means they're a user but then the editor role was the 1984 value so that's what we're confirming that we're getting back from that back-end api our user roles that we want to authenticate against so let's close the console again and resize the browser we'll come back to visual studio code and we can modify this require auth to now use those roles that are being stored inside of the auth state okay i'm going to go ahead and hide the file tree too just so nothing runs off the screen here and with this require auth component we're going to receive a prop and this prop is going to be allowed roles so this will get passed in and then once we receive that allowed roles instead of just checking to see if we have a user we're going to check the roles that are stored in our state and then we're going to find a higher order function here and we'll pass in each role to see if we find the role and then we're going to check the allowed roles and then we're going to see if the allowed roles includes the role that is being passed so what we're doing here is essentially looking for a value comparing the values of the two arrays this rolls is an array that is stored in our auth state and then the allowed roles is an array that is passed into this component and we're trying to match up a value so we're checking to see if this allowed roles array includes the role that's being passed and it will check each role in that array until it finds one and so if it doesn't find one then it would navigate away otherwise the outlet would be there and i don't want that semicolon that you saw me put there it confused me for a second because it was on a separate line so i did it out of habit but this is a ternary statement so this is what we're checking and it ends up being true or false and then we're either going to show the outlet if true and if not we'll navigate away but this isn't exactly what i want to do because we also want to show an unauthorized page there is a chance now that we have a user that is logged in but that just is not authorized to see the path or the page that they have requested essentially so if we want to show the outlet if true that's still fine but then after that let's go ahead and put this on another line we want a chained ternary which i don't mind some people do but this is not going to be a big chain ternary so we either have true for the outlet if not we're going to check something else so this is the beginning of the second ternary statement and then if we do have a user we just know they're not allowed to see what is nested here so then we're going to have a different navigate and otherwise then we'll show the login so this navigate is going to go to the unauthorized path and then let's go ahead and put in the same state because once again they didn't ask to go to the unauthorized path it's just where they ended up so we'll pass this along as well so the back button works and that's important too okay so now we've completed our require auth component that supports roles so once again the main logic here is we're comparing the values of two arrays we've got a roles array inside of our global authentication that says all the roles that the current user has and then we've got the allowed roles array that is passed into this component and we're going to compare the two so what we need to do yet is go back to the app component and pass in that allowed roles array for each path that we want to protect so now back in the app component right now we have one big block of protected routes but we're going to change this and what we need to do is pass allowed roles and now inside the allowed roles it's expecting an array so for the home path we can put in the user code which is 2001 but now we're going to need to close this route off with a closing tag so there we go and paste now we could put more than one path in here all of the different paths that are allowable to this user or this role we could put inside nested inside of this require auth path so now i'm going to copy the beginning here of the path and start another one for the editor i'll save just so we get some proper formatting and this is going to be different we're only going to allow in the role 1984 for the editor and we'll close that route as well and now for the admin it will be very similar route but it will have a different code this would be our 5150 code i'll scroll so we can see that and we should be closing that route afterwards as well and now our lounge is an example of where two different codes are allowed so now we can paste this and we'll have the allowed role of 1984 and 5150 so we can save those now in our system every user gets the role 2001 so we don't have to specify the 1984 or 5150 up here but if they did not if they only had one or the other then we could put all of the different roles up here in this array so a couple of things to note we can put more than one role in the array that's passed down another thing to note even though i'm not demonstrating it is we could put more than one path inside any one of these protected routes that are being protected by require auth now maybe you know these user codes for your company or for whoever you're working with and that's good enough for you to just pass in user codes and that's what is received from the server from the rest api that we've logged into however you could put in an object lookup and then use auto-completion to help you out so let's define the const up here just to show how that's done and we'll call this roles let's set this equal to an object and then you could put in user and here this would have a value of 2001 we'd have editor this would have a value of 1984 and then you'd have admin and this would have a value of 5150. so now we've created our roles object and now inside of these arrays instead of specifying the numbers you could say roles.user and we get autocompletion there which is nice so here i'll say roles.editor and then we'll have roles.admin there we go and now of course you can put in more than once so we're going to have roles.editor and then we'll also have roles dot admin and save so you can take advantage of auto completion with that and maybe it makes more sense to you to do that instead of having the codes remember if somebody digs enough your javascript is viewable by the public so maybe you don't want to put in the user editor and admin description either and you just want to make it a little less obvious by only using the code so that is totally up to you so with this saved we're ready to check our app once again let's come back to our app and now we'll go ahead and click the admin page and i'm going to log in with my username dave should not have access here two three there we go and i am unauthorized i do not have access to the requested page so i'll click go back and once i go back i'll click editors page and i am logged in so i can see the editors page no problem and i'm viewing the home page now which is only accessible if i log in and there's the link page so back to the home i can sign out and now let's log in with kevin and kevin does not have access to anything other than the home page so he is a user but he is not an editor and he is not an admin and so therefore he can't go to the lounge either but he could go to the link page we'll just sign out but now let's go ahead and sign in as jane who is trying to view the admin page that she should be able to and we're at the admin page she can also view the lounge because it's shared but she cannot view the editors page because she is not an editor so everything's working as expected one quick thing i didn't show before we go here we've resized that we'll come back and we want to look at that unauthorized component and we'll hide the file tree again the one thing to notice here is we are importing use navigate and we defined a quick function called go back and here this has navigate minus one which means it will just go back to where you came from and that's what we're using for the go back button on the unauthorized page so navigate -1 will just take you back one page in history overall i hope this tutorial has not only helped you understand react router version 6 a little bit better but it has helped you understand how to apply role-based user permissions for your protected routes remember to keep striving for progress over perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 369,444
Rating: undefined out of 5
Keywords: react protected routes, react, react js, role based authorization, react router, react router v6, react authorization, react user authorization, react route authorization, react auth, protected routes, protected routes in react, protected routes with react router, authorization in react, role based auth, role based authorization in react, react protected routes v6, react router 6 protected routes, protected routes and authentication with react router v6, reactjs, useauth, js, route
Id: oUZjO00NkhY
Channel Id: undefined
Length: 30min 42sec (1842 seconds)
Published: Fri Jan 14 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.