I really enjoy your videos about NestJS. It's the best NestJS channel on TH-cam that I know of. I have subscribed and supported you, and I'm looking forward to more advanced videos about NestJS from you. I'm always excited for your upcoming NestJS videos!
I do have a video on doing tests with Nest, the fundamentals from that should generally be applicable to most things. E.g. you could set up a test which mocks the service you use to send emails and asserts that calling POST /auth/login ultimately calls your mock email service with a generated url with an expected pattern. Or a test that calls your callback with a valid/invalid/expired token, assert your expected response. But yeah to your point maybe I could take a more TDD approach to these videos, I’ll think about that more
Very useful tutorial. I'm more interested in making the API multi-tenant, is there a best practice to do that? More specifically, I would like to get tenants' context from db and attach it to different user request. I found that I could use a REQUEST scoped provider to store the context or use the nest-cls module, but I couldn't find a tutorial on this topic. What do you think the best way to do?
Probably the big thing is having a solid authorization solution in place, so that you can logically separate what your different tenants can/can’t do. Take a look at some of my CASL videos
Thank you for your video and it's very useful, I have implemented the way you did and it's working fine, I want to know is there any way to capture the expired token in a separate callback because right now it's showing unauthorised in the browser, instead of this default message, I just want to implement custom UI design to show token has expired.
Most of my content are really meant to be video lessons, not a project to be cloned. There are already a bunch of written docs for most of this stuff if you’re just looking for a written reference. If you absolutely need a copy of the code you could just watch and follow along, you might find a lot more value from that than just getting a dump of the end result.
Why use a separate guard when you can use the refresh token? I have implemented a similar use-case by reusing the refresh token to get a new token pair. The refresh token sent via email has a shorter expiration time for safety. I always try to keep the number of external dependencies and libraries as short as possible, so it would prevent the use of the magic-link library.
You’re really asking why use a passport strategy: because it allows you to easily swap auth strategies while keeping the APIs mostly consistent. If you look at the implementation of the magic link strategy/library, it’s literally like just a handful of lines of code. Yes you totally could just implement that yourself, but not everyone needs to re-implement everything. Are you also going to re-implement Nest itself and all the other libraries you’re using? The answer right is “it depends”. Use your judgement, it’s not that black and white. Libraries allow external management, it’s improved by the community. It’s code you don’t have to maintain.
My question is, why use passport magic links, when we can implement the same logic by ourselves? All it is doing, is sending emails with a url that has JWT token in it. Also send email logic is something that we have to write ourselves anyway. If we use passport magic links, we have to write more code as opposed to the custom approach.
I agree this specific implementation is fundamentally simple to implement from scratch, does it always make sense to do so? It depends on your needs. Not everything needs re-invention
Hi Marius! Thanks for this awesome video, it helped me a lot! I have a question though: in your process, you send an email with a JWT token to the user, which then calls the callback URL, which then generates a new JWT token, that lasts longer. Why can’t we simply use the token that we get from the Magic Login Strategy to guard the endpoints and also to use on the frontend as a bearer? Keep up the good work! Your videos provide so much value, containing very useful information for production redy work!
Good question. There is no reason why you can’t do that, you totally could. However in my opinion it’s safer to make sure that magic links are short-lived and can naturally expire, because emails can be intercepted in some situations or easily forwarded, in general email is not always a secure protocol. That link could be sitting in an email server in plain text. Also anything in the url can also be saved in browser cache or browser history. What if you logout and the jwt is not yet expired and someone finds your login link from history, e.g. on a shared computer or any environment where your network traffic can be intercepted like at work. You reduce a lot of the risks by making sure the link in general is short-lived and ideally only usable once. Hope that helps and thanks for stopping by to comment!
@@mariusespejo Thanks a lot for your answer. It totally makes sense what you write, and I completley aggree. I actually implemented this method, the same way you did it in this video, and this was just a thought that I kept wondering about. I would also have another question if you don't mind answering it 😊 Is there any way of checking whether a JWT already exists for a user or not? I was thinking, maybe I could check if a user already requested a login link, and if so, why generate a new one, when I could simply send them the one that was already generated. On the same not, would it be possible to manually expire the JWT ( for instance, after they logged in, destoying the login token, until they request a new one ). I have been playing around with these kinds of thoughts, but could not really find anything related to in the documentations of Passport. Thanks again for the answer and for the awesome content you make 👋😊
Have you thought about using a library like express-session? That can be setup to work with passport. You can also configure the underlying storage, e.g. database in your case
35:31 some notes at the end that covers that, basically you can make the magic link point to your client instead and have your client make the GET request to the /callback
As an example, let’s say your CSR app is being served up by an express/nest server using the same passport strategies. In the /login/callback route handler once you have the jwt or created a user session, then you can do res.redirect(“/your-client-home-page”); If your client server however is trying to login to a different API that has this auth strategy, you would then need to update the magic login callback url setting so that the link instead takes you to your client’s server. Your client’s server would then need take the token from the url query and it would basically need to make the callback request to the API on behalf of the user This is all assuming your CSR still has some kind of server that serves up that index.html, it’s a little more complex to do auth without one because you typically wouldn’t want to just expose your access tokens to the public frontend. Anyways, probably hard to understand from just a comment but hope it helps
Hey Marcus, I've been following your tutorials and so for a long time and always wondered if you could make one on Google OAuth2 connection but not only on the back-end side. Many tutorials either do only front-end or back-end. Implementing it on both side meaning that your front-end would call the back-end that do the oauth2 logic would be very cool !
Sidenote - Not a bad idea to still return 200 OK if user does not exist. Simple obfuscation so malicious user cannot just randomly attempt to "login" and discover if emails are registered.
There’s really not much more code to look at than what was written in this video, which isn’t that much code to begin with. I also try my best to walk through it step by step. What else is there to analyze?
@@mariusespejo he's right. You make amazing content. Sometimes its just easier to step away from the video and analyze the source code to get more insight.
I also agree with providing source code. I'm encountering an issue where my code is not throwing the 401. I have to scrub through the video to check my code ... which is extremely painful. Great video, but it would be very helpful to have a link to the source code.
Custom decorators are really mostly for providing meta data, there’s not much more advanced stuff for that. And I do show how to create custom decorators in most of my auth videos
There’s not much to combine, don’t over think it. One you solve auth, then you should have a user in each request which you can pass to casl to build the abilities
It’s not the simple. It’s sent to the email inbox of the owner of the email. If you know their email you can trigger a login request for them but to actually login you need the link, you need access to the inbox itself
I really enjoy your videos about NestJS. It's the best NestJS channel on TH-cam that I know of. I have subscribed and supported you, and I'm looking forward to more advanced videos about NestJS from you. I'm always excited for your upcoming NestJS videos!
Thank you! Glad you’re enjoying the content!
It would be so amazing if you did tests for these more advanced topics as well. That is something I want to learn more about.
I do have a video on doing tests with Nest, the fundamentals from that should generally be applicable to most things. E.g. you could set up a test which mocks the service you use to send emails and asserts that calling POST /auth/login ultimately calls your mock email service with a generated url with an expected pattern. Or a test that calls your callback with a valid/invalid/expired token, assert your expected response.
But yeah to your point maybe I could take a more TDD approach to these videos, I’ll think about that more
@@mariusespejo 😅
Thank you so much for making these videos in Nest! 🤩
Best Tutorial ever !! 😍
Like always . The best!
Very useful tutorial. I'm more interested in making the API multi-tenant, is there a best practice to do that? More specifically, I would like to get tenants' context from db and attach it to different user request. I found that I could use a REQUEST scoped provider to store the context or use the nest-cls module, but I couldn't find a tutorial on this topic. What do you think the best way to do?
Probably the big thing is having a solid authorization solution in place, so that you can logically separate what your different tenants can/can’t do. Take a look at some of my CASL videos
Thank you for your video and it's very useful, I have implemented the way you did and it's working fine, I want to know is there any way to capture the expired token in a separate callback because right now it's showing unauthorised in the browser, instead of this default message, I just want to implement custom UI design to show token has expired.
Can you provide a Github link to your tutorial projects ?
Most of my content are really meant to be video lessons, not a project to be cloned. There are already a bunch of written docs for most of this stuff if you’re just looking for a written reference. If you absolutely need a copy of the code you could just watch and follow along, you might find a lot more value from that than just getting a dump of the end result.
Juust what I was looking for \o/ , thanks!
Why use a separate guard when you can use the refresh token? I have implemented a similar use-case by reusing the refresh token to get a new token pair. The refresh token sent via email has a shorter expiration time for safety.
I always try to keep the number of external dependencies and libraries as short as possible, so it would prevent the use of the magic-link library.
You’re really asking why use a passport strategy: because it allows you to easily swap auth strategies while keeping the APIs mostly consistent. If you look at the implementation of the magic link strategy/library, it’s literally like just a handful of lines of code. Yes you totally could just implement that yourself, but not everyone needs to re-implement everything. Are you also going to re-implement Nest itself and all the other libraries you’re using? The answer right is “it depends”. Use your judgement, it’s not that black and white. Libraries allow external management, it’s improved by the community. It’s code you don’t have to maintain.
My question is, why use passport magic links, when we can implement the same logic by ourselves? All it is doing, is sending emails with a url that has JWT token in it. Also send email logic is something that we have to write ourselves anyway.
If we use passport magic links, we have to write more code as opposed to the custom approach.
I agree this specific implementation is fundamentally simple to implement from scratch, does it always make sense to do so? It depends on your needs. Not everything needs re-invention
Hi Marius! Thanks for this awesome video, it helped me a lot! I have a question though: in your process, you send an email with a JWT token to the user, which then calls the callback URL, which then generates a new JWT token, that lasts longer. Why can’t we simply use the token that we get from the Magic Login Strategy to guard the endpoints and also to use on the frontend as a bearer?
Keep up the good work! Your videos provide so much value, containing very useful information for production redy work!
Good question. There is no reason why you can’t do that, you totally could. However in my opinion it’s safer to make sure that magic links are short-lived and can naturally expire, because emails can be intercepted in some situations or easily forwarded, in general email is not always a secure protocol. That link could be sitting in an email server in plain text. Also anything in the url can also be saved in browser cache or browser history. What if you logout and the jwt is not yet expired and someone finds your login link from history, e.g. on a shared computer or any environment where your network traffic can be intercepted like at work. You reduce a lot of the risks by making sure the link in general is short-lived and ideally only usable once.
Hope that helps and thanks for stopping by to comment!
@@mariusespejo Thanks a lot for your answer. It totally makes sense what you write, and I completley aggree. I actually implemented this method, the same way you did it in this video, and this was just a thought that I kept wondering about. I would also have another question if you don't mind answering it 😊 Is there any way of checking whether a JWT already exists for a user or not? I was thinking, maybe I could check if a user already requested a login link, and if so, why generate a new one, when I could simply send them the one that was already generated. On the same not, would it be possible to manually expire the JWT ( for instance, after they logged in, destoying the login token, until they request a new one ). I have been playing around with these kinds of thoughts, but could not really find anything related to in the documentations of Passport. Thanks again for the answer and for the awesome content you make 👋😊
TypeError: res.json is not a function using fastify adapter :(
I don’t think passport is directly usable to fastify
hi marius thank you for the content you are sharing please is there any video about the config service of nest js and how to implement it. thanks
I don’t have one for it but if you check the docs it’s pretty straightforward
@@mariusespejo thank you keeep going i like your content.
What's up Marius, have you tried implementing WebAuthn in NestJS yet?
I have not! But I’d like to learn more about it soon. Passwordless via biometrics on your phone would really cool
Sir, do you have a guide that shows me how to authentication with nestjs/graphql schema first ?
I do have a video on the channel for nest graphql auth but code first. But it’s mostly the same setup
@@mariusespejo the tricky part here is in handling the context req and res, it seems to require a different setup for this magic strategy.
Hi can you please help me in storing the session id to postgres db using typeorm? Unable to do that due to some deprecated methods
Have you thought about using a library like express-session? That can be setup to work with passport. You can also configure the underlying storage, e.g. database in your case
@@mariusespejo I used that one. But when I try to use store method in session, it throws unable to find metadata for session repository
what does next js offer over react i don't understand what are server and client side props and components. is it just rendering strategy or what?
This is a nest video not next just fyi don’t get those mixed up. Next offers a lot of things though like server-side rendering, ssg, etc.
how user will redirect to the web page after clicking to the magic link?
35:31 some notes at the end that covers that, basically you can make the magic link point to your client instead and have your client make the GET request to the /callback
@@mariusespejo still not clear how to achieve this in csr web app,need to Google this.Thanks for pointing out!
As an example, let’s say your CSR app is being served up by an express/nest server using the same passport strategies. In the /login/callback route handler once you have the jwt or created a user session, then you can do res.redirect(“/your-client-home-page”);
If your client server however is trying to login to a different API that has this auth strategy, you would then need to update the magic login callback url setting so that the link instead takes you to your client’s server. Your client’s server would then need take the token from the url query and it would basically need to make the callback request to the API on behalf of the user
This is all assuming your CSR still has some kind of server that serves up that index.html, it’s a little more complex to do auth without one because you typically wouldn’t want to just expose your access tokens to the public frontend.
Anyways, probably hard to understand from just a comment but hope it helps
Please do a little frontend calls with nest js I am a beginner
what about rate-limiting? you think its usefull?
Yeah totally, it would be good to prevent someone maliciously trying to trigger a login non-stop
@@mariusespejo do you have any idea how to correctly implement it?
docs.nestjs.com/security/rate-limiting
which terminal are you using ?
Warp, it’s pretty cool!
Hey Marcus, I've been following your tutorials and so for a long time and always wondered if you could make one on Google OAuth2 connection but not only on the back-end side. Many tutorials either do only front-end or back-end. Implementing it on both side meaning that your front-end would call the back-end that do the oauth2 logic would be very cool !
Sorry for the spelling or whatever english mistakes I made wroting my request :|
Sidenote - Not a bad idea to still return 200 OK if user does not exist. Simple obfuscation so malicious user cannot just randomly attempt to "login" and discover if emails are registered.
Totally! Good idea
I have only one question. Your tutorials are really amazing, but why dont you share a source code with us ? We need to analyze it more :D
There’s really not much more code to look at than what was written in this video, which isn’t that much code to begin with. I also try my best to walk through it step by step. What else is there to analyze?
@@mariusespejo I would say it'd be nice to be able to reference the code and see it in its entirety without having to go through the video again
@@mariusespejo he's right. You make amazing content. Sometimes its just easier to step away from the video and analyze the source code to get more insight.
I also agree with providing source code. I'm encountering an issue where my code is not throwing the 401. I have to scrub through the video to check my code ... which is extremely painful. Great video, but it would be very helpful to have a link to the source code.
Hey, how about you make a video regarding creating advance custom decorators? 🔥🔥🔥
Custom decorators are really mostly for providing meta data, there’s not much more advanced stuff for that. And I do show how to create custom decorators in most of my auth videos
Please make a video about complete authentication and authorization with casl and nestjs 🙏🙏
I have, in the channel
@@mariusespejo yes i know that but It's not combined.
There’s not much to combine, don’t over think it. One you solve auth, then you should have a user in each request which you can pass to casl to build the abilities
I’ll think about making a combined video but that’s honestly the gist of it
You'r super dude :)
Cool🎉🎉🎉🎉
Nice!
Please make clone series with long hours videos 7+ hours. Nestjs, prisma, all your stack...
Firssttttt❤❤
🥇😄
The magic is actually sending the login URL to email with a token and no password, that's all
‘Magic’ is just the term often used for login links, yes there’s really not much to it
Thirdd!!!
🥉💪
*promosm*
so, if anyone knows your email they can get jwt token ?
It’s not the simple. It’s sent to the email inbox of the owner of the email. If you know their email you can trigger a login request for them but to actually login you need the link, you need access to the inbox itself