Sign In with Magic.Link

This tutorial will teach you how to add secure Web3 Moralis authentication to your NextJS application by walking you through the task of creating a full-stack Web3 authentication solution using the popular NextJS framework.

10751075

Web3 Moralis Authentication with Magic.Link - Result

Before Starting

You can start this tutorial if you already have a NextJS dapp with MetaMask sign-in functionality.

Installing the Magic Connector

WAGMI Magic Connector - the easiest way to add Magic.Link authentication for dapps using wagmi:

npm i @everipedia/wagmi-magic-connector
yarn add @everipedia/wagmi-magic-connector
pnpm add @everipedia/wagmi-magic-connector

Configuring the Magic Connector

  1. Open thepages/signin.jsx file and add MagicConnector as a connector to the useConnect() hook:
import { MagicConnector } from '@everipedia/wagmi-magic-connector'
import { signIn } from 'next-auth/react'
import { useAccount, useConnect, useSignMessage, useDisconnect } from 'wagmi'
import { useRouter } from 'next/router'
import axios from 'axios'

function SignIn() {
  const { connectAsync } = useConnect({
    connector: new MagicConnector({
      options: {
        apiKey: 'YOUR_MAGIC_LINK_API_KEY', //required
      },
    }),
  })
  const { disconnectAsync } = useDisconnect()
  const { isConnected } = useAccount()
  const { signMessageAsync } = useSignMessage()
  const { push } = useRouter()

  const handleAuth = async () => {
    if (isConnected) {
      await disconnectAsync()
    }

    const { account } = await connectAsync()
    const userData = { address: account, chain: '0x1', network: 'evm' }

    const { data } = await axios.post('/api/auth/request-message', userData, {
      headers: {
        'content-type': 'application/json',
      },
    })

    const message = data.message

    const signature = await signMessageAsync({ message })

    // redirect user after success authentication to '/user' page
    const { url } = await signIn('credentials', {
      message,
      signature,
      redirect: false,
      callbackUrl: '/user',
    })
    /**
     * instead of using signIn(..., redirect: "/user")
     * we get the url from callback and push it to the router to avoid page refreshing
     */
    push(url)
  }

  return (
    <div>
      <h3>Web3 Authentication</h3>
      <button onClick={() => handleAuth()}>Authenticate via Magic.Link</button>
    </div>
  )
}

export default SignIn

Testing the WalletConnect Connector

Visit http://localhost:3000/signin to test authentication.

  1. Click on Authenticate via Magic.Link:
10751075

Sign In Page

  1. Enter your email:
10751075

Magic.Link Modal

  1. Verify the login from your email:
10751075

Message from Magic.Link in Gmail

  1. After successful authentication, you will be redirected to the /user page:
10751075

User Page

  1. Visit http://localhost:3000/user to test the user session's functionality:
  • When a user is authenticated, we show the user's info on the page.
  • When a user is not authenticated, we redirect to the /signin page.
  • When a user is authenticated, we show the user's info on the page, even refreshing after the page. (Explanation: After Web3 wallet authentication, the next-auth library creates a session cookie with an encrypted JWT [JWE] stored inside. It contains session info [such as an address and signed message] in the user's browser.)

Did this page help you?