DEV Community

Uriy Zhernakov
Uriy Zhernakov

Posted on • Edited on

How to do magic with Next.js

Do you know what is magic? Magic is a new thing that allows you to create passwordless login. How cool is that?

APP_GIF

But do you know how to do Magic with Next.js? Well, let's find out.

Why Next.js? I wanted to play with some cool things which I don't use in my everyday work, so I decided to try Next.js. You can totally use Magic with anything else. They have good docs and tutorials.

First of all install some packages

    npm i magic-sdk@beta @magic-sdk/admin

Let's build simple login form

    // login.js

    const Login = () => {
      const handleSubmit = useCallback(async event => {
        event.preventDefault();
        const elements = e.currentTarget.elements;
        const email = elements.email.value;
        if (email) {
          const magic = new Magic(YOUR_KEY);
          const didToken = await magic.auth.loginWithMagicLink({ email });
          const serverUrl = window.location.origin;
          const result = await fetch(`${serverUrl}/api/magic/login`, {
            headers: new Headers({
              Authorization: "Bearer " + didToken
            }),
            credentials: "same-origin",
            method: "POST"
          });
          if (result.status === 200) {
            // Route to your main page or whatever
          }
        }
      }, []);
      return (
          <form onSubmit={handleSubmit}>
            <input type="email" name="email" placeholder="Enter your email" />
                    <button type="submit">
                    SignUp \ Login
            </button>
          </form>
      );
    };

So, let's break down things:

  • User submits email address.
     <form onSubmit={handleSubmit}>
            <input type="email" name="email" placeholder="Enter your email" />
     </form>
  • We handle this submit and if email is not empty we create some Magic.
     const magic = new Magic(YOUR_KEY);

You can get your key in Magic dashboard.

Alt Text

  • With this cool one-liner we are getting user DID token. You can read more about DID token in Magic docs.
    const didToken = await magic.auth.loginWithMagicLink({ email });

Magic is doing all work for you. Only thing user should do is check his email.

Alt Text

  • But now we need to store user session. To do this we send POST request on our API endpoint.
    const result = await fetch(`${serverUrl}/api/magic/login`, {
      headers: new Headers({
        Authorization: "Bearer " + didToken
      }),
      credentials: "same-origin",
      method: "POST"
    });

Time to check out our server side code

On our server we need to create some magic again but now with different key.

    // magic.js

    import { Magic } from "@magic-sdk/admin";
    export const magic = new Magic(YOUR_OTHER_KEY);

You can also find this key in your Magic Dashboard.

Alt Text

Let's handle our API endpoint.

    // api/login.js

    import { serialize } from "cookie";

    export default async function login(req, res) {
      try {
        const DIDToken = req.headers.authorization.substr(6);
        const issuer = magic.token.getIssuer(DIDToken);
        const metadata = await magic.users.getMetadataByIssuer(issuer);
        if (!metadata) {
          throw new Error("No metadata from magic");
        }
        res.setHeader(
          "Set-Cookie",
          serialize("cool_cookie_name", issuer, {
            // very secure cookies options
          })
        );
        res.end();
      } catch (error) {
        res.status(error.status || 500).end(error.message);
      }
    }

What we are doing here:

  • We need user DID token from request headers.
    const DIDToken = req.headers.authorization.substr(6);
  • Then we are getting issuer (decentralized ID) and metadata about user from Magic.
    const issuer = magic.token.getIssuer(DIDToken);
    const metadata = await magic.users.getMetadataByIssuer(issuer)
  • And after that all you need to do is to create session cookie with your preferred options to store user session.
    res.setHeader(
      "Set-Cookie",
      serialize("cool_cookie_name", String(issuer), {
        // very secure cookies options
      })
    );

Voila, now you can use this session cookie to do all stuff you wanted to do with Next.js.

You can checkout repo if want to look at complete example. I also made a PR to Next.js examples repo.

P.S. It's actually my first ever article and first ever article in English. Hope you enjoyed it.

Top comments (0)