Don't do this if you implement Magic Links authentication
We recently started working on adding company accounts on weremote.eu and as part of that effort, we started thinking of ways to make login simple.
By simple I mean dead simple.
We settled on magic link authentication which is something Slack does when it asks you whether you want to manually insert your credentials or just drop your email in and they'll send you a login link.
This is also called password-less authentication because the user doesn't have remember a password and type it into the login form.
Although the workflow is pretty simple, I was torn between rolling my own mechanism using http-only cookies or using something like passportjs — either passport-zero or passport-magic-link.
So I decided to do some more reading before... deciding.
At one point I found this article which describes how to implement magic links with JWT.
It's a pretty decent write-up... but at one point I reached a "Wait! What?!" moment.
It was this portion right here:
And I literally heard myself saying ... "Mmmmmnope!"
How magic links work (simplified)
An application which provides password-less authentication has roughly the following workflow.
0?? User visits the login page
1?? User inputs his/her email & submits the form
2?? Application attempts to find user in the database
3?? Application creates a token and sets and expiry date for it
3??.1?? JWTs are amazing for this since they have expiry embedded.
The problem with them is that they are "heavier" and require more "network"
4?? Application sends the link to the user's email address
5?? User clicks on the link
6?? Application checks if the token is valid — is not expired, malformed or not belonging to this user(harder to do)
7?? If the token is valid, the user is provided with a session and is granted access to protected resources
What's wrong with that piece of code?
It allows an attacker to probe the site for valid email addresses which have accounts on the platform.
Here's how such a vulnerability looks IRL and at a way larger scale than you could ever imagine: 'Brute force' script snatched iPad e-mail addresses
The attack is virtually the same, but instead of inputting and email address and getting back true/false, in the AT&T the attackers used the ICC-ID (Integrated Circuit Card Identifier) — the unique number assigned to each SIM card — and got the email associated with that SIM instead.
The StackOverflow problem
Because developers nowadays are so used to copying code from various documentation/q&a sites without inspecting it thoroughly, products end up with security holes.
This can lead to gnarly data breaches which can result in huge fines, the loss of customer trust and possibly pose a threat against the security of your users.
The sad part is that they're easily preventible — just removing an else statement and running the code in the if statement every time.
Doing it better
The app shouldn't send users any error. It should especially not tell them they've inserted an invalid email address.
Don't assume that if the app would return "Something went wrong with your request" or "Error" things are instantly safer.
It takes only a couple of minutes to create a couple of accounts on any platform, and to probe using the emails of the test accounts.
Put some bruteforce prevention mechanisms in place. This way, if someone issues too many failed magic-link requests, block their IP. Seasoned hackers know how to bypass such a mechanism but having it in place might discourage some of them.
Conclusion
We should be aware that when we copy someone else's code, we don't just copy the solution, but we also copy their problems.
Also know that there's a huge boom in tutorials and instructional articles and other material. Often times these are written by people who are just getting started with a technology and love to experiment and share their knowledge.
This is an amazing thing, as long as we realize that it's there and it could bite us.
Even if something is written by a so-called expert in the field, we should be aware that even experts make mistakes. I've had junior devs send me "back to school" when they spotted some troubling pieces of code I wrote.
Now go make safer apps.
And know that software experience is built by building software.
So hire seniors, but hire them early, while they're still juniors!
We might have some over at www.weremote.eu, so check it out.
B2B Growth | Mergers & Acquisitions | $3.2M in pipeline | Founder & CEO, Inboxpirates
2 年Suraj Venkat
Security Solutions Consultant. PKI | HSM | KMS | Crypto
3 年probing emails was how Tesco breach happened, it makes life easy for an attacker.
Principal Engineer at Olio -Share More, waste less.
3 年Adrian O. I notice weworkremote.eu no longer seems to use magic login link? How come you dropped it, what issues were you facing?
Chief Executive Officer | Executive Management @ Metronet Broadband Networks
4 年So is weremote still using magic links. We've been really thinking hard about using that, but more dangerously on a fintech app.
Product @ Microsoft | Georgia Tech | CHI 2024 | Advocate of inclusive design for cognitive accessibility
4 年A very interesting read. However, it got me thinking on the popular "feedback" flow of user experience. Let's say a genuine user enters an email and goes off by one character. She/he does not get any feedback saying "invalid email", neither an email for the link, but somehow the email looks correct. How do we make this experience less frustrating for a valid user, from a UX perspective?