How to do magic with Next.js

eatmeplzzz

Uriy Zhernakov

Posted on April 5, 2020

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.

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
eatmeplzzz
Uriy Zhernakov

Posted on April 5, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About