How to Authenticate Users 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.
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
- Yarn
- pnpm
npm install @everipedia/wagmi-magic-connector
yarn add @everipedia/wagmi-magic-connector
pnpm add @everipedia/wagmi-magic-connector
Configuring the Magic Connector
- Open thepages/signin.jsxfile and addMagicConnectoras a connector to theuseConnect()hook:
import { MagicAuthConnector } from "@everipedia/wagmi-magic-connector";
import { signIn } from "next-auth/react";
import { useAccount, useConnect, useSignMessage, useDisconnect } from "wagmi";
import { useRouter } from "next/router";
import { useAuthRequestChallengeEvm } from "@moralisweb3/next";
function SignIn() {
  const { connectAsync } = useConnect({
    connector: new MagicAuthConnector({
      options: {
        apiKey: "YOUR_MAGIC_LINK_API_KEY", //required
      },
    }),
  });
  const { disconnectAsync } = useDisconnect();
  const { isConnected } = useAccount();
  const { signMessageAsync } = useSignMessage();
  const { requestChallengeAsync } = useAuthRequestChallengeEvm();
  const { push } = useRouter();
  const handleAuth = async () => {
    if (isConnected) {
      await disconnectAsync();
    }
    const { account } = await connectAsync();
    const { message } = await requestChallengeAsync({
      address: account,
      chainId: "0x1",
    });
    const signature = await signMessageAsync({ message });
    // redirect user after success authentication to '/user' page
    const { url } = await signIn("moralis-auth", {
      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.
- Click on Authenticate via Magic.Link:

- Enter your email:

- Verify the login from your email:

- After successful authentication, you will be redirected to the /userpage:

- Visit http://localhost:3000/userto 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 /signinpage.
- 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-authlibrary 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.)