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.
Top comments (0)