Are there any issues with sending back a cookie during a 302 redirect? For example, if I create a return-to-url cookie and redirect the user in the same response will any (modern) browser ignore the cookie?
Most browser are accepting cookies on 302 redirects. I was quite sure of that, but I made a little search. Not all modern browsers. Internet archive Link from a now removed/dead/ microsoft connect Q/A on Silverlight Client HTTP Stack ignores Set-Cookie on 302 Redirect Responses (2010)
I think we now have a replacement for IE6 and it's Windows Mobile browsers...
According to this blog post: http://blog.dubbelboer.com/2012/11/25/302-cookie.html all major browsers, IE (6, 7, 8, 9, 10), FF (17), Safari (6.0.2), Opera (12.11) both on Windows and Mac, set cookies on redirects. This is true for both 301 and 302 redirects.
As @Benni noted :
https://www.chromium.org/administrators/policy-list-3/cookie-legacy-samesite-policies
The SameSite attribute of a cookie specifies whether the cookie should be restricted to a first-party or same-site context. Several values of SameSite are allowed:
- A cookie with
"SameSite=Strict"
will only be sent with a same-site request.- A cookie with
"SameSite=Lax"
will be sent with a same-site request, or a cross-site top-level navigation with a "safe" HTTP method.- A cookie with
"SameSite=None"
will be sent with both same-site and cross-site requests.
One notice (to save developer's life):
IE and Edge are ignoring Set-Cookie in redirect response when domain of the cookie is localhost.
Solution:
Use 127.0.0.1 instead of localhost.
lvh.me
domain for 127.0.0.1
. It allows you to add subdomains, i.e. subdomain.lvh.me
–
Moreen Most browser are accepting cookies on 302 redirects. I was quite sure of that, but I made a little search. Not all modern browsers. Internet archive Link from a now removed/dead/ microsoft connect Q/A on Silverlight Client HTTP Stack ignores Set-Cookie on 302 Redirect Responses (2010)
I think we now have a replacement for IE6 and it's Windows Mobile browsers...
We hit this issue recently (Mar 2022) - both Firefox and Chrome didn't set the cookies immediately on HTTP 302 redirect.
Details:
- We sent HTTP 302 redirect with Set-Cookie header with "SameSite=Strict" policy and Location pointing at a different path of the same domain.
- However, the browser didn't send the Cookie in the subsequent GET request (the redirect's Location), even though it was indeed on the same domain (first-party request).
- We could see the Cookie from the browser storage inspect tab, but not in the request immediately following the 302 response.
- When we refreshed the page (or hit enter in the address bar), everything worked again, as the Cookie was sent properly in all following requests.
- We think this might be a bug / undocumented behaviour. It's like the browser stored the cookie "a little too late".
We had to work around this by serving HTTP 200 with a client-side redirect instead:
<!DOCTYPE html>
<html>
<head><meta http-equiv="refresh" content="0; url='REDIRECT_URL'"></head>
<body></body>
</html>
Here is the Chromium bug for this issue (Set-cookie ignored for HTTP response with status 302).
I just ran into this problem with both Firefox and Safari, but not Chrome. From my testing, this only happens when the domain changes during the redirect. This is typical in an OAuth2 flow:
- OAuth2 id provider (GitHub, Twitter, Google) redirects browser back to your app
- Your app's callback URL verifies the authorization and sets login cookies, then redirects again to the destination URL
- Your destination URL loads without any cookies set.
For reasons I haven't figured out yet, some cookies from request 2 are ignored while others are not. However, if request 2 returns a HTTP 200 with a Refresh
header (the "meta refresh" redirect), cookies are set properly by request 3.
samesite=strict
. For the callback request the browser still thinks that the originator is google (or whichever oauth provider you use). Hence if you set a samesite=strict cookie in your 302 response then the browser probably thinks "ah ha! this is a cross-site request coming from Google to your site" and hence doesn't send the cookie when requesting the redirected url. The fix is to use a meta-refresh as you've done, so your request comes from your own site. I could be talking crap, but that's my current thinking. –
Powered SameSite
, Domain
, Secure
will reliably send the cookie with the re-direct... –
Markley sameSite: 'strict
to 'lax'
did the trick. Thanks for the hint. –
Meras /
. SameSite made no diff which makes sense as my API is on the same site –
Bevus This is a really frowned upon approach, but if you really want to not rely on 30x set-cookie browser behavior you could use an HTML meta http-equiv="refresh"
"redirect" when setting the cookie. For example, in PHP:
<?php
...
setcookie("cookie", "value", ...);
url="page.php";
?>
<html>
<head><meta http-equiv="refresh" content=1;url="<?=$url?>"></head>
<body><a href="<?=$url?>">Continue...</a></body>
</html>
Server will send Set-Cookie with a 200 instead of a proper 300x redirect, so browser will store the cookie, and then perform the "redirect". The <a>
link is a fallback in case browser does not perform the meta refresh.
Encountered this issue while using OpenIdConnect / IdentityServer on .Net, where a separate API (different hostname) handles authentication and redirects back to the main site.
First (for development on localhost) you need to set CookieSecure
option to SameAsRequest
or Never
to deal with http://localhost/
not being secure. See Michael Freidgeim's answer.
Second, you need to set the CookieSameSite
attribute to Lax
, otherwise the cookies do not get saved at all. Strict
does not work here!
In my case I set CookieOptions.Secure=true, but tested it on http://localhost., and browser hide cookies according to the setting.
To avoid such problem, you can make cookie Secure option to match protocol Request.IsHttps,e.g.
new CookieOptions()
{
Path = "/",
HttpOnly = true,
Secure = Request.IsHttps,
Expires = expires
}
Set-Cookie
headers on 302 redirects however. –
Frazier secure=request.is_secure
in flask. –
Prevalent Request.IsHttps
. –
Indecipherable © 2022 - 2024 — McMap. All rights reserved.