Apache CXF not handling cookies with "Expires" directive? - cookies

We use SUN Jersey client to consume some REST services and Apache CXF to serve some REST services, in the same java project. Some of the services we consume return cookies with "Expires" directive set. For eg Set-Cookie: name=value; Expires=Wed, 09 Jun 2021 10:18:14 GMT.
Consider the below code, assuming wr is a Jersey WebResource. ClientResponse is also a Jersey class.
ClientResponse resp = wr.get(ClientResponse.class);
System.out.println(resp.getCookies())
Now, in the case of cookies with expires directive, the actual cookie is not returned. Instead, the expires directive itself is returned as the cookie (cookie's name is Expires, value is the date).
After some digging, we found that this is due to the way the Set-Cookie HTTP header is parsed by CXF. Please refer the fromString method here. Basically, the code considers the last <name>=<value> pair it finds in the Set-Cookie header to be the cookie. In this case, expires=<date> occurs after name=value (latter being the actual cookie needed).
OTOH, Jersey's header parsing code here (the actual impl class is here, and it calls the former) returns the actual cookie, ignoring the expires directive. This behavior is good enough for us. So we'd like to choose Jersey's version. How do we do this? Please note that we also need the project to still use CXF also (to serve services), so the dependency cannot be removed.
The project in question is a Maven project.

Related

Why isn't this cookie sent to other subdomains?

We have an authentication API for signing in and a file download API that serves protected files.
The authentication API lives at authentication.api.mysite.com and returns the following header on a successful sign-in:
Set-Cookie: sessionId=QpiYzBXNNhiMZQSdWfKiDM; SameSite=None; Secure; HttpOnly; Domain=.mysite.com
(I have also tried Domain=.mysite.com, i.e. with a leading dot, without luck.)
The file API lives at files.api.mysite.com and allows clients to download protected files given the following request header:
Cookie: sessionId=QpiYzBXNNhiMZQSdWfKiDM
The APIs are used by a web app that lives at something.othersite.com. In the browser dev tools, I see that the sign-in response has the cookie in the "Cookies" tab, so I know it's set. And the cookie is sent to other requests against the authentication API. But no cookies are sent in requests to the file API.
As I understand it (e.g. MDN), if Domain is set to mysite.com (or .mysite.com judging by some other sources) then it should also be sent to api.mysite.com and whatever.api.mysite.com. But it's not sent to other subdomains.
What are we doing wrong? How can we get the browser to pass the cookie set by the authentication API on to the file API?
In case it's relevant: Both APIs use CORS, set up to allow the specific host we're using (not wildcard), allow any method, allow any header, allow credentials, and expose a set of headers I don't think is relevant (Set-Cookie isn't included there, but it made no difference when we added it).
The cookie was correct; the problem was caused by how the front-end called the APIs. The front-end uses axios, and the solution was to use the withCredentials option, e.g.:
axios.post(
url,
data,
{ headers: headers,
withCredentials: true }
)

Are some top-level domains (like amazonaws.com) prevented / blocked from being used as cookie domain?

We have a simple service running in EC2. We are testing setting our cookies with domain ".amazonaws.com", but it's not working correctly.
The cookie and domain are being set:
Content-Length:62
Date:Tue, 15 Apr 2014 10:26:55 GMT
Server:Apache-Coyote/1.1
Set-Cookie:test=alfie; Domain=.mycompany.com; Expires=Sun, 27-Apr-2014 00:13:35 GMT; Path=/
Set-Cookie:test2=alfie; Domain=.amazonaws.com; Expires=Sun, 27-Apr-2014 00:13:35 GMT; Path=/
If we request using xxxx.yyyy.mycompany.com, the cookie appears in Resources (Chrome tools) and is resent on the next request.
However, if we request using host xxxx.yyyy.amazonaws.com, the response is the same but the cookie does not appear in Chrome tools and is not resent.
Removing the domain (so that cookie uses fully qualified hostname) works fine in both cases.
Clearly using .amazonaws.com as the domain is a Bad Idea, but it seems strange to me that it doesn't work, as it implies this restriction is being enforced by Chrome somehow (and other browsers - Firefox shows the same behaviour).
Or it is something else basic we are missing?!
Thanks, Alfie.
Yes. Browsers don't let you set cookies for what they consider to be top level domains, for example you can't set a cookie for .com.
There's not a hard and fast rule you can use for determining whether a domain is a top level domain - it's up to the registrar where they allow registrations, so you pretty much just have to create a list.
You can see the list of domains Firefox considers to be top level domains in the Firefox source code. Among other things there are a bunch of amazon related ones.

Facebook Login using Jmeter

I want to do a load test my Heroku application using Jmeter.
To access the functionality of the application, I need to login through Facebook first.
I tried with browser recording using proxy server. But the problem is the code parameter (response_type) returned by facebook is hard coded in the callback URI. So its giving exception (Code expired exception) while running the Jmeter script.
I am able to view the code in response header of https://www.facebook.com/dialog/permissions.request URL. So I need to grab this code from this header dynamically and put in the code parameter of callback URL.
For this I am using Regular Expression Extractor in Jmeter under /dialog/permissions.request URL.
My response header looks like below:
Cache-Control private, no-cache, no-store, must-revalidate
Date Wed, 26 Dec 2012 13:37:17 GMT
Expires Sat, 01 Jan 2000 00:00:00 GMT
Location http://myapplication.herokuapp.com/oauth/authenticate/facebook?code=SOME-CODE
P3P CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"
I want to extract this code=some code and put it in the next URL using regular expression extractor.
I don't know the JMeter context, but the regex can be something like:
\?code=(.*)
You might need to double the backslash. The $ can be problematic if the header is checked as a whole, you can replace it with \n perhaps.
[EDIT] I found the tester pointed from the JMeter page and used it against the header content you gave. Apparently the $ was not necessary, the search is stopping on a line bound. Still not sure about doubling the backslash. Experiment.
Problem is not with Regular Expression Extractor as mentioned by Saswat Sahoo. Main problem is Location header not even getting in Response header of Jmeter. We can see Location header in Browser's response header. Few information are missing in Jmeter Response Header compared to Browser's response header.

apache camel | jetty | Content-Type should be set on response if provided as OUT header

The Content-Type is not set in HttpBinding if an end-user has provided one as a OUT header.
So if an user exposes a Jetty service and lets requests fly in that is text/plain and want to return a response that is application/json or application/xml or the likes the content type can not be set as:
exchange.getOut().setHeader("Content-Type", "application/json");
Camel Version: 2.9.2
Camel Jetty Jar Version 2.9.0
Problem statement: Although I include the statement setHeader("Content-Type", "application/json"); or setHeader("Content-Type", "application/xml");, upon debugging I can see the following behaviour.
1.) Class "DefaultHeaderFilterStrategy", method "doFiltering" contains "Content-Type" as one of the filters to skip. Thus it removes the "Content-Type" from header if mentioned explicitly also.
Can you try with Camel 2.9.4 as we have fixed a number of bugs since that release.

How can I set a cookie in a request using Fiddler?

I need to set a cookie before I issue a request to a Web site using Fiddler. How do I do this?
Simple...You need to set a header value, with your request, like so:
Cookie: YourCookieName=YourCookieValue
To do this using the FiddlerScript engine, add the following code into the onBeforeRequest method:
oSession.oRequest["Cookie"] = (oSession.oRequest["Cookie"] + ";YourCookieName=YourCookieValue");
This will preserve any other cookies that have been set.
You need to be more specific about what you're trying to do.
You can edit (or add) an outbound Cookie header to send a cookie to the website. You can do this either manually or via the FiddlerScript engine. But that doesn't "set" the cookie on the client-- it simply sends it to the server. If you want to set a cookie on the client, you either have to use another means, or you can inject a Set-Cookie response header on a previous response from the server, with the value you want to set on the client.
You can also use the Fiddler Composer.
Run Fiddler
Open the Composer Tab on the top.
It's easiest if you can start with another request from your web site. To do this capture a the request you want to modify, then drag it from the UI to the composer tab.
A good explanation is here: http://www.debugtheweb.com/Fiddler/help/composer.asp
Fiddler allows your to resend/rebuild an existing request. There is a Request Builder. While rebuilding in the RAW form, modify your cookies.
This solution is valid for Cookie based authentication:
If you want to test the API/url which have authentication enabled, please try following, i am showing for MVC web API on IIS server. usually there are more than 1 cookie responsible for authorization, so you may need to send more than 1 cookie in header as follows:
User-Agent: Fiddler Host: localhost:51000 content-Type: application/json Cookie : .ASPXAUTH=xxxxx;ASP.NET_SessionId=yyyy;__RequestVerificationToken=zzzz
When running Fiddler as a reverse Proxy you can modify the response headers
via FiddlerScript by adding a line in the OnBeforeResponse method:
static function OnBeforeResponse(oSession: Session) {
// ...
oSession.oResponse["Set-Cookie"] = "sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT";
}
Also check Fiddler docs about Modifying a Request or Response for more info.