I just heard about CORS, and wanted to know if it can help me in what I wanted to do.
There is a website that has CORS enabled on its server. If a user has a client session running on his browser, I wanted to access this from my server. I want this cookie to authenticate that person on my server.
Is that possible?
Can someone give me a very detailed guide, tutorial or a working example of this?
Yes, this is possible, if the server responds with the Access-Control-Allow-Credentials: true response header. This header must be set by the server in order to exchange cookies. On the client side, they must set the XMLHttpRequest withCredentials property to true. See here for more details: http://www.html5rocks.com/en/tutorials/cors/
Related
I have a setup where a client application is running on a different domain (http://www.example.com) than the server application (http://www.example2.com). I've got the cross domain AJAX requests working except that I cannot figure out a way to send cookies with the request without having to add the Access-Control-Allow-Origin response header for each possible domain. Is there a way to set this up without having to specify a list of domains in that header? I'm aware of the security implications so I guess what I'm really asking is ... is there another framework separate from CORS that I can use which will allow this type of setup and at the same time allow any domain for the client application? I tried JSONP but that did not work out (could not send the cookie with the JSONP request). Is there something else I should try other than CORS and JSONP? Thanks.
EDIT: This is not a duplicate of the question mentioned in the duplicate notification. I'm already aware of the withCredentials flag. The problem is that I don't want to have to specify a list of domains in the CORS response header. I want something equivalent to setting that value to '*', but setting it to '*' is not allowed if sending a cross domain AJAX request that contains cookies.
I am using a CAS server to secure my Spring applications which includes REST and HttpInvoker APIs.
When an application redirects to a CAS server in a different domain we get CORS
'issues'. I have added the eBay Cors-Filter https://github.com/eBay/cors-filter to the applications and the CAS server.
However...
when the application redirects to the CAS server for authentication, the Origin header is changed to 'null'. This is due to a "privacy-sensitive" context noted in the CORS spec (page 14, section 7.3).
...and, now at last...the question!
If the server receives an Origin header of 'null' can it proceed as normal, just returning 'null' in the Access-Control-Allow-Origin header?
Does this break anything?
Is it unsafe?
Cheers
Allowing null origins is unsafe. This blog post does a pretty good job of breaking down why. The short version is, it enables a form of CSRF. An allowed origin of null means "any page that redirects to me" (or any code running from a file:/// URL, but that's another topic).
Let's say your app at app.example.com uses a service at service.example.com, protected with CAS on auth.example.com. Also, let's assume you set up service with Access-Control-Allow-Origin: null so that you can make a fetch from app that points to auth with a redirect to service. Got all that? Good, you make a fetch for auth.example.com/cas/login?service=service.example.com, login happens (session cookie set on auth.example.com), redirect happens (session cookie set on service.example.com), app gets data from service. Because of your Access-Control headers, the browser lets your app read the response.
Now, imagine that you visit a malicious page (evil.com/hello) that knows about your service. They run a 302 page on evil.com/redir that points to service.example.com. Now, this malicious code can fetch evil.com/redir with credentials="include". The browser will request the redirect page, getting a 302 with ACA-Origin=https://evil.com and ACA-Credentials=true, Location of service.example.com. The browser follows the 302, requesting service.example.com and including the relevant session cookie. In this request, Origin is set to null but you've whitelisted that value, so your service sends an ACA-Origin value of null and the browser lets the (malicious) requesting code see the response. You just leaked authenticated data from your service to the injected script, which can send it home to the attacker.
Yes, I believe you can return null or the wildcard * to allow any origin.
Does this break anything?
If you're only returning null when Origin: null is received then it shouldn't affect anything else.
Is it unsafe?
I'm not familiar with CAS, however as long as you aren't sending Access-Control-Allow-Credentials too, and your CAS isn't restricted by IP or on the local network only, then this doesn't open up your system any more than anonymous access does. See this answer for technical details.
If you are, then setting Access-Control-Allow-Origin will allow other domains and origins to read data from CORS that the user visits, using their cookies for CAS.
I have a website that uses asynchronous http requests (ajax, to use the common misnomer) for performing login and registration. The authentication cookie is set by the asynchronous request and it all works great.
I recently locked down the registration and login actions to require https. Everything appears to work, except that the authentication cookie returned isn't functioning properly and the user doesn't actually get logged in.
In Chrome, in the development tools, under resources, it doesn't show any cookies having been created. If I go to the Chrome settings and view all the cookies, I can see that a cookie has been created. Perhaps it's encrypted and not readable?
So, to summarize:
The initial page is loaded using normal HTTP
The Login action is an asynchronous HTTPS request
The authentication cookie returned by the HTTPS request doesn't seem to be working
How do I get this to work?
A couple things I should note:
This is not a CORS issue.
I am aware of the potential man-in-the-middle attack. This website does not house sensitive data. I'm attempting to do something very similar (if not exactly the same) to what reddit is doing.
I managed to figure this out. Turns out that in the Http response, you need to set the Access-Control-Allow-Credentials header to true. Also, you must set the withCredentials to true on the client-side http request.
I've managed to make a CORS request on IE8 using XDomainRequest. However it seems the cookies are not sent on IE8. Is there any hack for that ? The request is made from buy.example.com to buy.api.example.com
There is no way except to include the authentication cookie value / token in the query string e.g. : buy.api.example.com/?sessionId=$sessionId&otherparameters=test and set your webservice to check the query string if cookies are not present.
There is another way. If you use SSL on the non-default https port, it will keep sending the cookies.
For example, if your URL is something like this https://example.com:8443/xxxx, then it will send the cookies.
I experience the same issue you have. My web app (internal web app) was working with https but in a non standard port and it just works fine. When I configure to use 443, it stops working because the cookies are not sent by XDomainRequest object.
I hope this will help
Can an AJAX response set a cookie? If not, what is my alternative solution? Should I set it with Javascript or something similar?
According to the w3 spec section 4.6.3 for XMLHttpRequest a user agent should honor the Set-Cookie header. So the answer is yes you should be able to.
Quotation:
If the user agent supports HTTP State Management it should persist,
discard and send cookies (as received in the Set-Cookie response
header, and sent in the Cookie header) as applicable.
Yes, you can set cookie in the AJAX request in the server-side code just as you'd do for a normal request since the server cannot differentiate between a normal request or an AJAX request.
AJAX requests are just a special way of requesting to server, the server will need to respond back as in any HTTP request. In the response of the request you can add cookies.
For the record, be advised that all of the above is (still) true only if the AJAX call is made on the same domain. If you're looking into setting cookies on another domain using AJAX, you're opening a totally different can of worms. Reading cross-domain cookies does work, however (or at least the server serves them; whether your client's UA allows your code to access them is, again, a different topic; as of 2014 they do).
Also check that your server isn't setting secure cookies on a non http request. Just found out that my ajax request was getting a php session with "secure" set. Because I was not on https it was not sending back the session cookie and my session was getting reset on each ajax request.