I have a web application that handles a login flow from a guest link in two steps:
We process a request to /auth/guest-link?auth=<token>; this request, on success, returns a 307 Temporary Redirect, with a Set-Cookie header that contains a session cookie.
The next page looks for the Cookie header, to find the session token.
This works well enough on desktop, and on mobile when the link is entered directly into the URL bar in Firefox.
However, when I send the link over Discord, and click the link in Discord, it opens in that weird not-my-browser thing; I think the technical term for it is Android WebView, but I'm not certain¹ (I'll call it the "mini-browser" henceforth). When that occurs, the following happens:
/auth/guest-link is successful. It returns a 307 Redirect & Set-Cookie header, normally.
The next request from this mini-browser does not send the Cookie header at all.
The cookie is SameSite=Strict, and when I relax that parameter (by removing it) for the purposes of debugging, then the flow succeeds, and this mini-browser sends the cookie normally on the second request.
Note that we're not changing domains or origins, or going from http:// to https://; both requests are https://, both requests are to the same domain name. The exact cookie construction (this in a Rust actix-web app) is:
let cookie = Cookie::build("session", session_token) .secure(true) .http_only(true) //.same_site(actix_web::cookie::SameSite::Strict) .path("/") .finish();
Is there something I'm doing wrong here? Is this just a bug in the Android mini-browser that it doesn't respect SameSite=Strict?
Edit: I've now connect to this "mini-browser" via Firefox's about:debugging tools. (So, it is definitely Firefox.) I can thus inspect the page with DevTools. DevTools shows that (a.) the session cookie is stored in the browser's cookie store (b.) the Cookie header is confusingly not sent, despite that.
¹the Internet seems to strongly suggest that I should be able to differentiate the mini-browser by User-Agent, but the request I get has the User-Agent for Firefox. The UI I see in the mini-browser even seems specific to Firefox, so I think this is somehow something that lets an app ask Firefox (or whatever the user's browser is) to render something for them. The hamburger menu in this UI has a "Open in Firefox" (but also says "Powered by Firefox), but according the Android we're in Discord. So, I'm not sure "Android WebView" is the right term for this.
This isn't a WebView bug. It's SameSite=Strict working as designed. When a link is opened from Discord, the in-app browser treats the navigation as cross-site, so the cookie gets stored on the 307 redirect but isn't sent on the next request. Typing the URL directly works because the browser counts that as same-site.
There are two ways to fix it. The first keeps Strict: replace the 307 with a 200 page that redirects itself using <meta http-equiv="refresh" content="0;url=/app">, so the second request starts from your own site. The second is to switch to SameSite=Lax and keep CSRF tokens on POST requests.