I'm struggling with CORS and a SSO configuration between two WAS servers using LTPA key share.
CORS calls from server1 (domain1) to server2 (domain2) work fine if I don't have authentication on server2 (meaning the cross domain Ajax call works), but it doesn't if I have.
The context is: The web client logs into domain1, one part of the UI needs to display some data coming from server 2 (domain2). Server 1 and server 2 share the same LTPA key with the same realm. That works fine, I can make manual calls (with curl for example) to domain2 using the LtpaToken2 from the webclient obtain from domain1.
The problem is: When I make the CORS call from the web client, I use withCredentials to true, but withCredentials includes cookies from the remote domain, and of course I have no cookie yet since the browser does not know the domain2 yet. What I need to do is include the LtpaToken2 cookie from the local domain (domain1) when doing the cross-domain ajax call to domain2. That way I will be authenticated. But because of the cookie cross domain policy I'm stuck.
Am I approaching the problem in the wrong way here? How would you handle that: doing a CORS call to a yet unknown domain using the LtapToken from the local domain?
Thank you very much for your help!
Related
In my Controller, which is build with using spring-boot, I've enable CORS only for my server and localhost whit this annotation:
#CrossOrigin(origins = {"http://localhost:8080", "https://www.somepage.com"}, maxAge = 3600)
This is working fine. But now I'm not sure, if it's also needed, to add basic authentication for the REST API. As far as I understood, the only call the REST API is accepting now, is my own server and localhost, and that's why, I think it's not needed. But I was not able to figure out, if this is a bad practice or not.
Do You recommend to use basic auth too for the REST API even when CORS is enabled?
No.
The Same Origin Policy is a feature built into browsers that prevents an attacker's JavaScript running on the attacker's website from reading the response to an HTTP request from the victim's browser to the targetted website.
This stops the attacker from stealing data from the targetted website using the credentials belonging to the victim.
(To some degree. There are other kinds of attacks.)
CORS is a tool that relaxes this rule so that when you to allow another site to access that data (either using the user's credentials or because it is just public data), it can.
Note that I said "a feature built into browsers". It isn't built into other tools.
An attacker can still make HTTP requests with their code, or tools like Postman and curl, or their own web browser.
Neither the Same Origin Policy nor CORS are substitutes for authentication and authorization.
CORS is a mechanism implemented in browsers and it will not prevent me to access your API with curl. Therefore, secure your API if you need it to stay secure.
I have two Spring boot applications one is a client UI app and the other acts as an Authorization Server (using spring security oauth, implicit flow and form login).
When the two applications run on localhost (different ports) I can see the following flow:
The client makes a request to oauth/ahthorize to retrieve a token.
Since the client is not authenticated the server responds with a 302 redirect to its login form, setting also two cookies (XSRF, JSESSIONID).
The user enters his credentials and a POST is performed in the login form. Since the two apps run in localhost the two Cookies are sent in the POST request.
This way, the server retrieves the SavedRequest for this JSESSIONID and performs a redirect to the saved client url, as expected.
The problem is when running the two applications in different domains (I am trying to run it in Pivotal Web services environment).
The JSESSIONID cookie is not sent on POST of the login form.
This makes sense because the cookie was set for the client domain, whereas the login form is in a different domain and does not have access to the cookie.
This has as a result that the server does not find a SavedRequest object to retrieve the redirect URL
of the client and it redirects to the root of the server (/)
What am I missing?
EDIT: here is the POST on the login page on localhost (working scenario):
and here is the POST when domains are different (not working):
EDIT 2: Here is the authorize request, which is made to the client domain (and proxied to the server through Zuul:
I am building SPA with thin server architecture (in my case it mean: webserver role restricted to server static content and route xhr with backend REST services):
so far I failed to find any example that provide user authentication scheme that cover my requirements, when it comes to user authentication all what I see webserver (server side code) involved whether its php/nodejs/asp.net..etc.
I want to build the authentication with zero dependency on server side code that belong to webservers:
details:
user requested login.html.
NGINX served the user request.
user supplied credentials and submit.
Ajax XHR received by NGINX and routed to the Authentication backend REST service.
authentication backend service validated the request and returned response that include session cookie/access token/api key.
Ajax XHR received the response through NGINX, then what? how should I proceed? below are current ideas I have:
a. in many examples (including instagram): window.location.reload();. but in my case reload login.html will not cause NGINX to forward the user to the landing page unless it maintain the authentication logic! so how I can pass this obstacle?
b. in case I redirect the user to landing.html, NGINX will serve it. but again that's not acceptable because every resource request (except login.html) must be validated first (I mean both authentication and authorization).
I hope the question is clear now. I think if NGINX can be configured to pass every request to the authentication backend REST service before it go to the original destination, big part will be resolved though it might be big overhead for auth service!
Your best option here is to use X-Accel-Redirect. This will allow you to pass your requests to the authentication service and then in the authentication service you can run your auth logic and if successful set the X-Accel-Redirect header so that when nginx gets the response it will perform an internal redirect to the resource that you actually want to call. If authentication fails your service can reply with a 401 and not set the header so nginx will provide the proper response to the client.
Your other option, which will be more daunting, is to implement this as a custom Lua module.
In an application I implemented an javascript chat with long polling. Since there is just one Ajax Request per domain allowed I wanted to move the poll request to a subdomain.
So I have two domains:
dev.site.com
poll.dev.site.com
In my config.yml I entered the following:
framework:
session:
domain: .dev.site.com
cookie_domain: .dev.site.com
But Symfony does not keep me logged in if I try to poll on the sub-domain via Ajax.
Any idea on how to keep the session on the sub-domains?
I'm using the FOSUserBundle
First, the two applications need to share the fos_user table so they can reload the user when. As you have "one app and the two domains pointing to the same app." this should already be correct.
Next is to set the session cookie to be shared between the domain and the subdomain. The config in your question is correct. However for FOSUserBundle to be able to reload the user when you change from dev.site.com to poll.dev.site.com you need to share the session storage between the two domain.
The easiest way I can suggest is to store the session in a database. This is achieved by using the PdoSessionStorage available in Symfony. The official documentation covers how to setup the session storage to do that.
If all above is done correct you should not able to login to an secure area on dev.site.com, and then change the URL to an other secure area on poll.dev.site.com without any need provide login credentials again. Notice that the user credentials are only loaded in an secure area.
When it works to open poll.dev.site.com directly in the browser with any need to enter the credentials again. You need to do some additional work to get the Ajax request to work.
According to these two questions: Setting a cookie on a subdomain from an ajax request, multi-sub-domain cookies and ajax problems the problem is likely the http://en.wikipedia.org/wiki/Same_origin_policy.
The first suggests setting the following header fields on dev.site.com:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://poll.dev.site.com
And then passing withCredentials on the ajax request.
$.ajax({
url: 'http://poll.dev.site.com/some/ajax/endpoint.json',
xhrFields: {
withCredentials: true
}
});
I've tested it using a dummy file that would just set the cookie and try and ajax request. I got it to worked if I had withCredentials on the ajax request, but I could not see any difference when I tried with/without the Access-Control-Allow-* headers.
The other answer suggested using document.domain but I dodn't test that.
I used using Opera's Dragonfly to inspect the network trafic if the Cookie header was sent to the server when I tested. You can use Firebug, Chrome or probably IE too.
I have a problem related to subdomain and https request.
I am trying to route from http to https where my http address is subdomain.domain.com and https address is domain.com/subdomain. But the problem is when i switched from http to https i loose my session variables.
How can i persist my session variables in both http and https requests.
Thank you.
The session is probably tracked by a cookie.
Cookies have a domain associated with them, in this case this would be "subdomain.domain.com". For a different domain, even if it is the parent domain, the cookie will not be provided by the web browser.
I think there are ways to make a cookie valid for all subdomains under a given domain, but you have to look into the documentation of the software you are using for that.
For any more information, we really need more detail about what software you are using to keep this session. Standard PHP sessions? Or something else?