Seen this before here, but I've seen no real resolution. The server's Node Express express-session module OR cookie-session module sends back a Session Cookie, but as I had not coded in the SameSite/Secure attributes, they are not there and do the client on a subsequent POST to the server fails as Not Logged In, with a 403. As expected.
First, my client logs in to the server successfully:
Here is the corresponding server code, using express-session:
Which produced a Session Cookie via the Set-Cookie. NOTICE the SameSite='none' and Secure=true attributes were not included, and as expected, not there.
Now, I have added the sameSite and secure attributes to the session object and run the Login again.
Lets look at the Response Headers returned from this Login, with the attributes added to the session object. Not only do we not see the attributes on the Set-Cookie Response Header, but there is NO cookie returned!
It appears that when these 2 attributes are added to the session object in either express-session or cookie-session that the result is no cookie is returned. The meaning being that a subsequent POST to the server will return a 403, User Not Logged In.
I'm really stumped. I've spent a LOT of time on this! Thank you for ideas and help.
You seem to be misusing the cookie-session middleware. The cookieSession function takes an JavaScript object but the documentation doesn't mention any cookie field in that object.
Anything specified in a cookie field is ignored by the middleware and has no effect on the resulting cookie; the only reason your cookie ended up being flagged HttpOnly is that it's the middleware's default behaviour.
Instead, all the cookie attributes should be specified in a "flat" object, like so:
app.use(cookieSession({
name: 'session',
secret: secret,
domain: 'chicagomegashop.com',
sameSite: 'none',
secure: true,
httpOnly: true
}));
However, you have another issue. If I'm interpreting your screenshots correctly, you seem to attempt to set a cookie with a Domain attribute of chicagomegashop.com in a response from https://paylivepmt.com. That cannot work; browsers will ignore such a Set-Cookie response header:
The user agent will reject cookies unless the Domain attribute specifies a scope for the cookie that would include the origin server.
Not all the cookies shown by Chrome Dev Tools as part of the Request Header are found in the HttpServletRequest object.
Here is a screenprint from Chrome Dev Tools, showing the request headers for the GET HTTP request.
You can see that the "cookie" includes the "_fbp" cookie:
cookie request header
From the Chrome Dev Tools application tab, you can see that the "_fbp" cookie is from my same Domain and has not expired and is for Path / so it should be included (which it was):
cookie details
We're running a Java Spring MVC backend and when the request comes to the controller endpoint, we have the "HttpServletRequest request" parameter.
Examining that "request" object, I find that it has some of the cookies which were observed as part of the request, but not all of them... and specifically not the "_fbp" cookie I'm looking for.
Tried examining the cookies in all the following manners:
Object rhc = request.getHeader("Cookie");
Cookie wuc = org.springframework.web.util.WebUtils.getCookie(request, "_fbp");
parameter #CookieValue(name="_fbp", required=false) String fbpCookie
but no matter how I inspect that request, the "_fbp" cookie is not there. I noticed that most of the other cookies that are not found all have names beginning with underscores so I suspected maybe that is a naming convention that is ignored by Spring MVC but couldn't find any such rule.
Can anyone help explain the missing cookies? How can I get that "_fbp" cookie value for server-side processing? Appreciate any help.
Ive made some configurations to (finally) have my cookies set on HTTP only.
"Seem" to work.
Ive tried them with postman and I have the following:
When I hit the login page:
On the cookies section, my cookie with name JSESSIONID appears to be HTTP only (it has the check)
When I enter to the logged area , the same result...
The headers dont give me more details.
Then,
I check it with google chrome. I open the developers toolbar.
I load the login page.
At the headers on the response headers I get
Set-Cookie: JSESSIONID=434434..... HttpOnly
So, its fine (I guess).
Then I reload the page (or sign in).
Then the problem:
No response headers received.
The Request Headers brings my cookie (with the same ID at then the previous one) without the httponly, host info or any other cookie value I set before.
At the cookies tab I get Request Cookies only and no Response cookie.
And the request cookie is non http-only
At my resources tab, the Cookie is there, as HTTP only and with the previous values I set.
My question now is... Is it a really http-only cookie? Or my configuration is not properly set?
Should I always get the response cookie or the request cookie should be always http-only (In case I am trying to set it as http-only) or is this behavior normal (or at least accepted) ?
When I try to print my cookie with Javascript at both scenarios I get a null as response (what makes me think then it is correct).
Ideas?
Client doesn't send cookie attributes other than name and value back to server.
See also RFC6265 section 4.2.2 (emphasis mine).
4.2.2. Semantics
Each cookie-pair represents a cookie stored by the user agent. The
cookie-pair contains the cookie-name and cookie-value the user agent
received in the Set-Cookie header.
Notice that the cookie attributes are not returned. In particular,
the server cannot determine from the Cookie header alone when a
cookie will expire, for which hosts the cookie is valid, for which
paths the cookie is valid, or whether the cookie was set with the
Secure or HttpOnly attributes.
Everything's behaving as specified.
We have a site where we are using cookies for tracking purposes. Now we are thinking in changing the domain of our site but we will want to still recognise User's sessions from the old domain. Is this possible?
You can't retrieve cookies that belong to other domains. As a workaround (in case you can still use the old domain); by creating an iframe inside http://newdomain.com from http://olddomain.com, you can get cookies and send to parent via postMessage.
Cookies are affected by same origin policy but you can bypass it with CORS (Cross-origin resource sharing).
CORS is a play between browser and server.
Basic idea is allow ajax request to cross domains but you can use to share cookies(security measures should be taken).
Browser send a request with Origin header.
If the server allows the request then it reply with Access-Control-Allow-Origin header with the value of origin.
If the server doesn’t reply with the header or don’t match Origin with Access-Control-Allow-Origin browser disallow the request.
But it doesn’t send cookies or something like that by default(you have to add “allow-credentials” extra header).
With CORS you can share the session between domains adding to new domain server the following headers:
Access-Control-Allow-Origin: https://original-domain.com
Access-Control-Allow-Credentials: true
More info about CORS:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
http://quickleft.com/blog/cookies-with-my-cors
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?
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.
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...
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.
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>
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>Continue...</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
}