Sending browser cookies during a 302 redirect
Asked Answered
S

9

123

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?

Swiger answered 14/1, 2011 at 17:38 Comment(1)
Reading a bit, I'm thinking that session variables would be better than cookies since they are server-side and not reliant on client predictability.Webb
F
45

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...

Feature answered 14/1, 2011 at 21:14 Comment(2)
The forum page you specified cannot be accessible with the URL. Do you mean IE6 and Windows Mobile browsers aren't?Androgynous
link has moved. I,ve set a new link with quite the same content. and I meant IE specific versions for mobile add their own set of bugsFeature
T
69

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.
Ticking answered 13/11, 2013 at 7:47 Comment(5)
Unfortunately this list does not include Chrome, so we cannot exactly say all major browsers...Baguette
@MestreLion: on my Chrome browser it works. So.. I think we can say that t it finally works now, in 2019.Epitaph
It depends on the samesite policy: With strict it still doesn't work.Ulotrichous
From Get Ready for New SameSite=None; Secure Cookie Settings, "To safeguard more websites and their users, the new secure-by-default model assumes all cookies should be protected from external access unless otherwise specified. Developers must use a new cookie setting, SameSite=None, to designate cookies for cross-site access."Yesteryear
There might or might not be bugs on that 'major' browser called Safari where cookies are not set in case they have SameSite=Lax: bugs.webkit.org/show_bug.cgi?id=219650Maggy
A
55

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.

Atheist answered 28/10, 2016 at 11:19 Comment(3)
IE and Edge may have "fixed" this so they won't set cookies for 127.0.0.1 either. Doh! And they wonder why developers don't all love IE... Your answer still ended about 4 hours of head-scratching for me. Thanks!Resplendent
Encountered this on Chrome Version 92.0.4515.159 (Official Build) (x86_64).Bloodshot
Use lvh.me domain for 127.0.0.1. It allows you to add subdomains, i.e. subdomain.lvh.meMoreen
F
45

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...

Feature answered 14/1, 2011 at 21:14 Comment(2)
The forum page you specified cannot be accessible with the URL. Do you mean IE6 and Windows Mobile browsers aren't?Androgynous
link has moved. I,ve set a new link with quite the same content. and I meant IE specific versions for mobile add their own set of bugsFeature
M
26

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>
Mediterranean answered 14/3, 2022 at 11:37 Comment(4)
Another way to fix this is to set SameSite to Lax (or remove it and it will default to Lax)Chickweed
@UladzimirShchur Removing SameSite=strict is not a fix. I'd call it workaround, since it completely changes security context of the Cookie.Mediterranean
I've got he same problem, but I'm not using the SameSite flag. I have a page that login the users and redirect them removing log parameters from url (with a Location 302 header). This could be the very firt page the user vist. 1 of 10 of this request didn't catch the PHPSESSID cookie the login fails and the second page report an unauthorized error. I've dumped the response header of the first page and the request headers of the second one and verified the Set-Cookie is present but not sent back (other cookies are present). I can't see other way that use the meta redirect.Midmost
This Chromium bug describes a similar problem, but it's not reliably reproducible (hence closed wontfix). The meta refresh approach worked for us.Drat
S
23

Here is the Chromium bug for this issue (Set-cookie ignored for HTTP response with status 302).

Studious answered 16/6, 2016 at 17:5 Comment(3)
If this is true it is really bad news indeed :-(Baguette
I think they fixed it. The bug report still says "WontFix", but on my Chrome browser it works.Epitaph
@Epitaph note that Chromium is not Chrome: lifewire.com/chromium-and-chrome-differences-4172101 - that means that while it might work in Chrome that isn't necessarily true for ChromiumJarad
E
16

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:

  1. OAuth2 id provider (GitHub, Twitter, Google) redirects browser back to your app
  2. Your app's callback URL verifies the authorization and sets login cookies, then redirects again to the destination URL
  3. 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.

Euphrasy answered 7/8, 2020 at 12:49 Comment(7)
I suspect that the reason for this wrt oauth callback issues is 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
@Powered wow thank you. I kind of suspected it had to do with this, but your comment confirmed it.Rosenthal
I am also facing this problem, but I am not able to reproduce or observed in any sub-prod environment.is there a way to reproduce this.Elaterite
I'm facing this problem. Absolutely NO combination of SameSite, Domain, Secure will reliably send the cookie with the re-direct...Markley
For me changing the cookie from sameSite: 'strict to 'lax' did the trick. Thanks for the hint.Meras
Same issue - setting a cookie before redirecting to the oauth page works, but setting one on the oauth callback route before redirecting back to the UI doesn't. Changing SameSite to lax or none doesn't work for me.Bevus
Actually all I needed was "Path=/" which I thought could be omitted for /. SameSite made no diff which makes sense as my API is on the same siteBevus
B
11

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.

Baguette answered 30/7, 2019 at 15:26 Comment(0)
S
4

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!

Sulfonate answered 1/9, 2020 at 15:23 Comment(1)
To clarify a bit - the cookies do get saved. They just don't get sent to the next request, so it looks like they aren't getting saved.Maryalice
L
2

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
                }
Landes answered 2/10, 2017 at 12:25 Comment(3)
In that case don't set the secure flag. The whole point of the flag is to tell the browser to only use the cookie when connecting over HTTPS. Conditionally setting the flag changes the semantics somewhat, and you lose the cookie transitioning from HTTPS -> HTTP, but not when going from HTTP -> HTTPS. All this is orthogonal to what browsers do with Set-Cookie headers on 302 redirects however.Frazier
That time when the answer with -3 votes solves the problem. I was setting Secure=true, but forgot that on localhost I'm just using http to test it with. Noob mistake. Use secure=request.is_secure in flask.Prevalent
I think this should be safe enough when your production server is only accepting HTTPS, no HTTP. Still, it could be more robust to use a different way to test if you are testing a production server or not than by checking Request.IsHttps.Indecipherable

© 2022 - 2024 — McMap. All rights reserved.