How to do magic with Next.js
Tags: react, nextjs, javascript, tutorial
Published: 2020-04-05 09:24:33

---
title: How to do magic with Next.js
published: true
description: 
tags: react, nextjs, javascript, tutorial
---

Do you know what is magic? [Magic](https://magic.link/) is a new thing that allows you to create passwordless login. How cool is that?

![APP_GIF](https://media.giphy.com/media/12NUbkX6p4xOO4/giphy.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](https://docs.magic.link/).

### First of all install some packages

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

### Let's build simple login form

```jsx
    // 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.

```jsx
     <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.

```javascript
     const magic = new Magic(YOUR_KEY);
```

You can get your key in [Magic dashboard](https://dashboard.magic.link/).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fqz4of1xpwuzg0jd4pkf.png)

- With this cool one-liner we are getting user DID token. You can read more about DID token in [Magic docs](https://docs.magic.link/tutorials/decentralized-id).

```javascript
    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](https://dev-to-uploads.s3.amazonaws.com/i/2qvq8j1rkkctizwg6plx.png)

- But now we need to store user session. To do this we send POST request on our API endpoint.

```javascript
    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.

```javascript
    // 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](https://dev-to-uploads.s3.amazonaws.com/i/4yidrr5amxmgygxvctwl.png)

Let's handle our API endpoint.

```javascript
    // 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.

```javascript
    const DIDToken = req.headers.authorization.substr(6);
```

- Then we are getting issuer (decentralized ID) and metadata about user from Magic.

```javascript
    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.

```javascript
    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](https://github.com/emwsc/next.js/tree/magic/examples/magic) 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.