How to make Magic links with Node
The passwordless system introduced by Slack as a magic link is a really good alternative to the basic email/password authentication system for many reasons. Even if you don’t control the security level of the password encryption, you consider that your user mailbox provider is safe enough and that the fact that they give you back a token that you just sent them is way enough to authenticate them. In this way, we can see this as a cheap OAuth authentication (like Facebook) that doesn’t provide us any information about the user.
What about the implementation?
With the previous schema we know that we’ll have to implement only 2 endpoints. One to submit a request for an authentication key and one to get authenticated.
In the authentication endpoint, we’ll need 3 things. The access to our database to persist the account, the generation of the token and the generation of the mail. To generate the token, we’ll use a JSON Web Token approach. The advantage is that we can embed some content in the token and be sure that it’s not modified.
We’ll now generate a link containing the token in the query and send that link to our user by mail.
When our user will click on that link, we need to intercept the token that is passed as a query parameter, decode the content and put it in the context of the request. For that purpose, we just have to use an express middleware called express-jwt.
Now, when the user clicks on the link, we’ll have his information in the context and we can just use them.
And here our lifecycle is completed. Our users are now able to authenticate only by using their email address.
What about the security?
First, we have to take into consideration that the mailbox of our user may be compromised. If someone else intercepts the mail containing the token, they could have access to his account for the lifetime of our the token. There are several possibilities to solve this.
The first one would be to have a blacklist table for the token we want to cancel. Quite annoying and against the principle of making JWT tokens.
So what about putting a revision index in the token that we would store in the database? That way, only the token with the last revision would be able to login. With that solution we also lose the principle of JWT because we have to look in the database each time a user makes a request.
The nicest solution could be to make that the token we send by mail has a really short life, like 1 hour, and at the first request the user makes to the server, we generate a new token with a longer life.
Another strong solution would be to split the token in two pieces. Send the first piece by mail to the user and give the second piece back to the application in the response of the request. That way, only this mobile or browser will be able to rebuild the token and get authenticated.
An example would be nice!
The source code of a running example is available on the following link.
Contribute to magic-link-example development by creating an account on GitHub.github.com