next-auth: Signing in using magic link with Outlook email when SafeLinks enabled does not work
Describe the bug
Signing in with an Outlook email which is linked to an account where the SafeLinks premium feature is enabled does not work.
Another authentication library seems to have the same issue: https://github.com/FusionAuth/fusionauth-issues/issues/629.
When this Outlook feature is enabled, the magic link is encapsulated by a SafeLinks Outlook protection URL, e.g.:
https://eur02.safelinks.protection.outlook.com/?url=<magic-link-url>
From the issue in FusionAuth, it seems that the token gets invalidated because of some request that SafeLinks is being made beforehand. (Source: https://github.com/FusionAuth/fusionauth-issues/issues/629#issuecomment-629157742)
Steps to reproduce
- Sign in with Outlook email which has
SafeLinksenabled - Click on Sign link from email
Expected behavior User should be able to login
Screenshots or error logs
None. The user gets redirected to /auth/sign-in?error=Verification
Additional context /
Feedback
- Found the documentation helpful
- Found documentation but was incomplete
- Could not find relevant documentation
- Found the example project helpful
- Did not find the example project helpful
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 6
- Comments: 20 (6 by maintainers)
Just wanted to say for the record and for anyone else - I came into this issue (I run a platform using NGINX on the front, as a reverse proxy for a Django application, but the principles are the same for any stack) and here are some options for sorting it:
Anyway yes, annoying bug but but the solution for me was to handle the HEAD requests in the endpoint and pass them somewhere else, which doesn’t invalidate your tokens by completing the GET operation by accident.
Solved for me on both Outlook web client and desktop client with SafeLinks enabled.
Just adding in for anyone else coming in from google and experiencing this:
I’m seeing this issue with a lot of my corporate clients who rely on outlook. Organization protocol mandates SafeLinks, which screws them up, and invalidates their Login Via Email.
Would be great to see support for this merged into NextAuth out of the box!
I’ve done a bit more research, and it seems that Microsoft makes a HEAD request to the URL in the query params (our magic URL) before hand therefore “using up” the magic code and invalidating it for the user.
The fusion auth issue thread is pretty detailed / lots of discussion back and forth. A quick fix that seemed to work was to simply ignore HEAD requests in the invalidating magic code logic.
An Opencollective maintianer posted in that thread as well saying they’d had to work around a similar issue with outlook.com robots, and linked a PR through which they were able to get around the issue - https://github.com/opencollective/opencollective-frontend/pull/5476
Workaround Nr. 2 - the office365 admin can also apparently whitelist URLs which do not get this “safelink” treatment, so @dweemx, for now you cuold whitelist your application’s domain in order for magic link emails to work again in the short-term
As the GET and HEAD filtering doesn’t seem to work and Microsoft 365’s way of checking links is changing more often than an influencers mood and profile picture, isn’t there a more robust way of filtering the requests? Like the “Referer” header value… Does Microsoft 365 and other link checkers really have the site URL as “Referer” in the request? If not, then the easiest way might be to just ignore the POST/GET/HEAD method and all other values that probably will change, and concentrate on this one. Or is the “Referer” header value empty/invalid for the authentication request when the link is clicked? Also… If this issue is closed, was a solution found? Will it work for the next-auth 4.18.7+?
UPDATE: safe links no longer sends a HEAD request, instead it sends a GET with a very useful headers
user-agentandx-native-hostwhich containOneOutlooksomewhere in them.example headers from the new outlook on windows 11:
So I ignored every request with
OneOutlookin the mentioned headers, and it worked!example in Nuxt 3
You might wanna check for the email’s specific callback endpoint, but I’m not sure if there’s anything else that sends those headers.