• Stars
    star
    664
  • Rank 67,903 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 4 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Passwordless authentication with magic links for Passport.js.

passport-magic-login

Passwordless authentication with magic links for Passport.js 🔑

  • User signup and login without passwords
  • Supports magic links sent via email, SMS or any other method you prefer
  • User interface agnostic: all you need is an input and a confirmation screen
  • Handles secure token generation, expiration and confirmation

Originally implemented by Tobias Lins for Splitbee and eventually extracted for Feedback Fish:

Screenshot 2021-01-09 at 16 55 23 Screenshot 2021-01-09 at 16 55 28 Screenshot 2021-01-09 at 16 56 24

Usage

To use magic link authentication, you have to:

  1. Setup the Passport strategy and Express routes on your server
  2. POST a request with the users email or phone number from the client once they have entered it into the login input

Installation

npm install passport-magic-login

Frontend usage

This is what the usage from the frontend looks like once you've set it all up. It only requires a single request:

// POST a request with the users email or phone number to the server
fetch(`/auth/magiclogin`, {
  method: `POST`,
  body: JSON.stringify({
    // `destination` is required.
    destination: email,
    // However, you can POST anything in your payload and it will show up in your verify() method
    name: name,
  }),
  headers: { 'Content-Type': 'application/json' }
})
  .then(res => res.json())
  .then(json => {
    if (json.success) {
      // The request successfully completed and the email to the user with the
      // magic login link was sent!
      // You can now prompt the user to click on the link in their email
      // We recommend you display json.code in the UI (!) so the user can verify
      // that they're clicking on the link for their _current_ login attempt
      document.body.innerText = json.code
    }
  })

Backend setup

To make this work so easily, you first need to setup passport-magic-login:

import MagicLoginStrategy from "passport-magic-login"

// IMPORTANT: ALL OPTIONS ARE REQUIRED!
const magicLogin = new MagicLoginStrategy({
  // Used to encrypt the authentication token. Needs to be long, unique and (duh) secret.
  secret: process.env.MAGIC_LINK_SECRET,

  // The authentication callback URL
  callbackUrl: "/auth/magiclogin/callback",

  // Called with th e generated magic link so you can send it to the user
  // "destination" is what you POST-ed from the client
  // "href" is your confirmUrl with the confirmation token,
  // for example "/auth/magiclogin/confirm?token=<longtoken>"
  sendMagicLink: async (destination, href) => {
    await sendEmail({
      to: destination,
      body: `Click this link to finish logging in: https://yourcompany.com${href}`
    })
  },

  // Once the user clicks on the magic link and verifies their login attempt,
  // you have to match their email to a user record in the database.
  // If it doesn't exist yet they are trying to sign up so you have to create a new one.
  // "payload" contains { "destination": "email" }
  // In standard passport fashion, call callback with the error as the first argument (if there was one)
  // and the user data as the second argument!
  verify: (payload, callback) => {
    // Get or create a user with the provided email from the database
    getOrCreateUserWithEmail(payload.destination)
      .then(user => {
        callback(null, user)
      })
      .catch(err => {
        callback(err)
      })
  }
  
  
  // Optional: options passed to the jwt.sign call (https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback)
  jwtOptions: {
    expiresIn: "2 days",
  }
})

// Add the passport-magic-login strategy to Passport
passport.use(magicLogin)

Once you've got that, you'll then need to add a couple of routes to your Express server:

// This is where we POST to from the frontend
app.post("/auth/magiclogin", magicLogin.send);

// The standard passport callback setup
app.get(magicLogin.callbackUrl, passport.authenticate("magiclogin"));

That's it, you're ready to authenticate! 🎉

License

Licensed under the MIT license. See LICENSE for more information!

More Repositories

1

sharingbuttons.io

Quickly generate social sharing buttons with a tiny performance footprint
JavaScript
2,473
star
2

login-flow

🔑 A login/register flow built with React&Redux
JavaScript
1,610
star
3

micro-github

A tiny microservice that makes adding authentication with GitHub to your application easy.
JavaScript
729
star
4

mxstbr.com

The source for my personal website
JavaScript
438
star
5

karabiner

My Karabiner Elements configuration
TypeScript
106
star
6

fifteen-kilos

Fifteen kilos
JavaScript
82
star
7

awesome-austria

🇦🇹 A curated list of things that show the awesome side of Austria
JavaScript
75
star
8

markdown-test-file

A pure markdown test page to make sure your markdown support works as intended
58
star
9

pgp.asc

An initiative to decentralize public PGP keys.
HTML
56
star
10

postcss.parts

A searchable catalog of PostCSS plugins —
JavaScript
46
star
11

eslint-plugin-clean-styled-components

Lint your styled-components code to be clean
JavaScript
40
star
12

urql-exchange-schema

Hey Berlin! This is new
TypeScript
31
star
13

knowledge

💡 Document everything (inspired by @yoshuawuyts)
31
star
14

dotfiles

My dotfiles
Vim Script
23
star
15

styling-workshop

Styling React applications workshop
JavaScript
17
star
16

github-markdown-tricks

A collection of tricks one can use in Github Markdown
16
star
17

pokedex

An example React app built "the old way"
JavaScript
14
star
18

modern-react-workshop

JavaScript
13
star
19

create-vcard

Create a vCard from an object. Simple wrapper around vcards-js.
JavaScript
13
star
20

teapot

A simple teapot server in Go
Go
11
star
21

mxstbr.github.io

My old blog
SCSS
10
star
22

old-personal-website

[DEPRECATED] See https://github.com/mxstbr/mxstbr.com for the current version!
PostScript
7
star
23

digitalgarden

TypeScript
6
star
24

elixir-graphql-test

Nothing to see here, just learning some new stuff
Elixir
6
star
25

mxstbr

5
star
26

hoc-benchmark

JavaScript
5
star
27

sw-demo

Simple ServiceWorker demo
JavaScript
5
star
28

speaking

5
star
29

serverless-graphql-airtable-extended

Extended version of https://github.com/ibrahima92/serverless-graphql-airtable
JavaScript
4
star
30

first-website

The first website I ever published for myself
CSS
4
star
31

eslint-plugin-styled-components

An eslint plugin to lint styled-components CSS
JavaScript
4
star
32

wwc

React Workshop for Women Who Code London
HTML
4
star
33

modern-react

3
star
34

scrolled

A tiny library which adds a class on page load and when the user has scrolled.
JavaScript
3
star
35

jschat

JavaScript
3
star
36

workshops-website

Sample DatoCMS website built with GatsbyJS
JavaScript
3
star
37

cyclejs-counter

Hello from the GraphCDN demo!
TypeScript
2
star
38

cool-group-site

Just a test
CSS
2
star
39

nextjs-decap-cms-blog-template

TypeScript
2
star
40

eternalpad

One-off, device specific notes —
ApacheConf
2
star
41

postcss-viennajs

A PostCSS plugin to demonstrate how to write a PostCSS plugin
JavaScript
2
star
42

workshop

HTML
2
star
43

debug.css

Easily debug your CSS positioning issues
CSS
1
star
44

viennajs-sw-demo

JavaScript
1
star
45

convertr

Chrome extension which converts units on webpages to ones you actually understand.
JavaScript
1
star
46

graphql-functions-example

JavaScript
1
star
47

weather-app

HTML
1
star
48

memory

A memory game in Valentines Day style, written with PaperJS.
JavaScript
1
star
49

react-boilerplate-cli

CLI for react-boilerplate
1
star