I'm coding up a webapp with this exact login process - the issue I've found is on mobile phones - apps like gmail won't let you copy the link into a browser without a preview. The preview consumes the link. (next.js auth)
It's a bit annoying, since I don't want to login into the gmail in-app browser, I want to login on my regular browser.
Don’t forget some people have antivirus scanners that will load up every link when the email is opened, so you can’t have the link expire after 1 visit.
This is I think why unsubscribe links now have a single button saying “Unsubscribe” or similar when you press them. Likewise anything interesting should require a 2nd user action after loading the page.
Yes easy mistake to make. But this goes back to HTTP basics: a GET request shouldn’t mutate state. Either don’t consume the link (ie allow reuse), have a user confirm action with POST, send a code instead. There are many alternatives.
Personal favorite? Send a 6-digit code with ~1h expiry, exchange for a refresh token and keep the session for a long time. If you have really high value irreversible actions then you can just confirm with a new code.
Also works if mail client is on a different device.
A work around could be: login link token is good for 24hours unused, or 5mins after the first use. That way you don’t leave the user in a loop or risk them not clicking the link within a short amount of time. The token still expires after a reasonable duration too.
Pleas don’t force this login method. It is extremely annoying for anyone with a non-standard email setup (often for security reasons), and is slow as all hell.
It's a bit annoying, since I don't want to login into the gmail in-app browser, I want to login on my regular browser.