Fetching latest headlines…
How to create Magic Link authentication system for email verification on Node.js (step-by-step)
NORTH AMERICA
🇺🇸 United StatesMay 11, 2026

How to create Magic Link authentication system for email verification on Node.js (step-by-step)

1 views0 likes0 comments
Originally published byDev.to

Magic link authentication is becoming one of the most popular ways to verify users without passwords. Instead of asking users to remember passwords, we simply send them a secure login link through email.

What is a Magic Link?

A magic link is a unique URL sent to a user’s email. When the user clicks the link:

  • The server verifies the token
  • The user becomes authenticated
  • No password is required Example:
https://yourapp.com/verify?token=abc123

This approach is:

  • More secure than passwords in many cases
  • Easier for users
  • Great for modern SaaS apps

Basic setup for magic link authentication system

Firstly, you need to install auth-verify:

npm install auth-verify
const AuthVerify = require('auth-verify')
const auth = new AuthVerify({
    mlSecret: 'super_secret_key',
    mlExpiry: '5m',
    appUrl: 'http://localhost:3000',
    storeTokens: 'memory' // in production 'redis'
})

You need also web server like built on Express.js

Configure Magic Link Sender

Before sending links, you must set up your email transport.

Gmail Example

auth.magic.sender({
  service: 'gmail',
  sender: '[email protected]',
  pass: 'your_gmail_app_password'
});

Custom SMTP Example

auth.magic.sender({
  host: 'smtp.mailgun.org',
  port: 587,
  secure: false,
  sender: '[email protected]',
  pass: 'your_smtp_password'
});

API services Example

auth.magic.sender({
  service: 'api',
  apiService: 'resend', // 'mailgun', 'sendgrid'
  sender:  '[email protected]',
  apiKey: 'YOUR_API_KEY'
})

For "mailgun" you should also add also your domain

domain: "your-domain.com"

Send Magic Link

Send a secure, expiring link to the user’s email:

auth.magic.send('[email protected]', {
  subject: 'Your Secure Login Link ✨',
  html: `<p>Click below to sign in:</p>
         <a href="{{link}}">Login Now</a>`
});

The {{link}} placeholder will automatically be replaced with the generated magic link.

Verify Magic Link

Typically used in your backend /auth/verify route:

app.get('/auth/verify', async (req, res) => {
  const { token } = req.query;
  try {
    const user = await auth.magic.verify(token);
    res.json({ success: true, user });
  } catch (err) {
    res.status(400).json({ success: false, message: err.message });
  }
});

Full working example

const express = require('express');
const bodyParser = require('body-parser');
const AuthVerify = require('auth-verify');

const app = express();
app.use(bodyParser.json());

const auth = new AuthVerify({
  mlSecret: 'supersecretkey',
  appUrl: 'http://localhost:3000',
  storeTokens: 'memory'
});

auth.magic.sender({
  service: 'gmail',
  sender: '[email protected]',
  pass: 'your_app_password'
});

// Send link
app.post('/auth/send', async (req, res) => {
  const { email } = req.body;
  await auth.magic.send(email);
  res.json({ message: 'Magic link sent!' });
});

// Verify link
app.get('/auth/verify', async (req, res) => {
  try {
    const user = await auth.magic.verify(req.query.token);
    res.json({ message: 'Login successful!', user });
  } catch (err) {
    res.status(400).json({ message: err.message });
  }
});

app.listen(3000, () => console.log('🚀 Server running on port 3000'));

Comments (0)

Sign in to join the discussion

Be the first to comment!