HttpClient 4.x: how to retain cookies across multiple requests? - authentication

I need to use Apache HttpClient (4.x) to make 3 consecutive web calls and essentially log me into my app programmatically:
An HTTP GET to a login page (http://myapp01.example.com)
The server will respond to this GET with a response cookie "JSESSIONID"
An HTTP POST to the same page (using the same JSESSIONID as a request cookie)
The server now authenticates me and validates the JSESSIONID.
An HTTP GET to a different page under the same domain (http://myapp01.example.com/fizz), again using the same JSESSIONID as a request cookie
The first GET's response will contain a cookie named JSESSIONID. The POST will then log me in to the server (sending username and password data in the POST request body). This POST will also send (Set-Cookie) the JSESSIONID cookie received from the first GET. If my logins are successful, the JSESSIONID will now be authenticated, and I am logged in. I can then make the 2nd GET call (still using the same JSESSIONID) to /fizz which is ordinarily an authenticated URL.
Can this be done in HttpClient 4? I see there is a method HttpClient.getCookieStore(). but this seems to only store cookies per GET/POST/PUT/etc.
Any ideas as to how I can get this holding cookies across multiple requests, such that any cookies returned by the server are then added to subsequent requests?

Apache HttpClient takes care of that automatically (since version 2)

Related

REST API - SAML Authentication with Azure AD as IDP

Having application with SAML authentication along with Azure AD as IDP. When I hit Login SSO button the following happens:
Hits SAML Redirect URL (/Saml/SAMLLoginRedirect)
Redirects automatically to Ping Federator. Redirected URL is received with the response header of the first request. URL consist some SAMLRequest Token and RelayState value. Final response has Submit Form along with new SAMLRequest token and RelayState.
Hitting IDP (login.microsoftonline.com//saml2 with the SAMLRequest and RelayState from the final response not works as expected.
I have resolved this issue in jmeter. I have just enabled Follow Redirect so jmeter provides the response and cookie. I am extracting the Header value of first the request from URL. It is just because Jmeter has the feature of accumulating redirect sample into the original request.
So I am again hitting Ping Federator with the Token and RelayState received using URL extractor along with final response Cookie.
Further I am able to complete the IDP process successfully.
I am not able to achieve the same using RestAssured. When I disable redirect I am able to get the url from header. Processing the URL from the header value throws 500 error code though I have added the cookie information.
If I enabled redirect I am getting 200 response code along with expected response body and cookie.
But I am unable to proceed to the Ping Federator with the token and relay state received from the response. So I have to hit again the Ping Federator with the previous SAML Token again as I did with jMeter to achieve the proper response.
Problem: Unable to get the header value if I enable the redirect and further processing fails. If I disable the redirect then I am not getting Cookie and expected response when processing the URL from header value. Here all are GET request until the IDP (login.microsoftonline.com)
JMeter's HTTP Cookie Manager automatically extracts cookies from the Set-Cookie response header and sends them with the next request via Cookie request header if domain and path match and the cookie isn't expired.
RestAssured doesn't do this automatically so you will need to extract the cookies from the response and add them to the next request manually.
References:
REST Assured Tutorial 49 – How To Retrieve Single and MultiValue Headers From Response Using Rest Assured
Headers, Cookies and Parameters with REST-assured
Going forward you can just use a sniffer tool like Fiddler or Wireshark to compare requests coming from JMeter and RestAssured, given you send the same request (apart from dynamic parameteres which need to be correlated) you will get the same response

Handling cookies in HTTP request in Jmeter

I have a Jmeter load project the requires retrieving 2 values of cookies and resend them in the other requests.
Here is my project test plan:
-Test Plan
-Thread Group
-Login request
-Payment page
-Payment history page
-HTTP Cookie Manager
-HTTP Header Manager
-View Results Tree
Cookie Data:
JSESSIONID=0000SZb55xyLAaqLlDzumq_PpIw:-1; XSRF-TOKEN=a684e233-648e-4219-ae21-25fb362e232d
The cookie data is received successfully from the login request by cookie manager and sent in the second request (Payment page) but in the third request (Payment history page) only JSESSIONID is sent and I don't know why the second cookie is not sent in the third request.
Most probably you are not getting this cookie in Set-Cookie response header for second request therefore it doesn't get picked up by the cookie manager. If your application expects the cookie in 3rd request it might be your application issue.
As a workaround you can store the cookie value into a JMeter Variable for later re-use.
Add the next line to user.properties file (lives in the "bin" folder of your JMeter installation
CookieManager.save.cookies=true
Restart JMeter to pick the property up
That's it, now you should be able to refer cookie value as ${COOKIE_XSRF-TOKEN} where required, for example add another HTTP Cookie Manager as a child of the 3rd request (according to Scoping Rules "local" cookie manager will override the "global" one) and define XSRF_TOKEN and other cookies if needed there)
See Using the HTTP Cookie Manager in JMeter article for more information on handling cookies in JMeter tests.

JAX-RS, RestEasy: No session cookie

Folks,
Used to be that when you hit a servlet/jsp, the app server would automatically start a session. It would put a session cookie in the first dynamic response that would get tracked throughout.
I have a rest backend and I notice that no session cookies are being traded. So I manually add code to send the JSESSIONID cookie:
#Context
private HttpServletRequest httpRequest;
// ...
#GET
#Path( "/{rcpGuid}" )
public Response myMethod( ... )
{
final HttpSession session = httpRequest.getSession();
final String sSessionId = session.getId();
...
return Response.status( Response.Status.SEE_OTHER ).
location( redirectUrl ).cookie( new NewCookie( "JSESSIONID", sSessionId ) );
}
Now this is causing 2 copies of the JSESSIONID cookie being returned where before there was no Set-Cookie header. This is what I see now in my browser's inspector:
Set-Cookie:JSESSIONID=sdm-Q1P6pRoQbKd4-9cJylGb; Path=/nn, JSESSIONID=sdm-Q1P6pRoQbKd4-9cJylGb; Version=1
I don't care as long as this would work. But unfortunately, when my browser requests the URL being redirected to (notice that the response is "SEE_OTHER"), that request does not bear the session id. This causing my app to not function right.
Any insights?
Used to be that when you hit a servlet/jsp, the app server would automatically start a session. It would put a session cookie in the first dynamic response that would get tracked throughout.
The app server doesn't create a session until httpRequest.getSession() is called.
I have a rest backend and I notice that no session cookies are being traded. So I manually add code to send the JSESSIONID cookie:
In your example, you call getSession() and create a separate jsessionid cookie. That would explain why you have two cookies. If you do neither, you wont have a jessionid at all.
If it is a REST back-end, so you should not have JSESSIONID cookie and keep your back-end endpoints as Stateless.
All informations required to get a result from one of your web service should be contained in the request to the web service. A web service is idempotent.

JMeter Cookie Manager

I am using JMeter to make a simple login test on my website. I have a Thread Group which contains a Cookie Manager, an HTTP request to the root page, then an HTTP Post which posts a username and password, and then a Results view. When I run the test and view the response, the results show that the first HTTP request correctly calls set-cookie with the JSessionID, but the second HTTP request that POSTS credentials has no cookies - shouldn't this cookie be posted from the Cookie Manager? Thanks.
In most apps that I've tested, I don't see the actual cookie information after the initial request.
If your session isn't being maintained, there are a few quick things to check:
1. there are no hard coded JSessionID values in the HTTP Requests;
2. try different cookie manager types - different applications expect different settings.

XMLHttpRequest Basic Auth, second request

normally browser stores and adds authentication header automaticly after successfull authentication.
I have a XMLHttpRequest and added the authentication header for basic auth. No problem at all.
Then I try to send a second request to the same url that is basic http protected without adding manually the http request header to this request. Poorly it seems that the browser is not storing the authentication provided in request 1. My goal is to add the authentication handler transparently to every request that follows the first one (like a native browser do).
Any idea? Thanks.
Browser only storing authetication requested from user. So, if you send 1st request w/o authentication fields, browser will prompt user for auth this time, remember credentials and use it for next requests transparently.