mattsmith5
mattsmith5

Reputation: 1093

Java Set Security cookie using RestTemplate with Domain and as Secure

In addition to question below, how can I set the Cookie Domain and mark as "Secure"? Trying to set additional properties on Cookie.

Setting Security cookie using RestTemplate

I am trying to call a Restful JSON service using RestTemplate and Jackson json convertor. Now in order to call the service I need to pass in a Security cookie. I can achieve this by using URLConnection (See the code below)

URL url= new URL("https://XXXXXXXX");

URLConnection yc = url.openConnection(); yc.setRequestProperty("SecurityCookie", ssocookie.getValue()); Whats the parallel for this in RestTemplate? Here is a code snippet which I have been using to call a Restful Service using RestTemplate:

RestTemplate rest = new RestTemplate(); InputBean input = new InputBean(); input.setResource("SampleResource");
HttpEntity entity = new HttpEntity(input);
ResponseEntity response1 = rest.postForEntity( "https://XXXXXXXXX", entity, OutputBean.class); I can not figure out how to pass the security cookie while using RestTemplate to call the service. Any help on this would be great.

Answer Example:

https://stackoverflow.com/a/10080397/15435022

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + session.getValue());
HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
ResponseEntity rssResponse = restTemplate.exchange(
    "https://jira.example.com/sr/jira.issueviews:searchrequest-xml/18107/SearchRequest-18107.xml?tempMax=1000",
    HttpMethod.GET,
    requestEntity,
    Rss.class);
Rss rss = rssResponse.getBody();

Upvotes: 0

Views: 1159

Answers (3)

bblumenwiese
bblumenwiese

Reputation: 183

Assumptions

I assume that you are looking for a way to use cookie-based authentication to authenticate against a REST server, basically instead of accessing a web page.

I furthermore assume that you want to avoid exposing your cookie to sites that the cookies should not be sent to.

It would be pretty unusual to use cookies for server-to-server communication, but not impossible (I've hacked together a similar thing before). What you want to do sounds like exactly that, though: Setting/getting cookies from one server that then get stored and used on another server (the RESTful JSON server you want to call). I am not quite clear on whether you own the server that sets the cookie or not, and where those cookies would get used but I will try to give a good answer based on what you told us so far.

Cookie-based auth flow

Since you are talking about cookie attributes like Secure, HttpOnly, SameSite, etc., you seem to want to use the Set-Cookie header somewhere. This header is usually sent from the server to the client (usually browser but in your case the Spring application) when the client makes an initial HTTPS request to the server (simplifying a bit here).

The Cookie header carries only the key-value pairs (e.g. Cookie: JSESSIONID=...; YOURCOOKIE=...) and is used by the client to send the stored values of the cookies back to the server for their subsequent requests. Which of the cookies is determined by the browser based on what has been set in the SET-COOKIE header they received from the server.

Example flow:

  1. The Client sends an HTTPS request to the server, e.g. GET https://subdomain.yourdomain.com/do/
  2. The Server sends a reponse with the HTML of the page in the body (or in your case a JSON) and a bunch of headers, in our example Set-Cookie: JSESSIONID=<cookie-value>; Domain=yourdomain.com; SameSite: Lax; Secure; HttpOnly (or alternatively headers like Content-Security-Policy for more fine-grained control than SameSite).
  3. The Client (typically browser but might as well be your Spring application) receives all the information in the Set-Cookie header and stores them (temporarily / in the request context), along with all the cookie attributes.
  4. Upon making another request to the server, the client only sends the cookies as key-value pairs in the Cookies header. Browsers have rules that determine whether or not a cookie gets sent with a request (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent). If you want to send only the correct cookies in your Spring application, these additional attributes likely would have no effect, and you would need to simulate all the browser rules yourself, or just write custom logic for which cookies you want to actually send.

How you could try to make it work

Cookies usually get generated in a browser. A browser (client) makes a request to an HTTP(S) server and gets a response with the Set-Cookie attributes returned in the headers of the response. You could do the same with your application and just filter out the cookies you need.

The browser usually stores these cookies and you can see them in your DevTools in your browser for that page. (See for example this page for how to do this in Chrome: https://developer.chrome.com/docs/devtools/application/cookies/). Your Spring application would need to store these cookies somewhere in the Spring context. For more details if you want to reuse cookies from a request to your server, maybe this could help: RestTemplate client with cookies)

To specify a cookie that specifies for which domains, paths, etc. it is valid, you can use a combination of the following as part of the Set-Cookie fields in the HttpHeader, like Domain, Path, SameSite (for details for each attribute see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie). You can read up on how the browser validation rules work here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent

RestTemplate example code

In order to use these cookies in your restTemplate request, you can use the following code (based on your code example):

HttpHeaders requestHeaders = new HttpHeaders();

ResponseCookie cookie = new ResponseCookie("JSESSIONID", session.getValue() + "; HttpOnly; Secure; SameSite=Strict/Lax; Domain: yourdomain.com");
requestHeaders.add(cookie);

HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
ResponseEntity rssResponse = restTemplate.exchange(
    "https://jira.example.com/sr/jira.issueviews:searchrequest-xml/18107/SearchRequest-18107.xml?tempMax=1000",
    HttpMethod.GET,
    requestEntity,
    Rss.class);
Rss rss = rssResponse.getBody();

Depending on which Spring version you are using, this code may or may not work for you. I might update my response given more details

Further reading:

Closing remarks

This is my first answer on StackOverflow and I know it's gotten a bit long. Let me know what was helpful and maybe with a bit more context, I can maybe tweak/streamline it a bit more to your needs. I recently learned a lot about cookies when I had to do a similar thing as you, so I hope it helps.

Upvotes: 2

ziming zeng
ziming zeng

Reputation: 1

You can set whether the cookie should be httponly on response, as in the following code

Cookie cookie = new Cookie("SESSION", "");
cookie.setHttpOnly(true);
response.addCookie(cookie);

Upvotes: 0

Yanni2
Yanni2

Reputation: 191

I think you're talking about this. These values are thought to protect the cookie when it gets stored in the browser. For example, does the httpOnly property define that the cookie cannot be accessed by JavaScript in the frontend?.

You can set these values easily in an HTTP response with the Set-Cookie header.

For Example:

Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly

But you are sending a request. In that case can't you set one of these headers. It also won't make any sense. Why?
All these properties are thought to protect the cookie while it's stored in the browser. For example, does the httpOnly property protect the cookie from XSS attacks. The secure property should protect the cookie from getting sent through unsecure channels. Your browser will automatically send all available cookies during any request → it will also send them in an HTTP request (It won't send it over the http channel if you have set the secure property).

Upvotes: 0

Related Questions