In this tutorial, you will learn how to apply a JWT user authentication strategy with access and refresh tokens to your React app. You will also learn how to create a private Axios instance and apply Axios interceptors to requests and responses. This tutorial is part 4 of a React User Login and Registration series. Links to all tutorials in this series are in the description. 🚀 If you're just getting started with React, I recommend my React JS for Beginners full course here: czcams.com/video/RVFAyFWO4go/video.html
Dave, I have the similar question. When should make the refresh token api call ? What is the best approach to hit refresh token endpoint to get new access token?
Hi, thanks a lot, but with React 18 the last part with interceptors doesn't work. I receive CanceledError if using react 18 method render in the index.js, like const root = ReactDOM.createRoot(document.getElementById('root')); . And everything is fine when you use simple ReactDOM.render('code here").
This video in combination with the "JWT Authentication | Node JS and Express tutorials for Beginners" is the only tutorial/tutorial series that actually describes the full backend to frontend implementation of jwt authentication. AND provides the source code. It was frustrating finding so many videos that only did part of the implementation and expected the viewers to know how to handle the rest. Thank you.
Thank you Dave - just watched your node jwt auth video with refresh tokens and now watching the implementation w/react on the client. Like someone said here there’s not to many dev/teachers who explain and implement jwt auth w/refresh end to end and with a database. Keep the videos coming my friend! Would love to see more intermediate - advanced topics especially in node. Peace and much love 🙏🏾
hey dave, i love ur teaching style but , i want just one thing that , if u can do , can plz first explain , in which file what are u going to do , what is your thinking behind that file creation , i understand u breaking file in individual part for code modulizing but when we see the video , first we have to understand why this file is created and why u do that , what is ur thinking behind that file creation then we understand rest of , no doubt your teaching skill are far greater then any other teachers on youtube , if u can do this that help us a lot , love from India
36:27 one small addition in that catch block, is to check if the catched error code is due to 'cancelled req' due to aborting req when component unmounts. otherwise it will keep navigating back to login page even after success login! the code will look like: const getUsers = () => { try{ //try block code } catch (err) { console.log("error fetching users", err); if (err.code !== "ERR_CANCELED") navigate("/login", { state: { from: location }, replace: true }); } }
I've seen many instructors Dave but you set a higher, newer, and better standard. You explain everything to the level of formatting your code and you master these skills with great knowledge. Awesome tutorial!!! you're awesome, subscribed for sure.
Thank You! I was waiting for this video. There is no video on CZcams which shows how to implement Refresh Token. Even I took a udemy course and it just showed me how to implement just Access Token and skipped the Refresh Token part. Thank You soo much!
If you get 403 status when you try to refresh token, it's probably because during login cookies might not be saved in the browser. To fix it, you have to change siteName attribute from 'None' to 'Strict' when you are sending cookies ( Login and Refresh Token route)
These are baller vids man. Ive been at an internship for 3 months now, and the first couple months was a brain bleeding experience -- all of my self taught apps up to the point of hire were very one dimensional and basic, in terms of fetches, config, etc (they still are, but slightly better). After working in a pro setting and having to learn and use better practices such as custom hooks, acios config objects, etc, I can now follow and appreciate these videos even more. This is the perfect level of difficulty for me to improve my hobby applications. Great content, thank you so much!
You are on 🔥 with these advanced topics. Please keep them coming as there aren’t as many great videos on these topics. I just happen to be working on a new authentication system at work and trying to understand the differences between access, refresh token and the best practices for storing them and your video helped a lot ✊ and right on time
Hey Dave just wanted to point out that axios >= 1.0.0 (1.0 was released ~10 days ago) will cause your response interceptor to reject an error when retrying. There are a few lines in the axios source code that, when trying to normalize values, ends up returning any unknown value via toString, which ends up spitting out an entire function being toStringed as the error passed into the response interceptor. Downgrading axios to 0.27.2 allowed your solution to work perfectly.
@@DaveGrayTeachesCode Hey! Are you not going to say anything about a quick fix? I have been struggling with this problem for a couple of hours and just now saw this comment
Enjoyed the content on JWT Authentication on React. I have bookmarked your other videos on the playlist. I highly recommend your Nodejs and ReactJS course.
Hi Dave thanks a lot for this tutorial, it helped me a lot for implementing a refresh token flow at my React app. I would like to add a small fix to your guide, instead of using 403 response status at the interceptor, use 401. 401 refers to unauthorized, it means the client provides no credentials or invalid credentials, and 403 the client has valid credentials but not enough privileges to perform an action on a resource. If we validate vs 403, we can have the scenario of refreshing the token unnecessarily if the user doesn't have a role for a specific request.
@@DaveGrayTeachesCode I had the same issue, the ChatGpt response about that is: "When an access token expires in API, you should return the HTTP status code 401 Unauthorized, along with a WWW-Authenticate header indicating the authentication method required to access the requested resource. The HTTP status code 401 Unauthorized indicates that the request lacks valid authentication credentials for the target resource, and the WWW-Authenticate header informs the client which authentication method to use to authenticate the request. This is the correct status code to use when an access token has expired or is invalid. The HTTP status code 403 Forbidden, on the other hand, indicates that the server understood the request, but refuses to authorize it. This means that the client has authenticated correctly, but does not have sufficient permission to access the requested resource. Therefore, it is not appropriate to use the HTTP status code 403 Forbidden when the access token has expired in API. I had the same issue, the ChatGpt response about that is:In summary, when an access token expires in Web API, you should return the HTTP status code 401 Unauthorized."
Phew! This was a tricky one and it took a while to get it working correctly but I got there in the end. I had the same cookie problem as Marcos but working fine now after adding 'secure: true' to the cookie settings.
youtube now doesn't display dislike anymore. Dave if you see dislikes at the backend of youtube, don't frustrate, those dislikes are from bootcamp training people. we suport you. learned a lot from MERN stack series and this series. The redux series is little tough but I will spend more time on those. Thanks!
Hey Dave, I appreciate all your hard work in putting these videos together for those of us trying to learn something new. I enjoyed your video but I am having issues when logging in to see the Users list. I've seen that you answered similar questions about getting a CanceledError and I've also taken a look at your other videos describing these breaking changes. I've tried to implement your solutions while still working with strict mode but, I still receive errors. So far the only solution that has worked for me is to remove the AbortController in the Users component's useEffect but, is that appropriate? I would like to do things the right way and seeing as how you have the Abort Controller I just don't know what I should do.
Hi Rick. The AbortController issues an CanceledError by default when called. It is not a bad thing because it is expected to happen. With React 18 strict mode, React mounts, unmounts, and remounts each component. This creates one of those CanceledErrors. I did make a video about how to workaround this here: czcams.com/video/81faZzp18NM/video.html
@@DaveGrayTeachesCode Thanks for the response! I am currently watching the workaround video because at this point I considered removing the AbortController altogether. Do the errors also explain why, when I try to log in to see the users list, I was not redirected to see the list? When I try to log in, I can see the user object retrieved but all that happens is the Login form/component reloads.
Thank you Dave. I can't stop recommending you to my friends/colleagues. If one wants to learn modern react, your channel is highly recommended. You have helped me change some of my old codes.
In my app, I won't need registering, and I was searching for a tutorial on handling JWT authentication with react. You literally saved me posting this tutorial right now. I will try to implement only login using this video, I'm using Django for my backend. Thank you very much, very good and understandable tutorials + the small tips and tricks with the VS Code are also on point!
Hey, I am someone who knows react and js very little. I decided to build a full-stack application using React on TypeScript, SpringBoot on Java and MySql database. While I feel confident with Java and Spring, I struggle a lot with React. This series helps me a lot to implement a logging system and routing system. Some topics like cors weren't clear to me and with this series and with some ChatGPT explanation I got to the point where every basic info about HTTP-only cookies, tokens, react-router, etc became greatly allocated in my brain :). I would pay for a course like this, so I really think this is super valuable material. Peace and happy coding!
Thank you for your explanation. Can I have a question? If you don't store auth state in browser storage, when user reload the page, how to know if user is logged in or not?
Incredible! I had been looking for this content for some time, I was very dissatisfied with my authentication strategy, as I started in the area recently, I ended up following some practices, which based on initial knowledge, it is not possible to say whether it is a safe practice or not. your approach gave me good insights into how I can keep improving, thanks Dave, impeccable work. hugs from Brazil!
This one explained all I needed and relieved me of that pain related to access/refresh tokens that I've been having for the last couple of days. Thank you, Dave!
Your videos are making great changes to my skillset and improving standard programming concept everyday. You are awesome Dave Gray. I really appreciate your hard work.
Thanks for the amazing video(s)! Question, in your useAxiosPrivate hook, why did you add the refreshToken hook in the useEffect dependency array? it's a static function, innit?
You're welcome! Going back in time and my memory here... this was with React 17 that complained about things missing from the useEffect dependency array even when they weren't sometimes needed... so I usually added everything it complained about. Otherwise, many questions from viewers about the warning for the missing dependencies.
If you are using React 18, I suggest using a boolean ref with useRef before the getUsers function. In User.js: if (firstRenderRef.current) { firstRenderRef.current = false return } const getUsers = async () => { try { // something } catch (err) { console.error(err) navigate('/login', { state: { from: location }, replace: true }) } }
A very similar suggestion / solution to the "fix" I suggest in my video here: czcams.com/video/81faZzp18NM/video.html - good stuff, James! 💯 I will also be sharing a re-work of this full auth flow soon which uses React Query and React 18.
Hey Dave, just wanna say thank you for this amazing tutorial you really made it crystal clear on how to handle the tokens. Much love and wish you good health 🙏
just wanna note to myself or anyone who confused like me. 32:00 axios interceptors is the middle man who intercept between client and server both ways, request and response. the part that said !prevRequest?.sent means ?. operator is used to safely access properties or call methods on a possibly null or undefined value. null or undefined value in if statement is considered as false therefore, .....!prevRequest?.sent means if sent property doesn't exist, then undefined but not throw error and with the ! negates then the whole this of (!prevRequest?.sent) is true. thus, if sent doesn't exist then create this sent property, prevRequest.sent = true;
Great tutorial, got so many doubts cleared. However I have 1 question: Since, we are already sending access token and at server can also access refreshToken from cookie (as withCredentials is true), we can simply verify accessToken at server and if it's expired, we can verify refreshToken and if refresh token is valid we can simply send back new access token. This way we don't have to make 2 (requestInterceptor and responseInterceptor) requests to the server and hence don't require responseInterceptor at all.
Congratulations on 💯. What a great way to wrap up the year. Might be a good occasion to post a non-technical video. I am sure a lot of people would love to know you more.
Great tutorial! Very helpful, and as somebody else mentioned, I love that you mention every shortcut you use in VS Code because that lets em improve my own workflow. I'm always postponing diving deeper into VS Code's tools and this kills two birds with one stone (my apologies to PETA members).
Tus tutoriales son fantásticos! Estoy estudiando inglés por lo que se me complica un poco el idioma, pero tu contenido es de extrema utilidad. New sub! thx
thank you sir for this this truly raised my level up a notch and am happy this series teaches almost everything and i must say it did get a bit advanced for me lol
Your videos are one of the best out there. Each time there are anything that I don't understand from your video, I will go and research more on that portion and I will learn a lot. I got lost on the useAxiosPrivate hook portion but I just followed along the tutorial and it works!! Now I need to go learn about interceptors. Do you have any videos on it?
Glad I could help, Jonathan! 💯 This is the video I cover where I cover Axios interceptors overall. They intercept requests and responses and allow you to modify those requests and responses as they are intercepted. The Axios docs cover them here, too: axios-http.com/docs/interceptors
For the people running into the Refresh Error from axios instance change this: prevRequest.headers['Authorization'] = `Bearer ${newAccessToken}`; To: prevRequest.headers = { ...prevRequest.headers, Authorization: `Bearer ${newAccessToken}` };
One thingy I noticed. Let's say we open a page in a new tab, and this page has two different resources we need to get, let's say /cars to get a list of cars and /fruits to get a list of fruits. Those two request are sent immediatelly, without waiting one another. At the moment of time we don't have an access token, but we have a refresh token. Since the request are sent in parallel - we'll have the refresh token flow twice. So basically the more requests we issue - the more refresh token requests we'll get as a result. It would be nice to somehow delay all requests if refresh token request has started and hasn't finished yet.
What an amazing tutorial, Dave! Thank you very much for all your efforts putting in these videos! I've been wondering that why we shouldn't store JWT in local storage, because when we make a private request, we attach our JWT in the header ("Authorization": "Bearer ..."), so someone can copy that token from the request header. Why is this method more secured?
Wouldn't it make more sense to store the JWT expiration as a unix timestamp in the JWT and always check if the token has expired, so we do not get 403 responses at all?
There is usually more than one way to solve a problem, and your method could be employed. I prefer the separation of concerns from frontend and backend which is demonstrated here and lets the backend handle expirations. That said, some may prefer to decode the JWT on the frontend and circumvent the backend check with a check of their own. The frontend is never 100% secure and the backend still needs to track expired tokens, so I'd still keep the backend checks in place either way.
24:52 - I am always confused about this. Our auth and refresh - are an object and a function - reference type. When we use it in a dependency array - it will always "change" and make the component to be rerendered? No?
Hi Dave!, excellent video and explanation! Thank you! I have a doubt, it could be better to control the requests and responses with the axios interceptor, for example by putting the interceptors in the index.js, so in this way we do not repeat code, and control the redirection to the login also in the interceptors 🧐, I was thinking that it would be good, for example if we had more than 30 pages and components with authorization, we would need more than 30 redirections, it was just a thought not to repeat code if the app is big, thanks again for these videos! they are great! 👍
If you were creating many components you could abstract more logic. Remember the app may also have public pages so blanketing everything in the index might not be ideal. Overall, this code could serve as a blueprint to be modified as needed. I'm glad you like the series and thanks for the kind words! 💯🚀
Hi, Dave! First of all, thanks a lot for helpful tutorials you make. I have a question about a situation that refreshToken gets expired. Here's how things go in user's perspective. An admin user logs in => visits Home page => visits Admin page => waits 30s for refreshToken to be expired => visits Home page(!) => visits Admin page(!) => be redirected to Login page => can visit Home page by clicking browser's "go back" button(!) Those with (!) mark are not expected behaviours. Shouldn't user be logged out when refreshToken expires? Why a user can visit pages that require auth? What am I missing and what should I do?
Thank you a lot lot I was struggling how to combine .NET Core API implementing JWT with React, may gold bless you and give you what you wish, you helped me a lot !!
This is great content, i watched all videos, probably forgot to like them all, but already subscribed to the channel. Thanks very much for the explanation 👏
TYSM Dave ♥. May I ask why you're ejecting axios interceptors? Their documentation is also not very clear on this one. If we need an axios instance without those interceptors we can just use another instance other than axiosPrivate, right? So...?
Much like event listeners, if you do not remove the interceptors, they will begin to stack up. With interceptors, your requests will multiply. This will create unnecessary requests and unexpected behavior.
hey Dave just want to say this was a great tutorial, definitely has helped me alot to understand how to work with jwt and refresh tokens on the client side, can you do a tutorial on how to deploy with docker / kubernetes / enginx
Hi, Dave! Whould you consider a good choice to move the "redirection to login page" from the users component to the useAxiosPrivate hook? That is: in useAxiosPrivate.js, 1) add the required imports import { useNavigate, useLocation } from "react-router-dom"; 2) initalize const navigate = useNavigate(); const location = useLocation(); 3) replace the line newAccessToken = await refresh(); with something like: try { newAccessToken = await refresh(); } catch (err) { console.log("Cannot refresh token: redirecting to login page.", err); navigate('/login', { state: { from: location }, replace: true }); } ? This should handle the redirection logic in a unique point in the application, avoiding to replicate it in every component. Thanks!
I found a lot but this is the only video I've found on youtube with both access & refresh token used with proper purpose. I have one query, what if we use RTK (not RTKQ) and want to use useAxiosPrivate hook inside createAysncThunk to send/fetch data from server. How can we place axiosPrivate in that case as we can't use custom hooks outside component ot any other custom hooks. Again, thanks a lot for this video.👍
I made a video that applies this to Redux, but it may not apply it in the way you described... nevertheless, you can check out how it works here: czcams.com/video/-JJFQ9bkUbo/video.html
Hello Dave Gray, This tutorial was very helpful, it gave me a few ideas when working with access and refresh tokens, also learned a few new things too, I was able to work JWTs into a react app project I’m working on that relies on Passport.JS and Redis for authentication. For anyone running the React and backend server on a different machine and accessing it from a browser on another machine. On the backend, you’ll need to remove “samesite” and set “secure” to false for the secure cookie within “handleRefreshToken” to be set in a browser. Secure will only work if everything is being accessed from the same machine or you are feeding an HTTPS cert with the request. Please correct me if I’m wrong because chrome and Brave under network had a very tiny yellow “!” error that was hard to find. No errors were showing under console from Chrome, Brave or FireFox.
You're welcome! 💯 Just to add to your note which I believe is accurate.. In production, you will always want to use HTTPS instead of HTTP and add secure: true back to the cookie.
Skylark, I have to say it... I fu***** love you. You've just solved the issue that I've not been able to solve in the last 24hs. I was just getting a 401 with the sameSite="none" configuration, I dig into the whole web until I got to your comment. THANKS.
Link to the Node JS course is in the description. It has a resources link in its description with source code for every chapter. You will want to grab the last chapter if you just want the code.
Great guide! almost feel like I need to rewrite all my code cause the tutorials I followed didn't cover half of what you did... but that will be for some other time cause I have other projects to finish x) But thx for sharing your knowledge ow wise man!
Great tutorial ! I finally pushed myself to learn React and tous helped me a lot, i improved so much. But there is one thing i can't wrap my head around: why having the short duration jwt in memory if we have one supposedly more exposed in cookie to generate other short duration jwt?
Thank you! 🙏 For these tutorials, I have extremely short token durations as examples. A more realistic duration for the access token is anywhere from 15 to 60 minutes (set to preference) and the refresh token often lasts a day or longer. There are links in the description to articles discussing this strategy, too.
In this tutorial, you will learn how to apply a JWT user authentication strategy with access and refresh tokens to your React app. You will also learn how to create a private Axios instance and apply Axios interceptors to requests and responses. This tutorial is part 4 of a React User Login and Registration series. Links to all tutorials in this series are in the description. 🚀 If you're just getting started with React, I recommend my React JS for Beginners full course here: czcams.com/video/RVFAyFWO4go/video.html
I have a doubt is it fine having so many 403 requests made and logged in the console? Or is calling refresh token api in a settimeout better?
Dave, I have the similar question. When should make the refresh token api call ?
What is the best approach to hit refresh token endpoint to get new access token?
@@samiullahsheikh5015 using the Axios interceptors detailed in this tutorial, the refresh token endpoint is automatically requested when needed.
@@vickylance nothing wrong with a 403 if it is handled. The interceptors handle it. 💯
Hi, thanks a lot, but with React 18 the last part with interceptors doesn't work. I receive CanceledError if using react 18 method render in the index.js, like const root = ReactDOM.createRoot(document.getElementById('root')); . And everything is fine when you use simple ReactDOM.render('code here").
This video in combination with the "JWT Authentication | Node JS and Express tutorials for Beginners" is the only tutorial/tutorial series that actually describes the full backend to frontend implementation of jwt authentication. AND provides the source code. It was frustrating finding so many videos that only did part of the implementation and expected the viewers to know how to handle the rest. Thank you.
You're very welcome!
Yes thanks a lot! I attempted this about 2 yrs ago and couldn’t find a video on it being done the right way; they didn’t store access token in memory!
Thank you Dave - just watched your node jwt auth video with refresh tokens and now watching the implementation w/react on the client. Like someone said here there’s not to many dev/teachers who explain and implement jwt auth w/refresh end to end and with a database. Keep the videos coming my friend! Would love to see more intermediate - advanced topics especially in node. Peace and much love 🙏🏾
Thank you, ZB! 💯
hey dave, i love ur teaching style but , i want just one thing that , if u can do , can plz first explain , in which file what are u going to do , what is your thinking behind that file creation , i understand u breaking file in individual part for code modulizing but when we see the video , first we have to understand why this file is created and why u do that , what is ur thinking behind that file creation then we understand rest of , no doubt your teaching skill are far greater then any other teachers on youtube , if u can do this that help us a lot , love from India
36:27 one small addition in that catch block, is to check if the catched error code is due to 'cancelled req' due to aborting req when component unmounts. otherwise it will keep navigating back to login page even after success login! the code will look like:
const getUsers = () => {
try{
//try block code
} catch (err) {
console.log("error fetching users", err);
if (err.code !== "ERR_CANCELED")
navigate("/login", { state: { from: location }, replace: true });
}
}
This is gold! It just doesn't talk about the concepts instead develops per expectations of a real time user application. Absolutely loved it!
Thanks!
I've seen many instructors Dave but you set a higher, newer, and better standard. You explain everything to the level of formatting your code and you master these skills with great knowledge. Awesome tutorial!!! you're awesome, subscribed for sure.
Thank you for the kind words, and welcome aboard! 💯
Thank You! I was waiting for this video. There is no video on CZcams which shows how to implement Refresh Token. Even I took a udemy course and it just showed me how to implement just Access Token and skipped the Refresh Token part. Thank You soo much!
Right on! 💯 I have also noticed this information is hard to find. I have included some resource links in the description too.
@@DaveGrayTeachesCode Thanks, I will read those articles too.
If you get 403 status when you try to refresh token, it's probably because during login cookies might not be saved in the browser. To fix it, you have to change siteName attribute from 'None' to 'Strict' when you are sending cookies ( Login and Refresh Token route)
it still doesn't work
I love how you simplify the topic while explaining sir.
Thank You so much
Thank you, Ritesh! 💯🙏
These are baller vids man. Ive been at an internship for 3 months now, and the first couple months was a brain bleeding experience -- all of my self taught apps up to the point of hire were very one dimensional and basic, in terms of fetches, config, etc (they still are, but slightly better). After working in a pro setting and having to learn and use better practices such as custom hooks, acios config objects, etc, I can now follow and appreciate these videos even more. This is the perfect level of difficulty for me to improve my hobby applications. Great content, thank you so much!
You are on 🔥 with these advanced topics. Please keep them coming as there aren’t as many great videos on these topics. I just happen to be working on a new authentication system at work and trying to understand the differences between access, refresh token and the best practices for storing them and your video helped a lot ✊ and right on time
That's great to hear! Glad I could help and thanks for the support! 💯🚀
went from studying your videos to getting a job. Although we kind of not use react, but because of my skills I got the job. So A big thank you
Hey Dave just wanted to point out that axios >= 1.0.0 (1.0 was released ~10 days ago) will cause your response interceptor to reject an error when retrying. There are a few lines in the axios source code that, when trying to normalize values, ends up returning any unknown value via toString, which ends up spitting out an entire function being toStringed as the error passed into the response interceptor.
Downgrading axios to 0.27.2 allowed your solution to work perfectly.
Thanks Vince - yes, technology keeps moving forward. Also note this tutorial uses React 17 and React 18 strict mode will trigger multiple requests.
Hi Dave! Loving the tutorials. Any plans on updating this to keep up with updates?
@@dukekim4816 YT will not let me update videos.
Do you think this will get fixed in the future?
@@DaveGrayTeachesCode Hey! Are you not going to say anything about a quick fix? I have been struggling with this problem for a couple of hours and just now saw this comment
Enjoyed the content on JWT Authentication on React. I have bookmarked your other videos on the playlist. I highly recommend your Nodejs and ReactJS course.
Hi Dave thanks a lot for this tutorial, it helped me a lot for implementing a refresh token flow at my React app. I would like to add a small fix to your guide, instead of using 403 response status at the interceptor, use 401. 401 refers to unauthorized, it means the client provides no credentials or invalid credentials, and 403 the client has valid credentials but not enough privileges to perform an action on a resource. If we validate vs 403, we can have the scenario of refreshing the token unnecessarily if the user doesn't have a role for a specific request.
Thanks for the note! Not sure where I first learned 403 was the response to use for the expired access token but I stand corrected. 💯
@@DaveGrayTeachesCode
I had the same issue, the ChatGpt response about that is:
"When an access token expires in API, you should return the HTTP status code 401 Unauthorized, along with a WWW-Authenticate header indicating the authentication method required to access the requested resource.
The HTTP status code 401 Unauthorized indicates that the request lacks valid authentication credentials for the target resource, and the WWW-Authenticate header informs the client which authentication method to use to authenticate the request. This is the correct status code to use when an access token has expired or is invalid.
The HTTP status code 403 Forbidden, on the other hand, indicates that the server understood the request, but refuses to authorize it. This means that the client has authenticated correctly, but does not have sufficient permission to access the requested resource. Therefore, it is not appropriate to use the HTTP status code 403 Forbidden when the access token has expired in API.
I had the same issue, the ChatGpt response about that is:In summary, when an access token expires in Web API, you should return the HTTP status code 401 Unauthorized."
This is something I still struggle with after 3 years experience. This cleared up all my confusions. Thanks as usual, Dave!
Amazing tutorials, I've rarely seen something that well explained, and detailed. The rythm is great too !
Happy to hear that!
Phew! This was a tricky one and it took a while to get it working correctly but I got there in the end. I had the same cookie problem as Marcos but working fine now after adding 'secure: true' to the cookie settings.
Good job, Andrew! 💯🚀
Man waiting for full stack beginner friendly project
Coming soon! 💯
youtube now doesn't display dislike anymore. Dave if you see dislikes at the backend of youtube, don't frustrate, those dislikes are from bootcamp training people. we suport you. learned a lot from MERN stack series and this series. The redux series is little tough but I will spend more time on those. Thanks!
Thank you for the kind words!
Hey Dave, I appreciate all your hard work in putting these videos together for those of us trying to learn something new. I enjoyed your video but I am having issues when logging in to see the Users list. I've seen that you answered similar questions about getting a CanceledError and I've also taken a look at your other videos describing these breaking changes. I've tried to implement your solutions while still working with strict mode but, I still receive errors.
So far the only solution that has worked for me is to remove the AbortController in the Users component's useEffect but, is that appropriate?
I would like to do things the right way and seeing as how you have the Abort Controller I just don't know what I should do.
Hi Rick. The AbortController issues an CanceledError by default when called. It is not a bad thing because it is expected to happen. With React 18 strict mode, React mounts, unmounts, and remounts each component. This creates one of those CanceledErrors. I did make a video about how to workaround this here: czcams.com/video/81faZzp18NM/video.html
@@DaveGrayTeachesCode Thanks for the response! I am currently watching the workaround video because at this point I considered removing the AbortController altogether. Do the errors also explain why, when I try to log in to see the users list, I was not redirected to see the list?
When I try to log in, I can see the user object retrieved but all that happens is the Login form/component reloads.
Thank you Dave. I can't stop recommending you to my friends/colleagues. If one wants to learn modern react, your channel is highly recommended. You have helped me change some of my old codes.
Awesome, thank you! 💯🚀
In my app, I won't need registering, and I was searching for a tutorial on handling JWT authentication with react. You literally saved me posting this tutorial right now. I will try to implement only login using this video, I'm using Django for my backend. Thank you very much, very good and understandable tutorials + the small tips and tricks with the VS Code are also on point!
Glad I could help! 💯
Hey, I am someone who knows react and js very little. I decided to build a full-stack application using React on TypeScript, SpringBoot on Java and MySql database. While I feel confident with Java and Spring, I struggle a lot with React. This series helps me a lot to implement a logging system and routing system. Some topics like cors weren't clear to me and with this series and with some ChatGPT explanation I got to the point where every basic info about HTTP-only cookies, tokens, react-router, etc became greatly allocated in my brain :). I would pay for a course like this, so I really think this is super valuable material.
Peace and happy coding!
Thank you for your explanation.
Can I have a question?
If you don't store auth state in browser storage, when user reload the page, how to know if user is logged in or not?
Go to the next video in this series to create a Persistent Login (link in description)
Incredible! I had been looking for this content for some time, I was very dissatisfied with my authentication strategy, as I started in the area recently, I ended up following some practices, which based on initial knowledge, it is not possible to say whether it is a safe practice or not. your approach gave me good insights into how I can keep improving, thanks Dave, impeccable work. hugs from Brazil!
This guy could explain a very technical concept to a toddler and the toddler would understand it with ease. Thank you for this wonderful tutorial
Thank you for the kind words, Ibrahim! 🙏🙏
can someone explain why the useAxiosPrivate uses a useEffect and why the unneccesary auth and refresh dependency?
I love how you explain concepts in detail. You go as far as explaining the motivation behind every decision made. Great tutorial and thanks!.
This one explained all I needed and relieved me of that pain related to access/refresh tokens that I've been having for the last couple of days. Thank you, Dave!
Glad I could help!
Your videos are making great changes to my skillset and improving standard programming concept everyday. You are awesome Dave Gray. I really appreciate your hard work.
Great to hear! Thank you!
Thanks Dave Gray, i searched for this course and didn't find any clear and functional tutorial like your, Well Done
Glad it was helpful!
I have watched many tutorials and paid courses but this is next level - awesome explanation of everything ! Thank you!
Thanks for the amazing video(s)!
Question, in your useAxiosPrivate hook, why did you add the refreshToken hook in the useEffect dependency array? it's a static function, innit?
You're welcome! Going back in time and my memory here... this was with React 17 that complained about things missing from the useEffect dependency array even when they weren't sometimes needed... so I usually added everything it complained about. Otherwise, many questions from viewers about the warning for the missing dependencies.
A perfect solution to my every problem. Trust me this video is going to help me a lot.
If you are using React 18, I suggest using a boolean ref with useRef before the getUsers function.
In User.js:
if (firstRenderRef.current) {
firstRenderRef.current = false
return
}
const getUsers = async () => {
try {
// something
} catch (err) {
console.error(err)
navigate('/login', { state: { from: location }, replace: true })
}
}
A very similar suggestion / solution to the "fix" I suggest in my video here: czcams.com/video/81faZzp18NM/video.html - good stuff, James! 💯 I will also be sharing a re-work of this full auth flow soon which uses React Query and React 18.
Finally, a video that shows you how to securely authenticate users. Thanks Dave
Welcome!
Finally intermediate tuts for my job - appreciate your content, helps me get little bit higher and self sufficient as React dev at job field
Glad I could help!
Great tutorial😍, Keep sharing videos like this, Wish you more subscribers for your great efforts and time
Thank you!
Hey Dave, just wanna say thank you for this amazing tutorial you really made it crystal clear on how to handle the tokens. Much love and wish you good health 🙏
You're welcome, Roni! 🙏💯
just wanna note to myself or anyone who confused like me.
32:00
axios interceptors is the middle man who intercept between client and server both ways, request and response.
the part that said !prevRequest?.sent means
?. operator is used to safely access properties or call methods on a possibly null or undefined value.
null or undefined value in if statement is considered as false
therefore, .....!prevRequest?.sent means
if sent property doesn't exist, then undefined but not throw error and with the ! negates then the whole this of (!prevRequest?.sent) is true.
thus, if sent doesn't exist then create this sent property, prevRequest.sent = true;
Super helpful! I struggled making this year ago. I’m glad to see this explained because it seems much more manageable/clear coming from you!
Glad I could help! 💯
Great tutorial, got so many doubts cleared. However I have 1 question: Since, we are already sending access token and at server can also access refreshToken from cookie (as withCredentials is true), we can simply verify accessToken at server and if it's expired, we can verify refreshToken and if refresh token is valid we can simply send back new access token. This way we don't have to make 2 (requestInterceptor and responseInterceptor) requests to the server and hence don't require responseInterceptor at all.
Congratulations on 💯. What a great way to wrap up the year. Might be a good occasion to post a non-technical video. I am sure a lot of people would love to know you more.
Thank you and thank you for the request! 💯
Great tutorial! Very helpful, and as somebody else mentioned, I love that you mention every shortcut you use in VS Code because that lets em improve my own workflow. I'm always postponing diving deeper into VS Code's tools and this kills two birds with one stone (my apologies to PETA members).
You're welcome!
Tus tutoriales son fantásticos! Estoy estudiando inglés por lo que se me complica un poco el idioma, pero tu contenido es de extrema utilidad.
New sub!
thx
Gracias Lucas! Yo comprende un poquito español mi amigo 😃
The best IT teacher over the world!
This is probably the best JWT auth tutorial i've seen. Thank you!
Thank you, James! 🙏
I have zero idea what’s happening but I still watched-no clue why.
What if page is refreshed after loggedin? Our access token will be vanished from app’s state?
All this interconnected tutorials feels like movies franchise :)
love this tutorial btw.
Now I think I know how to apply access/refresh token strategy to web services. Thank you for the great tutorial!
Glad it was helpful! 💯
Thank for showing way to implement role based authentication and access control in react.
thank you sir for this this truly raised my level up a notch and am happy this series teaches almost everything and i must say it did get a bit advanced for me lol
Thank you for the tutorials!! Made it through all 4 and I'm happy that I did
A simple like or share is not enough for this rich tutorial. you deserve more. take love.
Thank you for the kind words! 🙏🙏
Your videos are one of the best out there. Each time there are anything that I don't understand from your video, I will go and research more on that portion and I will learn a lot. I got lost on the useAxiosPrivate hook portion but I just followed along the tutorial and it works!! Now I need to go learn about interceptors. Do you have any videos on it?
Glad I could help, Jonathan! 💯 This is the video I cover where I cover Axios interceptors overall. They intercept requests and responses and allow you to modify those requests and responses as they are intercepted. The Axios docs cover them here, too: axios-http.com/docs/interceptors
For the people running into the Refresh Error from axios instance change this:
prevRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
To:
prevRequest.headers = { ...prevRequest.headers, Authorization: `Bearer ${newAccessToken}` };
This whole playlist was of insane help. Don't know how to say thank you. But thank you anyway
You're welcome! 🙏
One thingy I noticed. Let's say we open a page in a new tab, and this page has two different resources we need to get, let's say /cars to get a list of cars and /fruits to get a list of fruits.
Those two request are sent immediatelly, without waiting one another. At the moment of time we don't have an access token, but we have a refresh token. Since the request are sent in parallel - we'll have the refresh token flow twice.
So basically the more requests we issue - the more refresh token requests we'll get as a result.
It would be nice to somehow delay all requests if refresh token request has started and hasn't finished yet.
Sounds like you are using React 18 in strict mode. Fix for what you are describing: czcams.com/video/81faZzp18NM/video.html
Wow, thanks for responding tho my request. This was worth the wait! Genius presented in a way that can be understood by the average react developper…
Right on! 💯 Glad I could help!
What an amazing tutorial, Dave!
Thank you very much for all your efforts putting in these videos!
I've been wondering that why we shouldn't store JWT in local storage, because when we make a private request, we attach our JWT in the header ("Authorization": "Bearer ..."), so someone can copy that token from the request header. Why is this method more secured?
Wouldn't it make more sense to store the JWT expiration as a unix timestamp in the JWT and always check if the token has expired, so we do not get 403 responses at all?
There is usually more than one way to solve a problem, and your method could be employed. I prefer the separation of concerns from frontend and backend which is demonstrated here and lets the backend handle expirations. That said, some may prefer to decode the JWT on the frontend and circumvent the backend check with a check of their own. The frontend is never 100% secure and the backend still needs to track expired tokens, so I'd still keep the backend checks in place either way.
Thank You! There is not so much high quality information regarding advanced topics such as authentification. Please keep on with such videos.
You're welcome! 💯🚀
This is the best JWT-cookie auth tutorial i've seen. Thank you so mush!, all works for me . thank you again for this awesome Tutorial.
You're welcome!! 🙏
I think I need to watch this video one more time,
I feel like my brain got shrank a little, it's maybe the cold weather,
Thanks Dave,
It's definitely the cold weather my friend! 🥶
24:52 - I am always confused about this. Our auth and refresh - are an object and a function - reference type. When we use it in a dependency array - it will always "change" and make the component to be rerendered? No?
thank you so much for the video, you answered all my confusions already in the first few mins! enjoying the whole video now
Glad it was helpful! 💯
your explanati level on is something else !!!
Hey Dave, Amazing tutorial as usual.
Im very happy to find pro tutorials like that in youtube and want to say thank you!
You're welcome! 💯
Hi Dave!, excellent video and explanation! Thank you! I have a doubt, it could be better to control the requests and responses with the axios interceptor, for example by putting the interceptors in the index.js, so in this way we do not repeat code, and control the redirection to the login also in the interceptors 🧐, I was thinking that it would be good, for example if we had more than 30 pages and components with authorization, we would need more than 30 redirections, it was just a thought not to repeat code if the app is big, thanks again for these videos! they are great! 👍
If you were creating many components you could abstract more logic. Remember the app may also have public pages so blanketing everything in the index might not be ideal. Overall, this code could serve as a blueprint to be modified as needed. I'm glad you like the series and thanks for the kind words! 💯🚀
Good effort but step by step by approach makes understandable more
You're awesome Mr.Gray. Keep up your great work, your channel gonna be big in the future !
Thank you for the kind words! 🚀
Hi, Dave!
First of all, thanks a lot for helpful tutorials you make. I have a question about a situation that refreshToken gets expired. Here's how things go in user's perspective.
An admin user logs in => visits Home page => visits Admin page => waits 30s for refreshToken to be expired => visits Home page(!) => visits Admin page(!) => be redirected to Login page => can visit Home page by clicking browser's "go back" button(!)
Those with (!) mark are not expected behaviours. Shouldn't user be logged out when refreshToken expires? Why a user can visit pages that require auth? What am I missing and what should I do?
I'm not sure what you are missing, but you can possibly view cached pages from your history - however, reloading those pages won't work.
Thank you a lot lot I was struggling how to combine .NET Core API implementing JWT with React, may gold bless you and give you what you wish, you helped me a lot !!
Glad to hear I helped!
Very well explained. Helping me a lot, Mr. Dave. Cheers from japan
Thank you! And hello 👋 to Japan!
This is great content, i watched all videos, probably forgot to like them all, but already subscribed to the channel. Thanks very much for the explanation 👏
Welcome aboard! And thank you for the kind words! 🙏💯
TYSM Dave ♥. May I ask why you're ejecting axios interceptors? Their documentation is also not very clear on this one. If we need an axios instance without those interceptors we can just use another instance other than axiosPrivate, right? So...?
Much like event listeners, if you do not remove the interceptors, they will begin to stack up. With interceptors, your requests will multiply. This will create unnecessary requests and unexpected behavior.
hey Dave just want to say this was a great tutorial, definitely has helped me alot to understand how to work with jwt and refresh tokens on the client side, can you do a tutorial on how to deploy with docker / kubernetes / enginx
Thank you and great request! Docker is definitely on my list 💯🚀
Thanks dave this was educative, I was having problems in implementing Auth on React.
Glad I could help!
Great course on react authentication. Thanks a lot. Exactly what needed.
Glad it was helpful! 💯
This is next level tutorial. Thanks @DaveGray for an awesome tutorial :)
Thank you for the kind words, Pravin! 💯
great tutorial Dave, really in-depth and easy to understand
Thank you!
Hi, Dave!
Whould you consider a good choice to move the "redirection to login page" from the users component to the useAxiosPrivate hook?
That is: in useAxiosPrivate.js,
1) add the required imports
import { useNavigate, useLocation } from "react-router-dom";
2) initalize
const navigate = useNavigate();
const location = useLocation();
3) replace the line
newAccessToken = await refresh();
with something like:
try {
newAccessToken = await refresh();
}
catch (err) {
console.log("Cannot refresh token: redirecting to login page.", err);
navigate('/login', { state: { from: location }, replace: true });
}
?
This should handle the redirection logic in a unique point in the application, avoiding to replicate it in every component.
Thanks!
I think that's a good thought! 💯 You lose some flexibility for redirects based on specific requests, but overall, this might be all that most need. 🚀
Another well made and greatly explained tutorial.
Thank you man. Awesome, best tutorial ever. Keep it up
Very informative! The best I have seen so far!
Glad to hear that! 💯
The best Auth tutorial ever!! appreciate all the references links too
You're welcome! 💯
there's something missing
how can use hooks useAxiosPrivate inside services library ( file contain only functions that call axios )
Best JWT Tutorial on YT 👍
Appreciate that!
I found a lot but this is the only video I've found on youtube with both access & refresh token used with proper purpose.
I have one query, what if we use RTK (not RTKQ) and want to use useAxiosPrivate hook inside createAysncThunk to send/fetch data from server. How can we place axiosPrivate in that case as we can't use custom hooks outside component ot any other custom hooks. Again, thanks a lot for this video.👍
I made a video that applies this to Redux, but it may not apply it in the way you described... nevertheless, you can check out how it works here: czcams.com/video/-JJFQ9bkUbo/video.html
Hello Dave Gray,
This tutorial was very helpful, it gave me a few ideas when working with access and refresh tokens, also learned a few new things too, I was able to work JWTs into a react app project I’m working on that relies on Passport.JS and Redis for authentication.
For anyone running the React and backend server on a different machine and accessing it from a browser on another machine. On the backend, you’ll need to remove “samesite” and set “secure” to false for the secure cookie within “handleRefreshToken” to be set in a browser. Secure will only work if everything is being accessed from the same machine or you are feeding an HTTPS cert with the request. Please correct me if I’m wrong because chrome and Brave under network had a very tiny yellow “!” error that was hard to find. No errors were showing under console from Chrome, Brave or FireFox.
You're welcome! 💯 Just to add to your note which I believe is accurate.. In production, you will always want to use HTTPS instead of HTTP and add secure: true back to the cookie.
Skylark, I have to say it... I fu***** love you. You've just solved the issue that I've not been able to solve in the last 24hs. I was just getting a 401 with the sameSite="none" configuration, I dig into the whole web until I got to your comment. THANKS.
Hi, where is the backend code?
Link to the Node JS course is in the description. It has a resources link in its description with source code for every chapter. You will want to grab the last chapter if you just want the code.
Insanity how good this is.
Wouldn't you want to put the controller outside the useEffect?
Exactly what I wanted ! Thanks
Great guide! almost feel like I need to rewrite all my code cause the tutorials I followed didn't cover half of what you did... but that will be for some other time cause I have other projects to finish x)
But thx for sharing your knowledge ow wise man!
You're welcome! 🙏🙏
Thank you Dave for everything, I have learned so much from you. 💙💙
Glad to help!
Great tutorial ! I finally pushed myself to learn React and tous helped me a lot, i improved so much. But there is one thing i can't wrap my head around: why having the short duration jwt in memory if we have one supposedly more exposed in cookie to generate other short duration jwt?
Thank you! 🙏 For these tutorials, I have extremely short token durations as examples. A more realistic duration for the access token is anywhere from 15 to 60 minutes (set to preference) and the refresh token often lasts a day or longer. There are links in the description to articles discussing this strategy, too.