THANK YOU! Unlike the official documentation of jwt-passport and passport (which fails miserably to explain the basics) , This is the best and the only JWT with passport that explains the basic concepts in a clear and in an understandable way. Cheers man!
@@zachgoll Oh, that's too bad... And I agree this should be featured as an official guide, so that newcomers (like me) get to understand everything right off the bat and not end up reading the source code of their package to understand what each part of their API do. (like I did right before I found this video) Anyways, thanks man for this video !
Hey Zack, Thanks so much for your dedication and methodical approach, it`s muchly appreciated. I have lost count of how many times i have replayed this so i GET IT!. Cheers!
explains the stuff to a great depth..thanx for the tut.........please make more tutorials on other topics too. Really appreciate your methodology of teaching
Its a great video you explain everything in simplified. Now my question is what thing we include in JWT Token I see people include user_id, user_name, user_group. Idea is once it get decoded you get user_group no need a database query for isAdmin kind of thing. Is it a good practice or bad. From security point of view what's your opinion ?
Thanks, Zach. This was helpful. Could you explain how we are supposed to invalidate the jwt when a user logs out? With the local strategy, simply calling req.logout would have been helpful. Is there the same logout feature that passport-jwt provides?
I read somewhere that the benefit of using JWT over the usual saving token in DB is we don't have to lookup in the database every time a request comes. But in your case, we are actually searching for users every time in the middleware function. This seems kinda wrong.
I think, you are trying to compare the usual session based authentication to the JWT one. The session based one does not use tokens, but session-cookies. When you log in to a website, your session ID and encrypted user data is stored on the server in a session store, typically on the database. The server issues the session-cookie and sends it with the response, then the browser stores it and sends it back to the server with the subsequent requests. The code, which maintain the session is in the express-session library, we do not touch it. We only look for the user data once in the database, when the user logs in. When the browser sends the username and the password, the local-strategy runs the function, which we write to look up the user in the database and decide if the credentials were OK.If the user logs in the session gets established and maintained by the browser and the server. It lasts until the user logs out. In the case of JWT, you normally can store all the user data, apart from the password or the password hash in the token. If you do this, you don't need to look up the database for the user data, because you get it with the token with every request. The user is simply logged in when the request contains the token and the server can get the user data from the token. There is a small problem though with JWTs. They are not encrypted, so anybody can read the user information from them. This is why you should never store passwords in them. Zach's solution is more secure, because he only stores the user ID in the token as user data. Although he needs to look up the user id in the database every time, it's more secure and it's a small price to pay for the added security.
Hi Zak. Actually best tutorials about passport i have ever seen. I hope you can add 3rd party login as well. Anyway why you do not store KEYS in .env file? Do you have any reason?
I think the private key should be stored in the .env file in the case of a real world application. You could leave the public key public. This app is just a demonstration and Zach might have wanted you to see clearly, what's going on, so he left both keys in the root directory of the app. There is another thing you should do for a real world app. You should set up the cors middleware to give access to your API only from the origin of your front-end app. To give access to your API from any origin is OK meanwhile you are developing, but it is very insecure in your production app.
Thanks for the useful tutorial. I have a question here. We are using two packages passport_jwt and jsonwebtoken. And as you mentioned that we are using the passport_jwt in one place just for protecting routes. So my question is the following, What is the purpose of using passort_jwt since we are able to decode the token using jsonwebtoken instead of using two packages? Thanks in advanced!
It's easy to answer. We could do it ourselves, but we don't have to do, because another programmer has already done it. This is the guy, who wrote the passport-jwt strategy for us. All we need to do is to check the docs, how we should use passport-jwt or even better just to watch Zach's tutorial. This is a bit easier than writing it yourself, although you can do it as Zach explains it in his previous video as an introduction.
You can write a custom middleware to check for a role property on the user. This passport series has a video on express middleware that I think might help!
When issuing the token, I think "iat" should be set in SECONDS, not MILLISECONDS. Otherwise, "jsonwebtoken" package will calculate the expiration date incorrectly. Thanks a lot for the video, it was extremely helpful~
I am just guessing, but Zach can correct me if I was wrong. I would say if the token is only used by your app, symmetric cryptography would do just fine. On the other hand you could use the same token to authenticate with different apps. In that case you have to use asymmetric cryptography. It might be the way how more difficult authentication workflows work under the hood, but that's longer learning for me too.
Awesome Zach! Thank you very much. I did things slightly different, mainly by using es6 await and typescript but other than that i followed you along and was able to get it set up fine. Question: what would you recommend for role based auth, custom middleware? Or is this something that can be handled by passport, thanks!
If you’re already using Typescript, I recommend the NestJS framework. It is a framework built on top of Express and has the concept of role based authentication built in with simple class decorators. You of course could build this as a middleware in Express, but I really have enjoyed working in NestJS for my projects!
Thanks for the great tutorial. I've been (successfully) using tutorials on how to use passport from others. What this tutorial taught me why things work if I do things in a certain way. So to say I've been doing things without understanding what was going on under the hood. Great work indeed. Do you think you could extend this video series with google/facebook/github authentication? I mean that component from passport, that allows to access the resource, if one is logged into google or smth. Would be very helpful.
He wanted an authentication workflow, where the registered user has been logged in without visiting the /users/login route. For doing this, he needed to issue the JWT at the registration as well. Whenever the front-end app has the JWT, the user is logged in as long as the token is not expired.
You probably want to add some conditional logic whether the date is less than or equal to the expiry time in the config passport.js User.findOne({ _id: payload.sub}).then((user) => { if (user) {
I get this error MongooseError [MissingSchemaError]: Schema hasn't been registered for model "User". Use mongoose.model(name, schema) when trying to use the model with the syntax const User = require('mongoose').model('User'); How I usually export models is module.exports = new mongoose.model("User", userSchema) and I receive it as const User = require('../models/user') I haven't seen this syntax that you're using. Perhaps I'm missing something?
Which portion of the video are you referring to? I would be glad to take a look. I believe I do register my models as you describe in the '/config' folder - github.com/zachgoll/express-session-authentication-starter/blob/final/config/database.js
@@zachgoll I'm sorry. I was doing a mongoose.connect instead of a mongoose.createConnection. After I changed the mongoose method, it worked! I just exported the connection and imported them as connection.models.User as you did! Thank you!
Hi guys. Do you like clean code? Do you like well engineered code, which is superb readable? This is the tutorial to follow about passport user authentication with JWT. When I was doing the simple session based authentication with the passport local strategy, I followed different tutorials, where everything regarding authentication was in the app.js file. I was wondering how I could put all that stuff in a different module and I did not know. I just left everything in app.js, because that app is all about authentication. Now I am watching Zach and he just shows me, how I could have done it. Do you know, which method, he is using in the video, to decouple all that stuff, he puts in the passport.js file? This in OOP is called 'dependancy injection'. It's just a fancy term for that well known way, he passes the passport middleware to the passport.js file as a parameter in the function. Although it's not OOP, what he is doing here, just a simple modular design, he uses this well known OOP way to do it. By the way dependency injection is used to get rid off name dependencies in OOP code. Here he could call the passport.js file like auth.js and the passport parameter in that file like authMiddleware for example. Even with these name changes, his code would be working, because he has already got rid off the name dependency. This is how well engineered Zach's code sample is. Zach it's just unbelievable. I think your coding style is strongly influenced by Angular. Never mind, Angular is well engineered, although I don't like it. What I like is your coding style. It cannot be cleaner, just incredible.
2 Years down the line and it's still a valuable tutorial; thank you for the good content, I found it very helpful
Man, this is the BEST tutorial explaining Jwts with passport!
THANK YOU!
Unlike the official documentation of jwt-passport and passport (which fails miserably to explain the basics) , This is the best and the only JWT with passport that explains the basic concepts in a clear and in an understandable way.
Cheers man!
I’ve been trying to get the developer of passport js to link to this video series, but to no avail 😆
@@zachgoll Oh, that's too bad...
And I agree this should be featured as an official guide, so that newcomers (like me) get to understand everything right off the bat and not end up reading the source code of their package to understand what each part of their API do. (like I did right before I found this video)
Anyways, thanks man for this video !
Hey Zack, Thanks so much for your dedication and methodical approach, it`s muchly appreciated. I have lost count of how many times i have replayed this so i GET IT!.
Cheers!
after 3 years, still the best tutorial on how to do that
this video has cleared so many confusions about how passport work. Thanks a lot Zach Gollwitzer
You deserve waay more subs man. Awesome job! Keep it up. Subscribed!
Very great tutorial. Love the way you break down the small stuff throughout the series as well.
explains the stuff to a great depth..thanx for the tut.........please make more tutorials on other topics too. Really appreciate your methodology of teaching
One of the most lucid videos!
Great series, great content. Thank you Zach.
Best wishes for you.
thanks you so much. went through lot of tutorials and couldnt get my authentication working. now it works fine.
So extremely grateful for this tutorial series! 🙏🏻
wow this is such a great video. thank you so much for all your efforts. i am hugely benefiting from it.
Thank you so much for this series. really helpful.!!!!
Hi, great course. much appreciated! Your approach is lighthouse to me.
Really love this tutorial and the way you're teaching. Auto sub! 👍
your explanations are so good, man. nice job
Really well explained and structured tutorial. Keep it up!
Amazing series, thank you!
A dedicated video touching on the different algorithms (like rs256) would be awesome!
Will keep that in mind for future videos 👍
@@zachgoll Thank you!
22:54 Isn't it supposed to have a very short lifespan, with it constantly being refreshed?
Awesome video, really well explained!
Helped clarify the JWT strategy, as the docs are not so easy to follow. Thanks.
Its a great video you explain everything in simplified. Now my question is what thing we include in JWT Token I see people include user_id, user_name, user_group. Idea is once it get decoded you get user_group no need a database query for isAdmin kind of thing. Is it a good practice or bad. From security point of view what's your opinion ?
I'm definitely no security expert, but my rule of thumb is to never put information that you want to keep private in a JWT like this
Thanks, Zach. This was helpful. Could you explain how we are supposed to invalidate the jwt when a user logs out? With the local strategy, simply calling req.logout would have been helpful. Is there the same logout feature that passport-jwt provides?
THANK YOU!!. no way to submit info easier)
Thank you! what is the exact reason you did not use local strategy for the login part?
Really helpful video. Thank you, man!
Thank you, Zach it helped me a lot
I read somewhere that the benefit of using JWT over the usual saving token in DB is we don't have to lookup in the database every time a request comes. But in your case, we are actually searching for users every time in the middleware function. This seems kinda wrong.
I think, you are trying to compare the usual session based authentication to the JWT one. The session based one does not use tokens, but session-cookies. When you log in to a website, your session ID and encrypted user data is stored on the server in a session store, typically on the database. The server issues the session-cookie and sends it with the response, then the browser stores it and sends it back to the server with the subsequent requests. The code, which maintain the session is in the express-session library, we do not touch it. We only look for the user data once in the database, when the user logs in. When the browser sends the username and the password, the local-strategy runs the function, which we write to look up the user in the database and decide if the credentials were OK.If the user logs in the session gets established and maintained by the browser and the server. It lasts until the user logs out. In the case of JWT, you normally can store all the user data, apart from the password or the password hash in the token. If you do this, you don't need to look up the database for the user data, because you get it with the token with every request. The user is simply logged in when the request contains the token and the server can get the user data from the token. There is a small problem though with JWTs. They are not encrypted, so anybody can read the user information from them. This is why you should never store passwords in them. Zach's solution is more secure, because he only stores the user ID in the token as user data. Although he needs to look up the user id in the database every time, it's more secure and it's a small price to pay for the added security.
thaaannks a lot !!! your videos are amazing
Hi Zak. Actually best tutorials about passport i have ever seen.
I hope you can add 3rd party login as well.
Anyway why you do not store KEYS in .env file? Do you have any reason?
I think the private key should be stored in the .env file in the case of a real world application. You could leave the public key public. This app is just a demonstration and Zach might have wanted you to see clearly, what's going on, so he left both keys in the root directory of the app. There is another thing you should do for a real world app. You should set up the cors middleware to give access to your API only from the origin of your front-end app. To give access to your API from any origin is OK meanwhile you are developing, but it is very insecure in your production app.
Thanks for the useful tutorial. I have a question here. We are using two packages passport_jwt and jsonwebtoken. And as you mentioned that we are using the passport_jwt in one place just for protecting routes. So my question is the following, What is the purpose of using passort_jwt since we are able to decode the token using jsonwebtoken instead of using two packages? Thanks in advanced!
It's easy to answer. We could do it ourselves, but we don't have to do, because another programmer has already done it. This is the guy, who wrote the passport-jwt strategy for us. All we need to do is to check the docs, how we should use passport-jwt or even better just to watch Zach's tutorial. This is a bit easier than writing it yourself, although you can do it as Zach explains it in his previous video as an introduction.
great job mate!
Duuuude, you saved me here ! Thx !
I got a problem... the expires in is not validating! Do i need to validate the token expiration?
How to protect routes for different roles? For example, Admin and Customer roles.
You can write a custom middleware to check for a role property on the user. This passport series has a video on express middleware that I think might help!
Thanks, I will try it out
When issuing the token, I think "iat" should be set in SECONDS, not MILLISECONDS. Otherwise, "jsonwebtoken" package will calculate the expiration date incorrectly.
Thanks a lot for the video, it was extremely helpful~
saved my day thank you so much
amazing mate!
One question though Zach, as this authentication only occurs within our own application, why bother using asymmetric instead of symmetric?
I am just guessing, but Zach can correct me if I was wrong. I would say if the token is only used by your app, symmetric cryptography would do just fine. On the other hand you could use the same token to authenticate with different apps. In that case you have to use asymmetric cryptography. It might be the way how more difficult authentication workflows work under the hood, but that's longer learning for me too.
Hello Zach, great tutorial, thanks for your effort, i was wondering if you can create also an example with passport sam2 using ADFS, many thanks
what about the Refresh Token concept ?
Awesome Zach! Thank you very much. I did things slightly different, mainly by using es6 await and typescript but other than that i followed you along and was able to get it set up fine. Question: what would you recommend for role based auth, custom middleware? Or is this something that can be handled by passport, thanks!
If you’re already using Typescript, I recommend the NestJS framework. It is a framework built on top of Express and has the concept of role based authentication built in with simple class decorators. You of course could build this as a middleware in Express, but I really have enjoyed working in NestJS for my projects!
Is it secure that it returns hash in response? I might be wrong but if not this salt then it wouldn't be secure
Thanks for the great tutorial. I've been (successfully) using tutorials on how to use passport from others. What this tutorial taught me why things work if I do things in a certain way. So to say I've been doing things without understanding what was going on under the hood. Great work indeed.
Do you think you could extend this video series with google/facebook/github authentication? I mean that component from passport, that allows to access the resource, if one is logged into google or smth. Would be very helpful.
One doubt -What is advantage to issue jwt in register route ?
He wanted an authentication workflow, where the registered user has been logged in without visiting the /users/login route. For doing this, he needed to issue the JWT at the registration as well. Whenever the front-end app has the JWT, the user is logged in as long as the token is not expired.
Hey! Love the series. However, Token doesn't seem to expire when iat: Date.now()
You probably want to add some conditional logic whether the date is less than or equal to the expiry time in the config passport.js
User.findOne({ _id: payload.sub}).then((user) => {
if (user) {
if(Date.now() done(err, null));
great tutorial
golden contents please do make videos on mern stack
I get this error
MongooseError [MissingSchemaError]: Schema hasn't been registered for model "User".
Use mongoose.model(name, schema)
when trying to use the model with the syntax
const User = require('mongoose').model('User');
How I usually export models is
module.exports = new mongoose.model("User", userSchema)
and I receive it as
const User = require('../models/user')
I haven't seen this syntax that you're using. Perhaps I'm missing something?
Which portion of the video are you referring to? I would be glad to take a look. I believe I do register my models as you describe in the '/config' folder - github.com/zachgoll/express-session-authentication-starter/blob/final/config/database.js
@@zachgoll I'm sorry. I was doing a mongoose.connect instead of a mongoose.createConnection. After I changed the mongoose method, it worked! I just exported the connection and imported them as connection.models.User as you did! Thank you!
Well done
thanks for ur info
I feel like passportjs doesn't add much to the equation
13:18
Hey Zach, in your profile pic you look 40+ but in videos you look twenties... so you might want to change that :D
😍😍😍
You forgot to update it on github
Hi guys. Do you like clean code? Do you like well engineered code, which is superb readable? This is the tutorial to follow about passport user authentication with JWT. When I was doing the simple session based authentication with the passport local strategy, I followed different tutorials, where everything regarding authentication was in the app.js file. I was wondering how I could put all that stuff in a different module and I did not know. I just left everything in app.js, because that app is all about authentication. Now I am watching Zach and he just shows me, how I could have done it. Do you know, which method, he is using in the video, to decouple all that stuff, he puts in the passport.js file? This in OOP is called 'dependancy injection'. It's just a fancy term for that well known way, he passes the passport middleware to the passport.js file as a parameter in the function. Although it's not OOP, what he is doing here, just a simple modular design, he uses this well known OOP way to do it. By the way dependency injection is used to get rid off name dependencies in OOP code. Here he could call the passport.js file like auth.js and the passport parameter in that file like authMiddleware for example. Even with these name changes, his code would be working, because he has already got rid off the name dependency. This is how well engineered Zach's code sample is. Zach it's just unbelievable. I think your coding style is strongly influenced by Angular. Never mind, Angular is well engineered, although I don't like it. What I like is your coding style. It cannot be cleaner, just incredible.
Extremely grateful for this tutorial series! 🙏🏻