Issues I’ve encountered building an app with magic links:
1. Include a fallback sign-in code in your magic link, in case the user needs to log in on a device where accessing their email isn’t practical.
2. Make sure the sign-in link can handle email clients that open links automatically to generate preview screenshots.
3. Ensure the sign-in link works with email clients that use an in-app browser instead of the user’s preferred browser. For example, an iOS user might prefer Firefox mobile, but their email client may force the link to open in an in-app browser based on Safari.
I arrived at the same conclusion after going through the steps and seeing that some corporate systems mark the login link as malicious, and there’s nothing I can do about it.
I've had success with sending a code, and the link takes you to a page where the input is pre-filled with the code, and you just have to click "Login".
> I think that a link to a page where you enter a one time code gets around a lot of these issues.
I've done both in my SaaS product - link is GET with the OTP in the link, the target page checks if the link is in the URL, and if not, then the user can type it in.
Only for signup, though. For sign-in, the default is to always have the user type it in.
These days there's also to consider that some Mail Threat Protection Tools (at least Microsoft Defender in Exchange Online does this) click links in Mails to check them.
Recently ran into this issue as new mail accounts got confirmed automatically and magic links were invalid when the user clicked them, because Microsoft already logged in with it during checking.
Come to think of it, magic links by definition violate the principle that GET requests should not change state. Defender & preview tools are actually following the established norms here - norms that were established decades ago precisely because we hit the more broad problem with C, U & D parts of CRUD, and collectively agreed that doing destructive operations on GET requests is stupid.
> These days there's also to consider that some Mail Threat Protection Tools (at least Microsoft Defender in Exchange Online does this) click links in Mails to check them.
What an insane policy, why am I surprised Microsoft came up with it…
4. Make sure the sign-in link on mobile works with your mobile app.
When McDonald's switched from email/password to magic links I had a hard time getting the magic link to work with the McD app. It usually would just open in the McD website.
Thus was quite annoying because about 98% of the time I eat McD's I would not do so if I could not order via the app [1].
I finally gave up and switched to using "Sign in With Apple" (SIWA). There was no way that I could find to add SIWN to an existing McD account, so had to use the SIWA that hides the real email from McD. That created a new McD account so I lost the reward points that were on the old account, but at least I could again use the McD app.
[1] They have a weekly "Free Medium Fries on Friday" deal in the app available for use on orders of at least $1. Almost every Friday for lunch I make a sandwich at home and then get cookies and the free fries to go with it from McD.
1) rooted or bootloader-unlocked Android devices are not allowed (granted it's easy enough to get past it for now but the checks are still there).
2) 2FA requirements as if anyone would bother to steal coupons from others
It appears that they want ordering burgers to have the same level of enhanced security as banking apps. Not even crypto or trading apps bother to block unlocked devices in such a way. Blocking rooted devices doesn't even make banking apps more secure but for them I can at least understand the reasoning.
I have heard that you are basically paying double what you normally would if you aren’t hunting for deals in mcd’s app these days. How much truth is there to that?
One thing I recently found annoying with Slack was that I wanted the company chat on my phone, but I didnt want the company’s email on my phone given the overly broad control of my phone
so I got the magic link on their computer and then I made a qr code
but wait, the email quarantine system had altered the whole link so I had to extract that
but wait the redirect url back to slack was malformed because of the url encoding and i had to fix that and then make the qr code
like wow just give me a qr code or code instead in the original magic link email!
One of the biggest advantages of magic links is that they're unphishable while still being easy to use (unlike passkeys).
Having a code completely negates that advantage, as attackers can just set up a fake website that asks for the code.
Magic links should log you in on the device you click them, not on the device that requested the login session. Anything else, while being a little bit less annoying, is a security issue and should be treated as such.
When using magic links, you can still support the common UX polish of letting a user log in on a different browser/device.
If the user opens the magic link in the same browser that initiated the email, then just log them in. Otherwise, present them with the Apple-style "Do you want to authorize a login from 1.2.3.4 using Firefox on iOS possibly located in Portland, Maine? [Authorize] or [Reject]".
> However, as with all other iOS web browsers, the iOS version uses the WebKit layout engine instead of Gecko due to platform requirements.
I do agree with what you’re saying though! Just those two in particular will probably have pretty good compatibility, which I was amused to find out when I looked into it.
The link is a "safe" GET request.
The page loaded via the link should do an "unsafe" POST for the login, via javascript with a form button for fallback.
>The purpose of distinguishing between safe and unsafe methods is to allow automated retrieval processes (spiders) and cache performance optimization (pre-fetching) to work without fear of causing harm. In addition, it allows a user agent to apply appropriate constraints on the automated use of unsafe methods when processing potentially untrusted content.
Exactly the same for email unsubscribe links, or a one click "buy now" link.
In my app, I just added an “Almost there!” Page with a button that the user needs to click. I still need to add a fallback option that uses a one time code for the other reasons mentioned above.
Save a browser cookie when the login is initiated. When the link is clicked check if the same cookie is present. If not, ignore it. Expire the link and the cookie after n minutes.
Have your logging-in session wait for / poll "has visited magic link", and authenticate that session when it's done.
Tons of systems do this. It works great, and it can quite easily work without any web browser at all on the logging-in side because it just needs to curl something -> poll for completion and save the cookies -> curl against the API. A number of oauth flows for e.g. TVs work this way, for instance, because it's a heck of a lot easier than integrating a full browser in the [embedded thing]. Many app-based 2FA (e.g. Duo) works this way too.
I might receive a magic link on my phone but then sometimes I'll copy/paste that over to my desktop or another device.
This works on 99% of magic links I've tried except for cases when they are trying to prevent account sharing. I remember the Bird bike app did this, where they required the magic link to be clicked on the same device login was initiated on. I was using my friends account and he would just forward me the link until one day this stopped working.
We've been using Magic Links for a few years (and yes, one reason was to avoid the security issue of storing user passwords when we were just at MVP stage) and found the top problems with it are:
1. Some users (0.1%) just don't ever get the email. We tried sending from our IP, sending from MailGun, sending from PostMark, having a multi-tier retry from different transactional tools. Still, some people just will not ever be able to log in.
2. People click old Magic Links and get frustrated when a 6-month old link "doesn't work". We've decided to remedy that by showing them a page that re-sends the link and explains the situation (like Docusign does) instead of an error message.
3. People will routinely mis-spell their email and then blame the system when they don't get the code.
All of this still results, I feel, in way fewer support tickets than the email+password paradigm, so I'm still in favor of Magic links.
It's indeed interesting the number of people misspelling their email address, or having an inbox so full that it cannot receive emails anymore.
I never tried to add magix links, but I added Google Sign in to my SaaS several month ago, and since then, it accounts for more than 90% of new sign-ups (users are devs, so rather tech savvy and privacy aware). I'm now convinced that no other method is a priority (I still have email/password of course).
> but I added Google Sign in to my SaaS several month ago, and since then, it accounts for more than 90% of new sign-ups (users are devs, so rather tech savvy
I do it for services I don't care about. In my mind it is more privacy for me. Keeps you out of my real inbox and my password out of your system and I believe that I can - to some extend - remove myself without having to go through whatever crap account deletion process that services has tried to cobble together.
Worst offenders let me login with google and then immediately asks for name and phone number or email and asks me to verify it.
Wouldn't privacy aware users prefer passkeys or passwords, instead of any kind of SSO?
In general, I do understand that use of SSO is due to convenience. Especially since in many cases websites provide less friction when signing up via SSO instead of using username+password.
I have my HN username at a venerable webmail service. I check it about once a year, tops. My name isn't unimaginably rare, but neither is it "Smith".
I am shocked, shocked, by the number of different K. Strauser people who have typed that email address into some random website or another. I've gotten bank notifications, loan documents, Facebook signup info, meeting minutes from some random volunteer work, and all kinds of other things. When I can figure out from context who the intended recipient is, I try to let them know so they can fix it. On one occasion, the person sent me back a swear-laden diatribe for "hacking their email". Sigh.
I think this has made me a better engineer, though. When someone says something in a meeting like "...as long as they type their email correctly", I can jump in and address that myth head-on. No, people will not type it correctly. If it's a minor pain in the neck for me, with an uncommon name, I can only imagine the traffic that the world's John Smith's get.
Funny part is most of those apply to passwords too, using an old password and complaining its not working, mistyping shit and complaining that its the system, and requesting a password reset and not getting the mail LOL so i only see upsides
Username+password (or passkeys) with a password manager (which ensures that credentials are used on the correct domain) via HTTPS is probably the only end-to-end encrypted way of exchanging credentials with good UX for general public.
If you are storing sensitive information in the system, by all means, you should act accordingly and require higher-security login than magic links. But if you do, you really should not be accepting username+password either. You need to at least put some 2FA on there to step up one level of security. And not SMS- or email-based 2FA either.
90% of web apps don't handle that kind of information, and for them a magic link is at least as good as passwords (as this article explains). Those that do handle things like personally identifiable information (beyond an email address) really should be enforcing 2FA or proper electronic IDs.
There is a whole profession writing recommendations about information security, and every web developer needs to be able to do this kind of analysis at a rudimentary level. We don't need to wing it, we can analyze security requirements in a systematic way.
Also what's the reasoning behind not wanting to store passwords?
It's not like the rest of the customer's data is not valuable? If you don't feel comfortable storing passwords, the amount of data I'd trust you with is strictly zero.
No, kudos to them for looking at a piece of data and asking themselves if it's worth storing—more companies should do that with more data. It's not that the rest of the data isn't valuable to some extent, it's that every piece you have makes the blast radius of a leak that much bigger, so why hold stuff you don't need?
Planning for a breach doesn't make you more likely to have one—if anything it makes you less likely!
To be fair to 404, they're trying to limit the amount of data they hold which IS good, but in the end they need to have the email address of subscribers.
The UX debate is valid, but magic links (and emailed one-time codes) are clearly more secure than password + password reset. Control of the email account gets you in either way. Passwords are an additional attack vector.
I've been a loyal Mercury customer for a while now, but their forced use of magic links as a third authentication factor any time my IP address changes (after authenticating with a secure password from my password manager and after a valid TOTP) has me ready to move my company's banking elsewhere.
I could understand requiring a third factor to authenticate if signing in from a different location or a different ISP than I've been using for the past 5 years, but it's ridiculous to do so if nothing has changed (except the final octet of my DHCP-assigned address) since I last signed in yesterday. I use a different computer (via SSH) to read my email than I do for web browsing, and cutting-and-pasting a signin link that's hundreds of characters long (spanning multiple lines in Emacs, so I have to manually remove \ where it crosses line boundaries) is a PITA.
Adding friction on every sign-in colors all subsequent interactions I have with an app, and makes me hate using it.
You shouldn’t get the device verification requirement if you’ve used the device before (we store a permanent cookie to check this) or for the same IP. Any chance your cookies are being cleared regularly?
We added this after attackers created clones of http://mercury.com and took out Google ads for it. When customers entered their password and TOTP on the phishing site, the phisher would use their credentials to login and create virtual cards and buy crypto/gold/etc. The phisher would also redirect the user to the real Mercury and hope they figured it was a blip.
This device verification link we send authorizes the IP/device you open it on, which has almost entirely defeated the phishers.
Since WebAuthn is immune to this style of phishing attack, we don’t require device verification if you use it. I highly recommend using TouchID/FaceID or your device’s flavor of WebAuthn if you can—it’s more convenient and more secure. You can add it here: https://app.mercury.com/settings/security
That said, we are talking internally about your post and we do recognize that as IPv6 gets more traction IPs will rotate much more regularly, so we’ll think if we should loosen restrictions on being a same-IP match.
Yes, I clear cookies every time I close my browser, as a layered approach to privacy on top of uBlock Origin and NoScript. There isn't a great way to exclude certain sites from this, other than setting up a dedicated web browser in a container just for Mercury.
I wasn't aware that WebAuthn didn't have this requirement. I prefer TOTP because I actually like having a second factor in addition to a credential stored on my computer's hard drive (whether a password or a private key in my password manager), but I might be willing to reduce my security posture to get rid of this annoyance.
One suggestion: the link would be half as annoying if it was easily cut-and-pasteable rather than a long email-open-tracking link spanning multiple lines. This is what it looks like when I copy it out of my email:
I have to manually remove the backslashes and re-combine the lines before pasting into my web browser.
Edit to add: looks like email.mg.mercury.com is hosted by Mailgun. Are you intentionally sharing these authentication tokens with a third party by serving them through this redirect? Do your security auditors know about this?
> IPv6 gets more traction IPs will rotate much more regularly
unfortunately, only few ISPs do IPv6 correctly by assigning a fixed prefix to customers. most of the ISPs apply the ipv4 logic when adding ipv6 planning hence this situation.
hopefully this will improve in the future and more stable prefixes will be given to users.
I like the schemes that send a numeric verification code that you manually type in without an email link. can also use a text message. Maybe allow this to be configured.
I think this is really great as a response to 404's post last week. I love 404 but I'm as annoyed by Magic Links as OP for the same reasons they mention.
Ricky Mondello wrote a really great blog last week[1] about how passkeys, as OP alludes to at the end, can be used alongside Magic Links, that I think is worth a read.
I haven't had these specific issues with magic links specifically, but I do remember when Epic launched the Epic Games Store and they would e-mail you two-factor codes to log in. I consistently had issues where I wanted to log into their store, got prompted to enter the two-factor code they e-mailed me, got no email for several minutes, requested another code, didn't get that either, gave up and did something else, and then got both codes 30 minutes later.
The fact is that even in the best of times, e-mail isn't reliable. Things go to your junk folder. Links get blocked by work spam filters. Mailboxes get full (I assume? it's been a while).
Personally, I have my e-mail on my iPhone and anywhere else (work laptop or gaming PC) I have to log into icloud.com to check my e-mail; it's cumbersome. Let me put in a password. Let me scan a QR code like embedded devices do. Give me at least one other option.
Thank you, this is a better piece than TFA! Reading TFA I was rather confused at how passkeys are an alternative to magic links—it makes a lot more sense to view them as a complement. Magic links allow you access to passkeys, which are basically "Remember this Computer" on steroids.
Am I misunderstanding something, or are passkeys not actually an alternative to magic links?
Every implementation of passkeys I've seen has presented me with the option to create a passkey after I've already logged in with some other method. I'll admit that I haven't dug into it deeply, but the UX I've been presented with consistently makes passkeys appear to be an alternative to the "Remember this computer" button, not to passwords in general. Somehow the service has to know that this new device is authorized. I know depending on the provider there's such a thing as passkey syncing, but that doesn't solve the problem of getting the initial authentication done.
The key insight with magic links is that your security system is no stronger than its recovery mechanism. We are never going to get to a world where passkeys are treated as the only authentication mechanism—there will always be a recovery mechanism, and in most cases an automated one via email. Given that that is the case, magic links simplify things by just not pretending that we have a more secure layer on top. By making the recovery mechanism the primary means by which you interact with the authentication flow you're being more honest about the actual security of your auth system.
I think as Ricky wrote last week [1], they should augment Magic Links or other auth methods. There are some positives about Magic Links for sure (though I don't know if making your email an even stronger attack vector is necessarily one of them), but for people who use a password manager, for example, they are a definite friction point that I think passkeys most certainly could alleviate.
There are definite UX problems around passkeys that could be improved and I think exporting will make syncing across systems a lot better (one of the reasons I use 1Password as my primary password and passkey system is so I can use my passkeys across devices; of course it helps that my employer uses 1Password as our system so I am logged into my personal and enterprise accounts and can auth then from personal or work devices, provided additional auth or enrollment isn't needed) -- but if the problem as 404 defines it is that they don't want to be responsible or even have to worry about storing your passwords/auth controls, I think passkeys is at least better for a subset of users than Magic Links.
But again, like Ricky, I don't think it should be viewed as either or. It should be both.
Thank you for the link! I saw your other comment and actually edited mine to point to that, because it's definitely the answer to my question!
> though I don't know if making your email an even stronger attack vector is necessarily one of them
I'm unconvinced that magic links do make your email an even stronger attack vector. Essentially every service that would be inclined to use magic links would already have a way to reset your password entirely once the email is compromised. All magic links do is make this the primary way to interact with the auth flow.
The bad guys already know that your email is the best target. Magic links just make that very explicit.
Passkeys are in a transition period right now. There is no reason you have to have an alternative login method if you are using Passkeys, but no service has switched over to being Passkey only yet. Some users on older OSs / Linux might not be able to generate and store Passkeys yet, many users are not using a cross platform credential manager so if you've created passkeys with iCloud Passwords, there isn't a way to log in via linux right now.
Give it a few more years and I suspect we will start to see services start with creating a passkey and never collecting a password. The passkey portability specs will be implemented, and hopefully Gnome/KDE implement passkey support.
What does the final end state of passkeys look like? What happens if I lose the device I created the passkey on, if it gets bricked, or if I get banned by the platform that was supposed to be syncing my passkeys?
sigh TBH, I hope not. Maybe optionally, but for now the friction might keep companies from going passkey only, which (I think) would be a total nightmare from a security and usability perspective.
The first thing I thought when I read this is how can the author make the specific criticisms of links/otp codes and then suggest passkeys, which have pretty much the same issues x10. Like if using a OTP from your phone or copying a link from your phone when using a work PC to visit a website is a pain, how much easier/better/same is it to try and have your work computer work with your personal passkey from a laptop or something?
> how much easier/better/same is it to try and have your work computer work with your personal passkey from a laptop or something?
Passkeys support authentication via a secondary device over Bluetooth (and this is supported in every major browser on every major platform). So you can login to a site on a machine that’s completely disconnected from your personal passkey store by scanning a QR code with your personal phone.
The login flow basically goes “request login with passkey” -> “browser recognises it doesn’t have the needed passkey, and offers a QR code to scan” -> “scan QR code with phone” -> “phone and browser handshake via Bluetooth” -> “passkey handshake happens between website and phone” -> “login completes”.
I’ve personally used this flow with my work laptop and my personal iPhone many times. iOS has built in support for the Passkey QR codes, so you can scan the code with the standard camera app. Additionally iOS supports allowing 3rd party passwords managers to take over the Passkey flow once you’ve scanned the QR code. So in my case I complete the flow with 1Password.
End-to-end the flow is pretty damn seamless, I’ve never personally had it fail, and take 30seconds to complete. The most annoying part is trying to remember where my phone is.
I refuse to use any service that only supports magic links for auth. It is incredibly user-hostile, and absolutely worse from a security perspective than passwords (with a password manager). Most critically it simply does not work in my personal setup where I do not have access to my email account from the machine I am using to login, precisely for security reasons and the safety of my accounts.
Anthropic has been the once exception to this personal policy simply because Claude is the best LLM out there. But it's a mountain of pain every time I have to re-login, and I've complained to them multiple times about this.
It is certainly not all, and most security conscious sites offer other recovery options like one time use codes. Many also allow for time delayed account recovery, which aren’t a usable option for magic links.
In any case the correct approach here is to fix password reset/account recovery (e.g. with social key recovery) rather than reduce everything to the lowest common denominator.
It also can be said to lower security because it instills the behavior of clicking on links in incoming emails as a standard practice.
As someone in the security industry, I find it amazing how much we've told people (in awareness training) to "not click things on the thing-clicking machine™" while simultaneously having processes like password resets that require doing it.
Fake password reset links are also a common attack vector, so yes people are told to be also cautious of those.
Otherwise it's been a while I haven't seen an reset link instead of a reset code. Copy/pasting is not much of a hassle, and it works even if the mail is checked on a different device.
The only real link I had to deal with were app callbacks that were explicitly labeled as such (with instructions from the app to explain what to expect)
Be careful of those as well, but in this case it's quite simple: password reset links should only be sent when the user explicitly requests them; of you receive an unexpected email asking you to reset your password, don't click the link.
Ok. So now my users get random login links for sites we may or may not use… sure, you Silicon Valley Cool Guy aren’t going to fall for it, but my blue collar Detroit UAW guys might.
Click that stupid magic link for a service we use, and they’re asked for their Office 365 credentials… all the while I’m telling them not to click links in emails.
Best implementation I see of this requires you to click the link on whatever device you receive the email on, but it doesn’t transfer the session there - it just triggers completion of the login process on whatever device you initiated the process on.
This is bad (phishing). The better solution is have the login only work on the device where the link is opened, and for cross-device use to also provide an OTP code the user can read on the receiving device and easily type in on the initial device. (Or only provide the OTP code and no link.)
How is that secure against the same phishing attacks that a clickable link is vulnerable to (basically the idea that someone can socially engineer you into a situation where you think you are supposed to complete the auth flow with them, enabling them to sign in as you?)
Agreed! If they all worked like this would be a happy camper. Nothing worse than being in one browser, opening the email, then it opens and authenticates you on the default browser or even better on a different device and needing to forward the link to the other device so you can open it there (yes odd scenario but try not to access certain emails from certain devices).
Sites that send an OTP (crazy-pink-horse-3837) that you can copy, and paste is a good middle ground if implementing the link that just Auths the original request is too difficult.
Most sites will have a confirmation once you click the link that includes the browser version and IP address. I have seen that info only in the email itself too with no confirmation afterwords, but not for some time. Have never seen one that is just a link with nothing else that once clicked allows the other device in but supposes could be implemented that way.
The article itself is about not making them the only option (which is fair), and the OP says if they do it should login the device which originally made the request (which I agree). If the implementation is just an email with only a link, no other information with no confirmation (yes, it's fine to let this device in), then I would have to agree with you it's very risky and could allow anyone to login as you (hopefully no sites are doing this, but...)
If you really want to allow for another browser to authenticate a login request, you can at least limit it to sessions coming from the same IP.
That would let you authenticate your desktop browser from an email you opened on your phone if you're on your home network, but without becoming widely exploitable by phishers.
AFAIK, McDonald’s does this with their mobile app (they weren’t letting me log in with my password) But the problem with their implementation was that the magic link that they send you is wrapped in a click tracker whose domain is blocked by pihole (and the likes), and I could not reach the actual auth URL to complete the login process.
A fully competent security team will, on the other hand, carry out a more comprehensive threat modelling exercise and make a pragmatic choice about whether this kind of auth flow is appropriate for your usecase.
The phishing risks for a bank account login are very different than those for a ‘returning player’ login to a casual gaming site for example.
BankID scams in Sweden worked because it did not require there to be authentication between the device that logged in and the device that authorised the login.
The victim got a phone call in which the she got manipulated into authorising something in the BankID smartphone app. But what she was actually doing was authorising the attacker to log into her online bank account.
First after several years (of blaming the thousands of victims for their millions lost) did the system start using QR codes on the screen scanned by the smartphone.
Solvable with the right information in the authorizing email.
Remember that the flow the magic link is part of is one you initiate, that causes you to get an email you are expecting.
That email, and the landing and confirmation page it links you to, can explain very clearly that you are only supposed to authorize this if you are trying to log in on known device in known location that is displaying recognizable number on the screen right now.
Yeah exactly. Plus, sometimes SOMETHING will click the link before it even gets to the person's inbox (some enterprise spam filter with a sandboxed browser for example).
edit: saw that nicce basically said that a second before I hit post.
Many email clients will click the link and invalidate it - for example outlook is a classic here - so the best implementation does not use redirects/links at all.
OTP is far better than an actual magic link - you can still include a link that pre-fills the code.
Yes but clicking the link itself shouldn't log you in. Any implementation of magic links that does this is broken because of link previews.
You click the button on the page which knows the session you're logging in from and link code and does a POST which completes the login. This is how all the "login by scanning QR code" flows work.
I’ve been stung by this before, where I’d already closed the original browser tab since I assumed the magic link would open a new tab (as they usually do)
1. Include a fallback sign-in code in your magic link, in case the user needs to log in on a device where accessing their email isn’t practical.
2. Make sure the sign-in link can handle email clients that open links automatically to generate preview screenshots.
3. Ensure the sign-in link works with email clients that use an in-app browser instead of the user’s preferred browser. For example, an iOS user might prefer Firefox mobile, but their email client may force the link to open in an in-app browser based on Safari.
I think that a link to a page where you enter a one time code gets around a lot of these issues.
Sending a code goes around a lot of issues.
Deleted Comment
I've done both in my SaaS product - link is GET with the OTP in the link, the target page checks if the link is in the URL, and if not, then the user can type it in.
Only for signup, though. For sign-in, the default is to always have the user type it in.
Recently ran into this issue as new mail accounts got confirmed automatically and magic links were invalid when the user clicked them, because Microsoft already logged in with it during checking.
What an insane policy, why am I surprised Microsoft came up with it…
When McDonald's switched from email/password to magic links I had a hard time getting the magic link to work with the McD app. It usually would just open in the McD website.
Thus was quite annoying because about 98% of the time I eat McD's I would not do so if I could not order via the app [1].
I finally gave up and switched to using "Sign in With Apple" (SIWA). There was no way that I could find to add SIWN to an existing McD account, so had to use the SIWA that hides the real email from McD. That created a new McD account so I lost the reward points that were on the old account, but at least I could again use the McD app.
[1] They have a weekly "Free Medium Fries on Friday" deal in the app available for use on orders of at least $1. Almost every Friday for lunch I make a sandwich at home and then get cookies and the free fries to go with it from McD.
1) rooted or bootloader-unlocked Android devices are not allowed (granted it's easy enough to get past it for now but the checks are still there). 2) 2FA requirements as if anyone would bother to steal coupons from others
It appears that they want ordering burgers to have the same level of enhanced security as banking apps. Not even crypto or trading apps bother to block unlocked devices in such a way. Blocking rooted devices doesn't even make banking apps more secure but for them I can at least understand the reasoning.
so I got the magic link on their computer and then I made a qr code
but wait, the email quarantine system had altered the whole link so I had to extract that
but wait the redirect url back to slack was malformed because of the url encoding and i had to fix that and then make the qr code
like wow just give me a qr code or code instead in the original magic link email!
Having a code completely negates that advantage, as attackers can just set up a fake website that asks for the code.
Magic links should log you in on the device you click them, not on the device that requested the login session. Anything else, while being a little bit less annoying, is a security issue and should be treated as such.
I don't like that for a number of reasons.
If the user opens the magic link in the same browser that initiated the email, then just log them in. Otherwise, present them with the Apple-style "Do you want to authorize a login from 1.2.3.4 using Firefox on iOS possibly located in Portland, Maine? [Authorize] or [Reject]".
Hey, wasn’t Firefox on iOS based on Safari related tech anyways?
https://en.m.wikipedia.org/wiki/Firefox
> However, as with all other iOS web browsers, the iOS version uses the WebKit layout engine instead of Gecko due to platform requirements.
I do agree with what you’re saying though! Just those two in particular will probably have pretty good compatibility, which I was amused to find out when I looked into it.
Any suggestions on what needs to be handled here? My first thought is UA checking to see if it looks like a real browser.
https://www.rfc-editor.org/rfc/rfc7231#section-4.2.1
>The purpose of distinguishing between safe and unsafe methods is to allow automated retrieval processes (spiders) and cache performance optimization (pre-fetching) to work without fear of causing harm. In addition, it allows a user agent to apply appropriate constraints on the automated use of unsafe methods when processing potentially untrusted content.
Exactly the same for email unsubscribe links, or a one click "buy now" link.
Dead Comment
Have your logging-in session wait for / poll "has visited magic link", and authenticate that session when it's done.
Tons of systems do this. It works great, and it can quite easily work without any web browser at all on the logging-in side because it just needs to curl something -> poll for completion and save the cookies -> curl against the API. A number of oauth flows for e.g. TVs work this way, for instance, because it's a heck of a lot easier than integrating a full browser in the [embedded thing]. Many app-based 2FA (e.g. Duo) works this way too.
This works on 99% of magic links I've tried except for cases when they are trying to prevent account sharing. I remember the Bird bike app did this, where they required the magic link to be clicked on the same device login was initiated on. I was using my friends account and he would just forward me the link until one day this stopped working.
I assume it generates a session on the post-login screen and authorize that session upon accessing link
1. Some users (0.1%) just don't ever get the email. We tried sending from our IP, sending from MailGun, sending from PostMark, having a multi-tier retry from different transactional tools. Still, some people just will not ever be able to log in.
2. People click old Magic Links and get frustrated when a 6-month old link "doesn't work". We've decided to remedy that by showing them a page that re-sends the link and explains the situation (like Docusign does) instead of an error message.
3. People will routinely mis-spell their email and then blame the system when they don't get the code.
All of this still results, I feel, in way fewer support tickets than the email+password paradigm, so I'm still in favor of Magic links.
I never tried to add magix links, but I added Google Sign in to my SaaS several month ago, and since then, it accounts for more than 90% of new sign-ups (users are devs, so rather tech savvy and privacy aware). I'm now convinced that no other method is a priority (I still have email/password of course).
I do it for services I don't care about. In my mind it is more privacy for me. Keeps you out of my real inbox and my password out of your system and I believe that I can - to some extend - remove myself without having to go through whatever crap account deletion process that services has tried to cobble together.
Worst offenders let me login with google and then immediately asks for name and phone number or email and asks me to verify it.
In general, I do understand that use of SSO is due to convenience. Especially since in many cases websites provide less friction when signing up via SSO instead of using username+password.
I am shocked, shocked, by the number of different K. Strauser people who have typed that email address into some random website or another. I've gotten bank notifications, loan documents, Facebook signup info, meeting minutes from some random volunteer work, and all kinds of other things. When I can figure out from context who the intended recipient is, I try to let them know so they can fix it. On one occasion, the person sent me back a swear-laden diatribe for "hacking their email". Sigh.
I think this has made me a better engineer, though. When someone says something in a meeting like "...as long as they type their email correctly", I can jump in and address that myth head-on. No, people will not type it correctly. If it's a minor pain in the neck for me, with an uncommon name, I can only imagine the traffic that the world's John Smith's get.
Username+password (or passkeys) with a password manager (which ensures that credentials are used on the correct domain) via HTTPS is probably the only end-to-end encrypted way of exchanging credentials with good UX for general public.
90% of web apps don't handle that kind of information, and for them a magic link is at least as good as passwords (as this article explains). Those that do handle things like personally identifiable information (beyond an email address) really should be enforcing 2FA or proper electronic IDs.
There is a whole profession writing recommendations about information security, and every web developer needs to be able to do this kind of analysis at a rudimentary level. We don't need to wing it, we can analyze security requirements in a systematic way.
It's not like the rest of the customer's data is not valuable? If you don't feel comfortable storing passwords, the amount of data I'd trust you with is strictly zero.
Planning for a breach doesn't make you more likely to have one—if anything it makes you less likely!
I could understand requiring a third factor to authenticate if signing in from a different location or a different ISP than I've been using for the past 5 years, but it's ridiculous to do so if nothing has changed (except the final octet of my DHCP-assigned address) since I last signed in yesterday. I use a different computer (via SSH) to read my email than I do for web browsing, and cutting-and-pasting a signin link that's hundreds of characters long (spanning multiple lines in Emacs, so I have to manually remove \ where it crosses line boundaries) is a PITA.
Adding friction on every sign-in colors all subsequent interactions I have with an app, and makes me hate using it.
You shouldn’t get the device verification requirement if you’ve used the device before (we store a permanent cookie to check this) or for the same IP. Any chance your cookies are being cleared regularly?
We added this after attackers created clones of http://mercury.com and took out Google ads for it. When customers entered their password and TOTP on the phishing site, the phisher would use their credentials to login and create virtual cards and buy crypto/gold/etc. The phisher would also redirect the user to the real Mercury and hope they figured it was a blip.
This device verification link we send authorizes the IP/device you open it on, which has almost entirely defeated the phishers.
Since WebAuthn is immune to this style of phishing attack, we don’t require device verification if you use it. I highly recommend using TouchID/FaceID or your device’s flavor of WebAuthn if you can—it’s more convenient and more secure. You can add it here: https://app.mercury.com/settings/security
That said, we are talking internally about your post and we do recognize that as IPv6 gets more traction IPs will rotate much more regularly, so we’ll think if we should loosen restrictions on being a same-IP match.
I wasn't aware that WebAuthn didn't have this requirement. I prefer TOTP because I actually like having a second factor in addition to a credential stored on my computer's hard drive (whether a password or a private key in my password manager), but I might be willing to reduce my security posture to get rid of this annoyance.
One suggestion: the link would be half as annoying if it was easily cut-and-pasteable rather than a long email-open-tracking link spanning multiple lines. This is what it looks like when I copy it out of my email:
I have to manually remove the backslashes and re-combine the lines before pasting into my web browser.Edit to add: looks like email.mg.mercury.com is hosted by Mailgun. Are you intentionally sharing these authentication tokens with a third party by serving them through this redirect? Do your security auditors know about this?
unfortunately, only few ISPs do IPv6 correctly by assigning a fixed prefix to customers. most of the ISPs apply the ipv4 logic when adding ipv6 planning hence this situation.
hopefully this will improve in the future and more stable prefixes will be given to users.
security = 1/convenience
but also vice versa
Deleted Comment
Ricky Mondello wrote a really great blog last week[1] about how passkeys, as OP alludes to at the end, can be used alongside Magic Links, that I think is worth a read.
[1]: https://rmondello.com/2025/01/02/magic-links-and-passkeys/
The fact is that even in the best of times, e-mail isn't reliable. Things go to your junk folder. Links get blocked by work spam filters. Mailboxes get full (I assume? it's been a while).
Personally, I have my e-mail on my iPhone and anywhere else (work laptop or gaming PC) I have to log into icloud.com to check my e-mail; it's cumbersome. Let me put in a password. Let me scan a QR code like embedded devices do. Give me at least one other option.
I'm still used to Apple people being almost completely invisible publicly.
Every implementation of passkeys I've seen has presented me with the option to create a passkey after I've already logged in with some other method. I'll admit that I haven't dug into it deeply, but the UX I've been presented with consistently makes passkeys appear to be an alternative to the "Remember this computer" button, not to passwords in general. Somehow the service has to know that this new device is authorized. I know depending on the provider there's such a thing as passkey syncing, but that doesn't solve the problem of getting the initial authentication done.
The key insight with magic links is that your security system is no stronger than its recovery mechanism. We are never going to get to a world where passkeys are treated as the only authentication mechanism—there will always be a recovery mechanism, and in most cases an automated one via email. Given that that is the case, magic links simplify things by just not pretending that we have a more secure layer on top. By making the recovery mechanism the primary means by which you interact with the authentication flow you're being more honest about the actual security of your auth system.
Edit: filmgirlcw has a link to an article that is much better than this one that explains how the two actually complement each other: https://news.ycombinator.com/item?id=42628226
There are definite UX problems around passkeys that could be improved and I think exporting will make syncing across systems a lot better (one of the reasons I use 1Password as my primary password and passkey system is so I can use my passkeys across devices; of course it helps that my employer uses 1Password as our system so I am logged into my personal and enterprise accounts and can auth then from personal or work devices, provided additional auth or enrollment isn't needed) -- but if the problem as 404 defines it is that they don't want to be responsible or even have to worry about storing your passwords/auth controls, I think passkeys is at least better for a subset of users than Magic Links.
But again, like Ricky, I don't think it should be viewed as either or. It should be both.
[1]: https://rmondello.com/2025/01/02/magic-links-and-passkeys/
> though I don't know if making your email an even stronger attack vector is necessarily one of them
I'm unconvinced that magic links do make your email an even stronger attack vector. Essentially every service that would be inclined to use magic links would already have a way to reset your password entirely once the email is compromised. All magic links do is make this the primary way to interact with the auth flow.
The bad guys already know that your email is the best target. Magic links just make that very explicit.
Like what? I'm failing to come up with a single benefit (for the user).
Give it a few more years and I suspect we will start to see services start with creating a passkey and never collecting a password. The passkey portability specs will be implemented, and hopefully Gnome/KDE implement passkey support.
sigh TBH, I hope not. Maybe optionally, but for now the friction might keep companies from going passkey only, which (I think) would be a total nightmare from a security and usability perspective.
Passkeys support authentication via a secondary device over Bluetooth (and this is supported in every major browser on every major platform). So you can login to a site on a machine that’s completely disconnected from your personal passkey store by scanning a QR code with your personal phone.
The login flow basically goes “request login with passkey” -> “browser recognises it doesn’t have the needed passkey, and offers a QR code to scan” -> “scan QR code with phone” -> “phone and browser handshake via Bluetooth” -> “passkey handshake happens between website and phone” -> “login completes”.
I’ve personally used this flow with my work laptop and my personal iPhone many times. iOS has built in support for the Passkey QR codes, so you can scan the code with the standard camera app. Additionally iOS supports allowing 3rd party passwords managers to take over the Passkey flow once you’ve scanned the QR code. So in my case I complete the flow with 1Password.
End-to-end the flow is pretty damn seamless, I’ve never personally had it fail, and take 30seconds to complete. The most annoying part is trying to remember where my phone is.
Anthropic has been the once exception to this personal policy simply because Claude is the best LLM out there. But it's a mountain of pain every time I have to re-login, and I've complained to them multiple times about this.
Is it though? Majority (if not all) services I frequently use have email as recovery option for forgotten passwords.
In any case the correct approach here is to fix password reset/account recovery (e.g. with social key recovery) rather than reduce everything to the lowest common denominator.
It also can be said to lower security because it instills the behavior of clicking on links in incoming emails as a standard practice.
When links in email come into mind, so does phishing.
I hate these magic links a lot.
The point is not to click suspicious links. If you know a magic link was sent, it's not suspicious.
That being said, I hate them just for the delay.
™Kelly Shortridge 2021 (https://x.com/swagitda_/status/1503751776134180873)
Otherwise it's been a while I haven't seen an reset link instead of a reset code. Copy/pasting is not much of a hassle, and it works even if the mail is checked on a different device.
The only real link I had to deal with were app callbacks that were explicitly labeled as such (with instructions from the app to explain what to expect)
Click that stupid magic link for a service we use, and they’re asked for their Office 365 credentials… all the while I’m telling them not to click links in emails.
apple's email privacy scheme seems interesting (apple always loads all images), but I don't know if there are drawbacks.
Sites that send an OTP (crazy-pink-horse-3837) that you can copy, and paste is a good middle ground if implementing the link that just Auths the original request is too difficult.
Most sites will have a confirmation once you click the link that includes the browser version and IP address. I have seen that info only in the email itself too with no confirmation afterwords, but not for some time. Have never seen one that is just a link with nothing else that once clicked allows the other device in but supposes could be implemented that way.
The article itself is about not making them the only option (which is fair), and the OP says if they do it should login the device which originally made the request (which I agree). If the implementation is just an email with only a link, no other information with no confirmation (yes, it's fine to let this device in), then I would have to agree with you it's very risky and could allow anyone to login as you (hopefully no sites are doing this, but...)
That would let you authenticate your desktop browser from an email you opened on your phone if you're on your home network, but without becoming widely exploitable by phishers.
Deleted Comment
The phishing risks for a bank account login are very different than those for a ‘returning player’ login to a casual gaming site for example.
The victim got a phone call in which the she got manipulated into authorising something in the BankID smartphone app. But what she was actually doing was authorising the attacker to log into her online bank account.
First after several years (of blaming the thousands of victims for their millions lost) did the system start using QR codes on the screen scanned by the smartphone.
Remember that the flow the magic link is part of is one you initiate, that causes you to get an email you are expecting.
That email, and the landing and confirmation page it links you to, can explain very clearly that you are only supposed to authorize this if you are trying to log in on known device in known location that is displaying recognizable number on the screen right now.
edit: saw that nicce basically said that a second before I hit post.
OTP is far better than an actual magic link - you can still include a link that pre-fills the code.
You click the button on the page which knows the session you're logging in from and link code and does a POST which completes the login. This is how all the "login by scanning QR code" flows work.