You don't need passwords anymore! NestJS passwordless magic link authentication

Sdílet
Vložit
  • čas přidán 9. 07. 2024
  • In this tutorial video we take a look at the steps to implement passwordless authentication via magic links using NestJS and PassportJS.
    00:00 - Passwords are terrible
    01:15 - Project setup
    02:25 - Users Service
    03:40 - API design
    06:43 - passport-magic-login intro
    08:14 - Magic Login Strategy
    14:53 - Auth Service validate user
    17:10 - Complete login route and send magic links
    21:17 - Validate email pattern
    23:02 - Complete callback route
    27:35 - Generating JWT upon login
    30:59 - Protect routes with JWT check
    34:23 - Full authentication flow demo
    35:31 - A couple extra thoughts
    35:35 - Outro

Komentáře • 77

  • @BaoNguyen-lz4cb
    @BaoNguyen-lz4cb Před rokem +1

    I really enjoy your videos about NestJS. It's the best NestJS channel on CZcams 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!

    • @mariusespejo
      @mariusespejo  Před rokem +1

      Thank you! Glad you’re enjoying the content!

  • @dawid_dahl
    @dawid_dahl Před rokem

    Thank you so much for making these videos in Nest! 🤩

  • @MichelVersianiDev
    @MichelVersianiDev Před rokem

    Juust what I was looking for \o/ , thanks!

  • @abolfazljalildoost766

    Like always . The best!

  • @suvendusekharsahoo5739

    Best Tutorial ever !! 😍

  • @dawid_dahl
    @dawid_dahl Před rokem +5

    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.

    • @mariusespejo
      @mariusespejo  Před rokem +4

      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

    • @samuelvalentine7846
      @samuelvalentine7846 Před rokem

      ​@@mariusespejo 😅

  • @AnlGUNDAL
    @AnlGUNDAL Před 11 měsíci

    You'r super dude :)

  • @yhzh755
    @yhzh755 Před rokem +1

    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?

    • @mariusespejo
      @mariusespejo  Před rokem

      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

  • @TerryZeng
    @TerryZeng Před rokem

    Nice!

  • @reneheijdens8444
    @reneheijdens8444 Před rokem

    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.

    • @mariusespejo
      @mariusespejo  Před rokem +3

      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.

  • @abrahimzaman360
    @abrahimzaman360 Před rokem

    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?

    • @mariusespejo
      @mariusespejo  Před rokem +1

      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.

  • @Fragler01
    @Fragler01 Před 2 měsíci

    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!

    • @mariusespejo
      @mariusespejo  Před 2 měsíci

      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!

    • @Fragler01
      @Fragler01 Před 2 měsíci

      @@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 👋😊

  • @abrutii
    @abrutii Před rokem

    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 !

    • @abrutii
      @abrutii Před rokem

      Sorry for the spelling or whatever english mistakes I made wroting my request :|

  • @msrini
    @msrini Před rokem

    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

    • @mariusespejo
      @mariusespejo  Před rokem

      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

    • @msrini
      @msrini Před rokem

      @@mariusespejo I used that one. But when I try to use store method in session, it throws unable to find metadata for session repository

  • @wissendev5490
    @wissendev5490 Před rokem +2

    Can you provide a Github link to your tutorial projects ?

    • @mariusespejo
      @mariusespejo  Před rokem +1

      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.

  • @user-xx2zz5vp8g
    @user-xx2zz5vp8g Před rokem

    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

    • @mariusespejo
      @mariusespejo  Před rokem +1

      I don’t have one for it but if you check the docs it’s pretty straightforward

    • @user-xx2zz5vp8g
      @user-xx2zz5vp8g Před rokem

      @@mariusespejo thank you keeep going i like your content.

  • @moneebal-alfi8109
    @moneebal-alfi8109 Před rokem

    Sir, do you have a guide that shows me how to authentication with nestjs/graphql schema first ?

    • @mariusespejo
      @mariusespejo  Před rokem

      I do have a video on the channel for nest graphql auth but code first. But it’s mostly the same setup

    • @evandorezende1
      @evandorezende1 Před 10 měsíci

      @@mariusespejo the tricky part here is in handling the context req and res, it seems to require a different setup for this magic strategy.

  • @SachinYadav-hk7id
    @SachinYadav-hk7id Před 9 měsíci

    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.

    • @mariusespejo
      @mariusespejo  Před 9 měsíci +1

      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

  • @soulofjack7294
    @soulofjack7294 Před rokem

    how user will redirect to the web page after clicking to the magic link?

    • @mariusespejo
      @mariusespejo  Před rokem +1

      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

    • @soulofjack7294
      @soulofjack7294 Před rokem

      ​@@mariusespejo still not clear how to achieve this in csr web app,need to Google this.Thanks for pointing out!

    • @mariusespejo
      @mariusespejo  Před rokem +1

      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

  • @AjaySingh-jz8qx
    @AjaySingh-jz8qx Před 2 měsíci

    Please do a little frontend calls with nest js I am a beginner

  • @pelaoinfo
    @pelaoinfo Před rokem

    TypeError: res.json is not a function using fastify adapter :(

    • @mariusespejo
      @mariusespejo  Před rokem

      I don’t think passport is directly usable to fastify

  • @robokishan
    @robokishan Před rokem

    which terminal are you using ?

  • @marcelofernandez6561
    @marcelofernandez6561 Před rokem

    what about rate-limiting? you think its usefull?

    • @mariusespejo
      @mariusespejo  Před rokem +1

      Yeah totally, it would be good to prevent someone maliciously trying to trigger a login non-stop

    • @geebrox
      @geebrox Před rokem

      @@mariusespejo do you have any idea how to correctly implement it?

    • @mariusespejo
      @mariusespejo  Před rokem

      docs.nestjs.com/security/rate-limiting

  • @saurabhtalele1537
    @saurabhtalele1537 Před rokem

    Cool🎉🎉🎉🎉

  • @ajdinpipo08
    @ajdinpipo08 Před rokem +4

    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

    • @mariusespejo
      @mariusespejo  Před rokem

      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?

    • @milkdrom3da
      @milkdrom3da Před rokem +8

      @@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

    • @progressnwimuelekara2167
      @progressnwimuelekara2167 Před 8 měsíci +1

      ​@@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.

    • @mattsullivan9220
      @mattsullivan9220 Před 5 měsíci

      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.

  • @codearmadillo
    @codearmadillo Před 10 měsíci

    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.

  • @cubedev4838
    @cubedev4838 Před rokem

    Please make clone series with long hours videos 7+ hours. Nestjs, prisma, all your stack...

  • @permanar_
    @permanar_ Před rokem

    Hey, how about you make a video regarding creating advance custom decorators? 🔥🔥🔥

    • @mariusespejo
      @mariusespejo  Před rokem

      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

  • @SakibJaber
    @SakibJaber Před rokem

    Please make a video about complete authentication and authorization with casl and nestjs 🙏🙏

    • @mariusespejo
      @mariusespejo  Před rokem

      I have, in the channel

    • @SakibJaber
      @SakibJaber Před rokem

      @@mariusespejo yes i know that but It's not combined.

    • @mariusespejo
      @mariusespejo  Před rokem

      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

    • @mariusespejo
      @mariusespejo  Před rokem

      I’ll think about making a combined video but that’s honestly the gist of it

  • @mynameisjeff8559
    @mynameisjeff8559 Před rokem

    Thirdd!!!

  • @stubertv7088
    @stubertv7088 Před rokem

    Firssttttt❤❤

  • @abdulrahmanelheyb
    @abdulrahmanelheyb Před rokem

    The magic is actually sending the login URL to email with a token and no password, that's all

    • @mariusespejo
      @mariusespejo  Před rokem

      ‘Magic’ is just the term often used for login links, yes there’s really not much to it

  • @cruz7047
    @cruz7047 Před rokem

    *promosm*

  • @neerosity
    @neerosity Před rokem

    so, if anyone knows your email they can get jwt token ?

    • @mariusespejo
      @mariusespejo  Před rokem

      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

  • @TheWalrus_45
    @TheWalrus_45 Před rokem

    What's up Marius, have you tried implementing WebAuthn in NestJS yet?

    • @mariusespejo
      @mariusespejo  Před rokem

      I have not! But I’d like to learn more about it soon. Passwordless via biometrics on your phone would really cool