How to do magic with Next.js
Uriy Zhernakov
Posted on April 5, 2020
Do you know what is magic? Magic is a new thing that allows you to create passwordless login. How cool is that?
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.
- 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.
- 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.
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.
Posted on April 5, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.