I'm writing a small class that acts as a very basic HTTP client. As part of a project I'm working on, I'm making it cookie aware. However, it's unclear to me what happens when my client receives multiple "Set-Cookie" headers with the same key but different values are set.
For example,
Set-Cookie: PHPSESSID=abc; path=/
Set-Cookie: PHPSESSID=def; path=/
Set-Cookie: PHPSESSID=ghi; path=/
Which one of these is supposed to be the value for PHPSESSID? This usually ends up happening when you call session_start() and then session_regenerate_id() on the same page. Each will set its own header. All browsers seem to do okay with this, but I can't seem to get my client to pick the right one out.
Any ideas?!
RFC 6265 section 4.1.2 states:
If the user agent receives a new cookie with the same cookie-name,
domain-value, and path-value as a cookie that it has already stored,
the existing cookie is evicted and replaced with the new cookie.
Notice that servers can delete cookies by sending the user agent a
new cookie with an Expires attribute with a value in the past.
So I would process the headers in order given and overwrite them if there is a duplicate. So in your case you would have just one PHPSESSID=ghi.
RFC 6265 states:
Servers SHOULD NOT include more than one Set-Cookie header field in the same response with the same cookie-name.
I would therefore be very concerned if your service sends multiple Set-Cookie headers with the same key. Especially because I have seen user agents and proxies behave unexpectedly - sometimes taking the value of the first header, sometimes rearranging headers.
As a client, the typical user agent behavior seems to be to take the value of the last header. The RFC alludes to that behavior with this statement:
If the user agent receives a new cookie with the same cookie-name, domain-value, and path-value as a cookie that it has already stored, the existing cookie is evicted and replaced with the new cookie.
Related
I have a requirement where i need to invoke a SOAP Webservice operation for login and get the cookie from the SOAP response and use the cookie to invoke another SOAP operation to retrieve some data. The Login operation response has a cookie(Set-Cookie) which looks like ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax
Now how do i map this cookie to the retrieve operation. Do i map ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax fully or just ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb or just vqjucdxcxrgg5swr0f3z0peb. I tried all three options and i am getting java.lang.IllegalArgumentException: Port may not be negative error when i invoke the retrieve operation. Please let me know if i am doing anything wrong. I am using Tibco BW to invoke the SOAP operations.
Found the answer to my question in the link https://en.wikipedia.org/wiki/HTTP_cookie .Please read below
Setting a cookie
Cookies are set using the Set-Cookie HTTP header, sent in an HTTP response from the web server. This header instructs the web browser to store the cookie and send it back in future requests to the server (the browser will ignore this header if it does not support cookies or has disabled cookies).
As an example, the browser sends its first request for the homepage of the www.example.org website:
GET /index.html HTTP/1.1
Host: www.example.org
...
The server responds with two Set-Cookie headers:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
...
The server's HTTP response contains the contents of the website's homepage. But it also instructs the browser to set two cookies. The first, "theme", is considered to be a session cookie since it does not have an Expires or Max-Age attribute. Session cookies are intended to be deleted by the browser when the browser closes. The second, "sessionToken", is considered to be a persistent cookie since it contains an Expires attribute, which instructs the browser to delete the cookie at a specific date and time.
Next, the browser sends another request to visit the spec.html page on the website. This request contains a Cookie HTTP header, which contains the two cookies that the server instructed the browser to set:
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
…
This way, the server knows that this request is related to the previous one. The server would answer by sending the requested page, possibly including more Set-Cookie headers in the response in order to add new cookies, modify existing cookies, or delete cookies.
The value of a cookie can be modified by the server by including a Set-Cookie header in response to a page request. The browser then replaces the old value with the new value.
Cookie attributes
In addition to a name and value, cookies can also have one or more attributes. Browsers do not include cookie attributes in requests to the server—they only send the cookie's name and value. Cookie attributes are used by browsers to determine when to delete a cookie, block a cookie or whether to send a cookie to the server.
I'm working on making a Symfony website secure. I have taken a look at this page: How to set secure and httponly attributes on Symfony 4 session
and applied the suggested change into framework.yaml:
session:
handler_id: ~
cookie_secure: true
cookie_httponly: true
When I log in, in the network tab I see three instances of Set-Cookie. The first is a cookie removal, having secure and HttpOnly attributes. The second is a cookie creation, where the cookie identifier has the secure and HttpOnly attributes. The third is setting some parameters in an HTTP-encoded manner, this one also has the secure and HttpOnly attributes. So far so good. However, when I go to any page, I have a Cookie attribute among the Request Headers which has the same identifier as the one which was created earlier, but the secure and HttpOnly attributes are not specified.
So, when I log in and the cookie is created I have the attributes I expect, but later, on visiting separate pages I no longer see them. Why is the secure and HttpOnly attribute not specified on later, after-login Request Headers? Did I miss something?
The security attributes are set by the server in the Response headers and the browser uses them to determine if it has to send the cookie along in the Request, but it never sends the attributes themselves, just the cookie value. If you inspect an ajax or unsecure request the cookie header should not appear in the request at all.
You can see some examples in the RFC6265.
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.
is there any reason (safety?) why someone should rename the ASP.NET Session Cookie Name or is it just a senseless option of ASP.NET?
If you have several applications running under the same domain on the same server, you may well want to have seperate session cookie names for each one, so that they aren't sharing the same session state or worse still overwriting each other.
See also the notes for the Forms Auth cookie name:
Specifies the HTTP cookie to use for authentication. If multiple applications are running on a single server and each application requires a unique cookie, you must configure the cookie name in each Web.config file for each application.
1) It might (slightly) slow someone down who is (casually) looking for it.
2) You might want to hide the fact that you are running ASP.NET
Below link provides more information about why session cookies should be renamed.
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
"The name used by the session ID should not be extremely descriptive nor offer unnecessary details about the purpose and meaning of the ID.
The session ID names used by the most common web application development frameworks can be easily fingerprinted [0], such as PHPSESSID (PHP), JSESSIONID (J2EE), CFID & CFTOKEN (ColdFusion), ASP.NET_SessionId (ASP .NET), etc. Therefore, the session ID name can disclose the technologies and programming languages used by the web application.
It is recommended to change the default session ID name of the web development framework to a generic name, such as “id”."
With cookie prefixes, you can add a security attribute to your cookie by naming it a special way. So in that case renaming your ASP.NET session cookie does have an impact on security:
__Secure-… cookies can only be written from secure (HTTPS) sites.
__Host-… cookies can only be written from the same, secure domain. So not from subdomains or insecure (HTTP) sites.
According to the following specification, https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00, that modern browsers implement, the prefixes are used to make things more secure.
3.1. The "__Secure-" prefix
If a cookie's name begins with "__Secure-", the cookie MUST be:
Set with a "Secure" attribute
Set from a URI whose "scheme" is considered "secure" by the user
agent.
The following cookie would be rejected when set from any origin, as
the "Secure" flag is not set
Set-Cookie: __Secure-SID=12345; Domain=example.com
While the following would be accepted if set from a secure origin
(e.g. "https://example.com/"), and rejected otherwise:
Set-Cookie: __Secure-SID=12345; Secure; Domain=example.com
3.2. The "__Host-" prefix
If a cookie's name begins with "__Host-", the cookie MUST be:
Set with a "Secure" attribute
Set from a URI whose "scheme" is considered "secure" by the user
agent.
Sent only to the host which set the cookie. That is, a cookie
named "__Host-cookie1" set from "https://example.com" MUST NOT
contain a "Domain" attribute (and will therefore be sent only to
"example.com", and not to "subdomain.example.com").
Sent to every request for a host. That is, a cookie named
"__Host-cookie1" MUST contain a "Path" attribute with a value of
"/".
The following cookies would always be rejected:
Set-Cookie: __Host-SID=12345 Set-Cookie: __Host-SID=12345;
Secure Set-Cookie: __Host-SID=12345; Domain=example.com
Set-Cookie: __Host-SID=12345; Domain=example.com; Path=/
Set-Cookie: __Host-SID=12345; Secure; Domain=example.com; Path=/
I think its mainly a matter of taste. Some people/companies want control every aspect of their web apps and might just use another name for consistency with other cookie names. For example, if you use very short one-character parameter names throughout your app you might not like session cookie names like ASPSESSID.
Security reasons might apply but security through obscurity is rather weak in my opinion.
When you set a cookie, you set the raw cookie data, and some metadata. This metadata includes the path for where the cookie is valid, the expiration time of the cookie, and so on.
When a browser performs a request, what exactly will the browsers send with it? Will it send the full cookie, with all the "metadata"? Or only the actual data of the cookie, without the metadata?
No only the value of the cookie is returned in subsequent requests, the other metadata stays on the client.
When you define a cookie on the server a Set-Cookie header is created in the response carrying the name, value and other metadata about the cookie. Multiple Cookies will create multiple Set-Cookie headers in the response.
When the browser makes subsequent requests it checks its "database" of available cookies to see which cookies are appropriate for the path being requested. It then creates a single Cookie header in the request that carries just a series of name/value pairs of the qualifying cookies.
Its important to keep tight control on the number of cookies and the size of the data otherwise you may find that the weight of cookie data being sent for each and every request can be deterimental to performance. This would be much worse if the metadata were returned with the cookies as well.
The server sets the cookie with the "Set-Cookie" header. This contains the metadata (path and expiry), if specified. The client (browser) only sends the cookie itself in a "Cookie" header.
Firebug is a useful tool for Firefox to view all these headers. Similar tools should be available for other browsers.
only the cookie data is sent to server,other metadata is for the browser to perform some actions like cookie expiration
the user-agent will re-transmit the path, domain, and port attributes if the cookie was set under RFC2965 (via the Set-Cookie2 header) and if the attribute was specified by the server. a sample request might contain:
Cookie: $Version="1";
name="val"; $Path="/site"; $Domain=".example.com"; $Port="81";
name="val"; $Path="/site/dir"; $Domain=".example.com"; $Port="81"
if the cookie was specified using the original netscape Set-Cookie header, no attributes will be re-transmitted. if multiple cookies with the same name (but different paths) are valid for the request, all matching cookies will be supplied. an example request:
Cookie: name=val; name=val2
the full spec is here:
https://www.rfc-editor.org/rfc/rfc2965
the original netscape spec is here:
http://web.archive.org/web/20070805052634/http://wp.netscape.com/newsref/std/cookie_spec.html