Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • Official Blog
  • Nearby Places Finder
  • Direction Route Finder
  • Distance & Time Calculator
Menu

Node.js Express Passwordless Login Example to Send Magic Auth Link Using Nodemailer

Posted on March 12, 2023

 

Welcome folks today in this blog post we will be implementing passwordless auth to send magic link to user’s email address in node.js and express using the nodemailer library. All the full source code of the application is shown below.

 

 

Get Started

 

 

In order to get started you need to make a new node.js project using the below command

 

 

npm init -y

 

 

npm i express

 

 

npm i uuid

 

 

npm i nodemailer

 

 

And now you need to make an index.js file and copy paste the following code

 

 

index.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const express = require("express");
const nodemailer = require("nodemailer");
const uuid = require("uuid");
 
// Set up Nodemailer transport
const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    type: "OAuth2",
    user: "sharmagautam1997dob@gmail.com",
    accessToken:"##youraccesstoken##",
  },
});
 
// User database
const users = [
  { id: 1, email: "geekygautam1997@gmail.com", magicCode: null },
  { id: 2, email: "nehajoshi1982dob@gmail.com", magicCode: null },
];
 
const app = express();
app.use(express.json());
 
// Serve HTML file
app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html");
});
 
app.listen(3000, () => {
  console.log("Server listening on port 3000");
});

 

 

As you can see we are making a simple express app and also we are importing the nodemailer library and configuring it by passing the email address from which we will be sending out the magic links and here we need to pass the access_token which you can easily create using the google oauth2 playground as shown below

 

 

 

 

And now we need to make the index.html file and copy paste the below code

 

 

index.html

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
<head>
  <title>Magic Link Auth</title>
</head>
<body>
  <h1>Magic Link Auth</h1>
  <form>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email">
    <button type="button" onclick="sendMagicLink()">Send Magic Link</button>
  </form>
  <script>
    async function sendMagicLink() {
      const email = document.getElementById('email').value;
      const response = await fetch('/login', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ email })
      });
      const result = await response.text();
      alert(result);
    }
  </script>
</body>
</html>

 

 

As you can see we are having the input field where we allow the user to enter the email address and then we make the post request to the /login route in the backend and here we are passing the email which is entered by the user.

 

 

Now we need to make the /login post request inside the index.js file as shown below

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Login endpoint
app.post("/login", async (req, res) => {
  const { email } = req.body;
  const user = users.find((u) => u.email === email);
  if (!user) {
    return res.send("User not found");
  }
  const magicCode = uuid.v4().substr(0, 8);
  user.magicCode = magicCode;
  const mailOptions = {
    from: "sharmagautam1997dob@gmail.com",
    to: email,
    subject: "Magic Link Login",
    html: `
      <p>Click the link below to log in:</p>
      <a href="http://localhost:3000/dashboard?email=${encodeURIComponent(
        email
      )}&code=${encodeURIComponent(magicCode)}">Log in</a>
    `,
  };
  try {
    await transporter.sendMail(mailOptions);
    res.send("Magic link sent to your email");
  } catch (err) {
    console.error(err);
    res.send("Error sending email");
  }
});

 

 

As you can see in the above route we are sending the email using the nodemailer. And now we need to implement the request whenever someone clicks that magic link that we sent what happens. Now we need to check the code if that matches the code that we sent as shown below

 

 

 

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
// Dashboard endpoint
app.get("/dashboard", (req, res) => {
  const { email, code } = req.query;
  const user = users.find((u) => u.email === email && u.magicCode === code);
  if (!user) {
    return;
  }
 
  user.magicCode = null;
  res.send("Welcome to the dashboard!");
});

 

 

As you can see in the above /dashboard route we are extracting the email and the magic code and then we are finding the email if it’s exists inside the array of users. And also we are checking the magic code if it matches the code that we sent. If it’s matches then we show the message to the user that welcome to the dashboard as shown below

 

 

FULL SOURCE CODE

 

 

index.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
const express = require("express");
 
const nodemailer = require("nodemailer");
const uuid = require("uuid");
 
// Set up OAuth2 credentials
 
 
// Set up Nodemailer transport
const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    type: "OAuth2",
    user: "sharmagautam1997dob@gmail.com",
    accessToken:"##youraccesstoken##",
  },
});
 
// User database
const users = [
  { id: 1, email: "geekygautam1997@gmail.com", magicCode: null },
  { id: 2, email: "nehajoshi1982dob@gmail.com", magicCode: null },
];
 
const app = express();
app.use(express.json());
 
// Serve HTML file
app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html");
});
 
// Login endpoint
app.post("/login", async (req, res) => {
  const { email } = req.body;
  const user = users.find((u) => u.email === email);
  if (!user) {
    return res.send("User not found");
  }
  const magicCode = uuid.v4().substr(0, 8);
  user.magicCode = magicCode;
  const mailOptions = {
    from: "sharmagautam1997dob@gmail.com",
    to: email,
    subject: "Magic Link Login",
    html: `
      <p>Click the link below to log in:</p>
      <a href="http://localhost:3000/dashboard?email=${encodeURIComponent(
        email
      )}&code=${encodeURIComponent(magicCode)}">Log in</a>
    `,
  };
  try {
    await transporter.sendMail(mailOptions);
    res.send("Magic link sent to your email");
  } catch (err) {
    console.error(err);
    res.send("Error sending email");
  }
});
 
// Dashboard endpoint
app.get("/dashboard", (req, res) => {
  const { email, code } = req.query;
  const user = users.find((u) => u.email === email && u.magicCode === code);
  if (!user) {
    return;
  }
 
  user.magicCode = null;
  res.send("Welcome to the dashboard!");
});
 
app.listen(3000, () => {
  console.log("Server listening on port 3000");
});

 

 

Recent Posts

  • Node.js Express Passwordless Login Example to Send Magic Auth Link Using Nodemailer
  • Python 3 Tkinter Script to Encrypt PDF Documents With Password Using PyPDF2 Library GUI Desktop App
  • Node.js Express Project to Upload Image Buffer & BLOB Data to MongoDB Database & Display it in Browser Using Javascript
  • Node.js Tutorial to Export Images to PDF Document With Effects Using FilePix Library in Javascript
  • Node.js Tutorial to Export All Pages of PDF Document to Images and Save it in Javascript
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme