Set-Cookie in HTTP header is ignored with AngularJS
JavascriptAngularjsCookiesSetcookieJavascript Problem Overview
I'm working on an application based on AngularJS on client side and Java for my API (Tomcat + Jersey for WS) on server side.
Some path of my API are restricted, if the user doesn't have a session the response status returned is 401. On the client side, 401 http status are intercepted to redirect the user to the login page.
Once the user is authenticated, I create a session on the server side
httpRequest.getSession(true);and the response send to the client does have the Set-cookie instruction in its header :
Set-Cookie:JSESSIONID=XXXXXXXXXXXXXXXXXXXXX; Domain=localhost; Path=/api/; HttpOnly
The problem is that the cookie is never put on the client side. When I inspect cookie for localhost domain it's empty, so the next requests don't have this cookie in their header and client side still couldn't access to the restricted path of my API.
The client and the server are on the same domain but they don't have the same path and the same port number :
Client : http://localhost:8000/app/index.html
Server : http://localhost:8080/api/restricted/
Additional info : CORS is enabled on the both side :
"Access-Control-Allow-Methods", "GET, POST, OPTIONS" "Access-Control-Allow-Origin", "*" "Access-Control-Allow-Credentials", true
Any idea for making the Set-cookie works properly ? Is it an AngularJS related issue ?
Javascript Solutions
Solution 1 - Javascript
I found an issue in AngularJS that help me to move forward.
It seems that "Access-Control-Allow-Credentials" : true
was not set on the client side.
Instruction $httpProvider.defaults.withCredentials = true
was ignored.
I replace $resource call by a simple $http call with {withCredentials:true} in the config parameter.
Solution 2 - Javascript
I've managed to solve an issue very similar to yours. My Play! backend tried to set a session Cookie which I could not catch in Angular or store via browser.
Actually the solution involved a bit of this and a bit of that.
Assuming you've solved the initial issue, which can be solved only by adding a specific domain to the Access-Control-Allow-Origin and removing the wildcard, the next steps are:
-
You have to remove the HTTP-Only from the
Set-Cookie
header, otherwise you will never be able to receive a cookie "generated" by your angular code
This setup will already work in Firefox, though not in Chrome -
To make it work for Chrome too, you need to:
a) send a different domain from localhost in the cookie, using the domain your WS are "hosted". You can even use wildcards like .domain.com
instead of ws.domain.com
b) then you'll need to make a call to the domain you specified in the cookie, otherwise Chrome won't store your cookie
[optional] I would remove that /api
path in favor of a /
And that should to the trick.
Hope to have been of some help
Solution 3 - Javascript
In your post request on the client side, make sure to add the following:
For jquery ajax requests:
$.ajax({
url: "http://yoururlgoeshere",
type: "post",
data: "somedata",
xhrFields: {
withCredentials: true
}
});
With Angular's $http service :
$http.post("http://yoururlgoeshere", "somedata", {
withCredentials: true
});
Solution 4 - Javascript
You need work on both the server and client side.
Client
Set $http
config withCredentials
to true
in one of the following ways:
-
Per request
var config = {withCredentials: true}; $http.post(url, config);
-
For all requests
angular.module("your_module_name").config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push(['$q', function($q) { return { request: function(config) { config.withCredentials = true; return config; } }; } ]); } ]);
Server
Set the response header Access-Control-Allow-Credentials
to true
.
Solution 5 - Javascript
The addition HttpOnly means that the browser should not let plugins and JavaScript see the cookie. This is a recent convention for securer browsing. Should be used for J_SESSIONID but maybe not here.
Solution 6 - Javascript
Just solved a problem like this.
I was doing this and not working...:
$cookies.put('JSESSIONID', response.data);
Cookies are saved in the browser, but when I sent a new request, all the cookies were sent exept mine. (my cookie is JSESSIONID)
then i look in the chrome inspector and i found this:
THE PROBLEM IS THAT WAS NOT THE CORRECT PATH!!!
then I tried this and my cookies were sent. yay! :
$cookies.put('JSESSIONID', response.data, {'path':'/'});
I do not know if this is your case, but this worked for me.
regards!