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 Strict
.
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 SameSite=Lax
.
Today I Learned™. 🙂