Fórum
Access-Control-Allow-Origin JSONWS
Eric COQUELIN, modificado 8 Anos atrás.
Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
Dear all,
I have setup remote services accessible with JSON Web services.
When one the service is being called using AJAX, the browser reject the response as header Access-Control-Allow-Origin is not populated with "*"
How can I force Liferay to populate this value? Generally, how can we achieve architecture where there are mobile client or any other client type with interacts with the Liferay server using JSON WS ?
Thank you in advance for your help
I have setup remote services accessible with JSON Web services.
When one the service is being called using AJAX, the browser reject the response as header Access-Control-Allow-Origin is not populated with "*"
How can I force Liferay to populate this value? Generally, how can we achieve architecture where there are mobile client or any other client type with interacts with the Liferay server using JSON WS ?
Thank you in advance for your help
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
Hi,
Do anybody can help ?
I make the following call from an HTML page hosted by another application running on port 8091 on the same server
Authentication is deactivated so far but it might be the next issue...
My portal-ext.properties
I can't imagine it is that complicated. I assume, it is a single configuration to update somewhere...
Do anybody can help ?
I make the following call from an HTML page hosted by another application running on port 8091 on the same server
var req = new XMLHttpRequest();
req.open("GET", "http://localhost:8090/api/jsonws/zp-portlet.vendor/get-vendors/company-id/20254");
//req.setRequestHeader("Authorization", "Basic " + btoa("mrjones:test12345"));
req.send();
Authentication is deactivated so far but it might be the next issue...
My portal-ext.properties
json.service.auth.token.hosts.allowed=127.0.0.1,SERVER_IP
json.service.auth.token.enabled=false
jsonws.servlet.hosts.allowed=127.0.0.1,SERVER_IP
I can't imagine it is that complicated. I assume, it is a single configuration to update somewhere...
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
Dear all,
It took time but I got it...
For JSON exchange, you can't use "XMLHttpRequest" but should use "fetch" (https://davidwalsh.name/fetch). I know fetch is not yet widely supported but I understand that it should be soon the case.
Here is an example of call
With that call, it will reuse the cookies already received from the server, including the JSESSIONID. Which is great. Then authentication of subsequent request is solved.
Now, I need to understand how to get authenticated and have this cookie populated. If anyone has any clue, please help.
Have a good weekend.
It took time but I got it...
For JSON exchange, you can't use "XMLHttpRequest" but should use "fetch" (https://davidwalsh.name/fetch). I know fetch is not yet widely supported but I understand that it should be soon the case.
Here is an example of call
fetch("http://localhost:8090/api/jsonws/zp-portlet.vendor/get-vendors/company-id/20254",
{mode: 'no-cors', credentials: 'include'})
.then(function(response) {
console.log(response);
}).catch(function(ex) {
console.log('parsing failed', ex)
})
With that call, it will reuse the cookies already received from the server, including the JSESSIONID. Which is great. Then authentication of subsequent request is solved.
Now, I need to understand how to get authenticated and have this cookie populated. If anyone has any clue, please help.
Have a good weekend.
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
I wanted to share further analysis I made on this subject.
I was wrong when writting that fetch would solve my issue. I did not understand immediatly that fetch is "just" a new generation of XMLHttpRequest... As a result, even if you have the feeling that the request is correctly processed by the server, you still have some limitations.
Indeed, when sending the request, I had the feeling that I could process the response
Then I realized, reading Google Chrome documentation that the response will be "opaque" because the request is not permitted between domains. Response details are not available but the request is correctly processed on server side as if it was a valid request coming from a valid host.
But, in most cases, not being able to read the response is a real problem. So I understood that the request should be sent as follows:
i/o "no-cors", I should use "cors". Now, the server rejects the request because it comes from an invalid domain.
Next step is to change Tomcat configuration so that it allows cors requests. Liferay web.xml was updated as follows
After restarting Liferay, the request is correctly processed and the response can be processed as well.
I don't really know if it is the best approach but at least it works. If you have any comments, don't hesitate to add, it will be more than helpful.
I was wrong when writting that fetch would solve my issue. I did not understand immediatly that fetch is "just" a new generation of XMLHttpRequest... As a result, even if you have the feeling that the request is correctly processed by the server, you still have some limitations.
Indeed, when sending the request, I had the feeling that I could process the response
fetch( url, {mode: 'no-cors', credentials: 'include', headers: headers} )
.then(function(response) {
console.log(response);
}).catch(function(ex) {
console.log('parsing failed', ex)
})
Then I realized, reading Google Chrome documentation that the response will be "opaque" because the request is not permitted between domains. Response details are not available but the request is correctly processed on server side as if it was a valid request coming from a valid host.
But, in most cases, not being able to read the response is a real problem. So I understood that the request should be sent as follows:
fetch( url, {mode: 'cors', credentials: 'include', headers: headers} )
.then(function(response) {
console.log(response);
}).catch(function(ex) {
console.log('parsing failed', ex)
})
i/o "no-cors", I should use "cors". Now, the server rejects the request because it comes from an invalid domain.
Next step is to change Tomcat configuration so that it allows cors requests. Liferay web.xml was updated as follows
<!-- http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter -->
<!-- Doit être ajouté pour traiter le pb des accès distants en XMLHttpRequest ou autres -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
After restarting Liferay, the request is correctly processed and the response can be processed as well.
I don't really know if it is the best approach but at least it works. If you have any comments, don't hesitate to add, it will be more than helpful.
Andrew Jardine, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Liferay Legend Postagens: 2416 Data de Entrada: 22/12/10 Postagens Recentes
Hi Eric,
Thanks for sharing your results and analysis with the community. Too often people post a problem, find a solution but then never update the thread with their findings.
Reading your post though I have a couple of comments .. maybe something for you to try as well if you have a moment . Changing the web.xml for the ROOT application of course can be done but from experience it leads to problems when you want to upgrade. In particular I have found that with the EE version of the product when I use the patching tool to apply service packs, the changes I have made to the web.xml are lost. The only work around to this I believe... and perhaps you could argue "the purist way" to make such changes is with a *barf* EXT plugin .
Having said that, I recently had to enable CORS on an application. In our case it was another app that was iframing content from the Liferay side but regardless, CORS was the issue. Rather than turn it on for the whole server we used the portal-ext settings --
so that only the urls that HAD to support CORS did.
I am curious, could you try this on your side to see if it allows you to fix your issue without enabling CORS for the entire server?
Thanks for sharing your results and analysis with the community. Too often people post a problem, find a solution but then never update the thread with their findings.
Reading your post though I have a couple of comments .. maybe something for you to try as well if you have a moment . Changing the web.xml for the ROOT application of course can be done but from experience it leads to problems when you want to upgrade. In particular I have found that with the EE version of the product when I use the patching tool to apply service packs, the changes I have made to the web.xml are lost. The only work around to this I believe... and perhaps you could argue "the purist way" to make such changes is with a *barf* EXT plugin .
Having said that, I recently had to enable CORS on an application. In our case it was another app that was iframing content from the Liferay side but regardless, CORS was the issue. Rather than turn it on for the whole server we used the portal-ext settings --
http.header.secure.x.frame.options=true
http.header.secure.x.frame.options.1=<first_url>
http.header.secure.x.frame.opti ons.2=<second_url>
...
</second_url></first_url>
so that only the urls that HAD to support CORS did.
I am curious, could you try this on your side to see if it allows you to fix your issue without enabling CORS for the entire server?
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
Hi Andrew,
Thank you for your response.
I never noticed that file https://docs.liferay.com/portal/6.2/propertiesdoc/system.properties.html and will try what you provided. However, I'm wondering if we cant set a prefix i/o a exact URL because I'd like to allow all JSON WS.
I will let you know after trying. Thank you for the tips.
Thank you for your response.
I never noticed that file https://docs.liferay.com/portal/6.2/propertiesdoc/system.properties.html and will try what you provided. However, I'm wondering if we cant set a prefix i/o a exact URL because I'd like to allow all JSON WS.
I will let you know after trying. Thank you for the tips.
Andrew Jardine, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Liferay Legend Postagens: 2416 Data de Entrada: 22/12/10 Postagens Recentes
Hi Eric,
If I understand you correctly, I think you are asking about using this property to configure a "root" location under which all child urls would follow the same value. I'm not sure about doing that with this option to be honest. In our case we have just a couple of URLs that we wanted to allow the external application to "iframe". I would also advocate that, even if there are 50 or 60 different URLs that you want to allow CORS on, better to specify those 50 or 60 (as painful as that might be) than to open up the server entirely. This is after all not just a pain in the ass, but a security feature
If I understand you correctly, I think you are asking about using this property to configure a "root" location under which all child urls would follow the same value. I'm not sure about doing that with this option to be honest. In our case we have just a couple of URLs that we wanted to allow the external application to "iframe". I would also advocate that, even if there are 50 or 60 different URLs that you want to allow CORS on, better to specify those 50 or 60 (as painful as that might be) than to open up the server entirely. This is after all not just a pain in the ass, but a security feature
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
Hi Andrew,
Unless I missunderstood something, the XFRAME is not a solution to the CORS issue.
As stated in the system.properties comments, the default behavior is SAMEORIGIN
If you want to block other URL, you just set the URL inbetween (with a value lower than 255) or if you want to deny everything, you put DENY i/o SAMEORIGIN and allow only some of the URL.
With that configuration, it doesn't change Liferay behavior.
Liferay controls the header "Origin" and then notice that it doesn't match the server URL (running on port 8090) and the brower reject the request because Liferay did not provide "Access-Control-Allow-Origin" header in the response...
Without the CORS filter, the problem remains. And I'm still wondering why there is no easiest solution to solve this problem.
Unless I missunderstood something, the XFRAME is not a solution to the CORS issue.
As stated in the system.properties comments, the default behavior is SAMEORIGIN
http.header.secure.x.frame.options=true
http.header.secure.x.frame.options.255=/|SAMEORIGIN
If you want to block other URL, you just set the URL inbetween (with a value lower than 255) or if you want to deny everything, you put DENY i/o SAMEORIGIN and allow only some of the URL.
With that configuration, it doesn't change Liferay behavior.
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,ms;q=0.2
Access-Control-Request-Headers:authorization, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:8090
Origin:http://localhost:8091
Referer:http://localhost:8091/
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B137 Safari/601.1
Liferay controls the header "Origin" and then notice that it doesn't match the server URL (running on port 8090) and the brower reject the request because Liferay did not provide "Access-Control-Allow-Origin" header in the response...
Without the CORS filter, the problem remains. And I'm still wondering why there is no easiest solution to solve this problem.
Eric COQUELIN, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Expert Postagens: 254 Data de Entrada: 03/11/13 Postagens Recentes
I have seen that a bug was opened in 2014 but closed without any modification : https://issues.liferay.com/browse/LPS-46310
However, I have the feeling it was closed for a bad reason. Security on server side is important, indeed. But if no browser can communicate with Liferay, this is an issue... At least my issue so far
However, I have the feeling it was closed for a bad reason. Security on server side is important, indeed. But if no browser can communicate with Liferay, this is an issue... At least my issue so far
Andrew Jardine, modificado 8 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Liferay Legend Postagens: 2416 Data de Entrada: 22/12/10 Postagens Recentes
Hi Eric,
hmmm I am certainly no security expert but all I can say is that for our case we set a couple of urls on those properties. The urls were in our Liferay application and are being referenced by SalesForce (via IFRAME). Without these properties, the requests were blocked.
I can see only one reference to these properties in the LR codebase -- in the SanitizedServletResponse class. Perhaps if Tomas is kickin' around the forums he could shed some light for us
hmmm I am certainly no security expert but all I can say is that for our case we set a couple of urls on those properties. The urls were in our Liferay application and are being referenced by SalesForce (via IFRAME). Without these properties, the requests were blocked.
I can see only one reference to these properties in the LR codebase -- in the SanitizedServletResponse class. Perhaps if Tomas is kickin' around the forums he could shed some light for us
Jack Bakker, modificado 6 Anos atrás.
RE: Access-Control-Allow-Origin JSONWS
Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens RecentesEric COQUELIN:
I don't really know if it is the best approach but at least it works. If you have any comments, don't hesitate to add, it will be more than helpful.
For anyone finding this thread, I found Tomas' dev.life presentation useful:
https://web.liferay.com/community/dev.life/previous
"20140923 - Tomáš Polešovský - Securing remote JSON Web Services"
His code is still at: https://github.com/topolik/presentations/tree/master/jsonws-services-portlet/