The Change Email feature on my side-project broke a few days ago.
The usual stuff:
- user authenticates and clicks “Change email”;
- enters the new email and receives a verification link.
The trouble was that clicking the verification link would end their session. Hmm… Interesting. Even more interesting was that if I’d copy-and-paste the verification link into the browser, it would work. Hmm… 🤔
After googling a couple of days, I thought that if the URL is the same, and it works when I paste it in the browser, but doesn’t when I click it in email, then the difference must be the somewhere in the HTTP headers.
So I printed the headers as early as possible on the server, and comparing them I found that the cookies were not being sent when clicking the link in the email. Besides that there was this
Sec-Fetch-Site header that was different: when clicking the link in the email it was
cross-site instead of
same-site when pasting the URL directly. This kind of makes sense: the browser goes from Gmail to my website, so, yeah, it’s cross-site.
It somehow dawned on me after some time that this might be related to the session cookie that I vaguely recalled having a similar attribute:
SameSite; I had it set to
Yeah, that was it: because the request was going from one site to another, from Gmail to my site, the browser was adding the
Sec-Fetch-Site: cross-site HTTP header, and also was not sending the cookies with
SameSite=Strict. The fix was to delete the
SameSite attribute from the session cookie, which at the moment is the same as
Today I Learned™. 🙂