Technical Articles
CORS and Fiori/UI5 – Everything you need to know
Everyone who starts developing Fiori/UI5 apps, and doesn’t have a web development background, sooner or later will face Cross-Origin Resource Sharing (CORS) issues and suffer a little bit until wrap their minds around this concept and fully understand it.
Every now and then I need to help a friend/colleague who is getting messages such as:
Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘https://xxxxxxxxxxx.com’ is therefore not allowed access.
Access to fetch at ‘https://backend.com’ from origin ‘https://frontend.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.
Access to fetch at ‘https://backend.com’ from origin ‘https://frontend.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
Access to XMLHttpRequest at ‘https://backend.com’ from origin ‘https://frontend.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Access to XMLHttpRequest at ‘https://backend.com’ from origin ‘https://frontend.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
But what the hell is CORS?!? What does that mean?
According to Mozilla Developer Network:
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.
Translating to English, it means, by default a web application running on https://frontend.com (one origin) cannot access resources from https://backend.com (different origin), unless the “backend” explicitly allows it.
Ajax (XMLHttpRequest) and Fetch API requests (javascript) follow the Same-origin Policy (SOP) which is a security mechanism that reduces possible attack vectors. Before CORS, it was impossible to access resources from another origin (different domain, port, protocol…). Same-origin Policy didn’t allow it for security reasons. Nobody wants applications running on http://superhacker.ru to access our backend server, right?
OK, enough talking. Let’s see some examples…
I’ve identified my OData Service URL from the backend and I’m going to do some tests before writing my Fiori/UI5 app. In this case, the famous NorthWind OData Services from Microsoft: https://services.odata.org/V2/OData/OData.svc
I’m going to test it with JaSON, a tool for testing and debugging web services, (it could be Postman, SoapUI, etc). My OData Service endpoint is the service metadata: https://services.odata.org/V2/OData/OData.svc/$metadata
From browser (direct access):
From JaSON:
So far so good. Now, let’s access the same endpoint from my Fiori/UI5 app using an OData Model. My app is running on localhost (127.0.0.1).
//Don't judge me, it's for simplicity's sake
const url = 'https://services.odata.org/V2/OData/OData.svc';
const model = new sap.ui.model.odata.v2.ODataModel(url); //Yep, globals...
Oooops… We’ve got an error!
Access to XMLHttpRequest at ‘https://services.odata.org/V2/OData/OData.svc/$metadata’ from origin ‘http://localhost:61264’ has been blocked by CORS policy…
If we try with jQuery Ajax or Fetch API, we’ll get pretty much the same CORS error.
//Yep, no callbacks, don't judge me...
const url = 'https://services.odata.org/V2/OData/OData.svc/$metadata';
$.get(url); //jQuery Ajax
fetch(url); //Fetch API
It doesn’t matter whether I’m running a Fiori/UI5 app from my local computer, from SAP Cloud Platform or from SAP Fiori Front-end Server On-Premise. CORS error will be the same because I’m accessing resources from another origin, another domain. “Ok, I got it… But, why did it work from JaSON before?” you might ask. It works because JaSON is a developer tool, a plugin installed in your browser. It isn’t a web application being accessed from your browser. JaSON and other dev tools don’t care about Single-origin Policy and CORS. Remember, SOP and CORS are a browser security mechanism, it’s the browser who blocks your ajax/fetch requests.
OK, then what? How can I fix it?
I have some good news and some bad news… The bad news is you CANNOT fix it. I mean, not from your Fiori/UI5 app side, not for good. As aforementioned, the browser expect some very specific HTTP headers from the endpoint being called (another origin). However, you can use some workarounds for testing only. They are not recommended for Production environments.
Now, the good news! You can fix it for real, as long as you have access to the backend and authorization to change some parameters. There are a bunch of HTTP headers to be used for CORS: Access-Control-Allow-WhatDoYouWant? Some options are: Access-Control-Allow-Origin informs the browser which origin has access to the server. Access-Control-Allow-Methods tells the browser which HTTP methods are supported. And so on…
For instance, you could make your SAP Gateway return responses with CORS HTTP headers such as: ‘Access-Control-Allow-Origin’ : ‘http://localhost:61264’. In this example, the HTTP header informs the browser to allow Cross-Origin Resource Sharing requests from http://localhost:61264 only. If you’re feeling brave, you could allow requests from any origin: ‘Access-Control-Allow-Origin’ : ‘*’. You could also tweak few parameters on SAP Web Dispatcher to return these HTTP headers (which is a better idea than handling it on SAP Gateway).
Some other possibilities would be:
Eclipse + proxy (testing only)
If you’re developing your app from Eclipse, you could use a proxy servlet. All you need to do is add proxy to your OData Service URL. It works local only.
//Note the PROXY in the URL
const url = 'proxy/https/services.odata.org/V2/OData/OData.svc';
const model = new sap.ui.model.odata.v2.ODataModel(url);
CORS Anywhere (testing only)
It’s a node.js proxy which adds CORS HTTP headers to the proxied requests. You call CORS Anywhere + your endpoint URL and that’s it. It works anywhere 😉
const url = 'https://cors-anywhere.herokuapp.com/https://services.odata.org/V2/OData/OData.svc';
const model = new sap.ui.model.odata.v2.ODataModel(url);
SAP Cloud Platform – Destination
In case you’re deploying your apps to SAP Cloud Platform, it’s even easier. You don’t need to mess around with HTTP headers in the backend, you just need to create a Destination for the OData Service URL and consume the Destination from your Fiori/UI5 app. That’s all, nothing else. It works in a similar way as CORS Anywhere.
If you would like to learn more about the topic, go through the links below. They contain few other concepts related to CORS and more examples. Also, a list of the all HTTP headers used with CORS.
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors
Happy New Year! \o/
Nice Tip.. Thanks!
Thanks for writing this. CORS is faced by all developers no doubt.
Well-written and to the point. Thanks.
Thanks for the article.
I have faced the exact same issue, I have deployed UI5 application in SAP EP as Web project and tried to access oData service which is not in the same domain as SAP EP.
When i tried to access oData service, i got the following error , But somehow fixed the error by setting headers in GW servier rewrite.txt using Basis help.
/sap/opu/odata/sap/ZDMS_DEMANS_SRV/$metadata' from origin 'http://xxx.xxx.xxx.xxx:xxxxx' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.”.
But now when i access the oData service i am getting the below error.
Access to XMLHttpRequest at
/sap/opu/odata/sap/ZDMS_DEMANS_SRV/$metadata' from origin 'http:// xxx.xxx.xxx.xxx:xxxxx has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
index.html#/quotation/create:1 Uncaught (in promise) {message: "HTTP request failed", request: {…}, response: {…}, statusCode: 0, statusText: "", …}
Please let me know what needs to be done.
Regards,
Dayalan
You should create a thread for it: https://answers.sap.com/index.html
Hi Mauricio,
thanks for the write up, i appreciate it very much.
I am trying to call the northwind odata service from eclipse. and even when i add proxy to the url i get the 500 server error.
“proxy/https/services.odata.org/V2/OData/OData.svc”;
do i need to do some configuration in eclipse for this?
Kind regards,
New to ui5, new to web development.
thank you very much.
Vamsi
You should create a thread for it: https://answers.sap.com/index.html
Fiori Launchpad has a longstanding bug. This bug stopped developers from using even CORS compliant APIs within Fiori apps. This is resolved now with SAPUI5 version 1.60.9. Reference https://github.com/SAP/openui5/issues/2402
Very helpful thanks Mauricio Lauffer
Hi Mauricio,
Nice article. However, I am running into the CORS issue when my SAP UI5 application is using the destination defined to Northwind which is strange. Any ideas on why this would be happening? I have a destination to Northwind pointing to https://services.odata.org. The reads are working just fine, but the post is not working for the create.
Access to XMLHttpRequest at 'https://services.odata.org/V2/(S(qgjsd2qqpmu0c4xcwnnakxge))/OData/OData.svc/$batch' (redirected from 'https://webidetesting3752626-s0007610100trial.dispatcher.hanatrial.ondemand.com/Northwind/V2/(S(qgjsd2qqpmu0c4xcwnnakxge))/OData/OData.svc/$batch') from origin 'https://webidetesting3752626-s0007610100trial.dispatcher.hanatrial.ondemand.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Regards,
Jay
Hi Jay Malla,
Did you find any solution for this? I'm getting the same error.
Regards,
Bhoomika
Hi Jay, Bhoomika,
I am getting same error, do you have solution for this ?
Thanks,
Anil.
You should create a thread for it: https://answers.sap.com/index.html
Hi Mauricio,
How could I achieve the same for Fiori News Tile?
How can I use the desination url feed define in SCP and being called in SCP fiori launchpad portal?
Regards,
Ben
Hello all,
I have the same issue when configuring the Tiles in Gateway.
"has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource."
Is there any ideas on how to fix this?
Thanks,
PN
You should create a thread for it: https://answers.sap.com/index.html
Thanks for the article ! It worked in Eclipse
great article, however i am missing the last bit.
"consume the Destination from your Fiori/UI5 app"
could you please add more flesh to it ?
thanks
Hi Luca.
Follow a link with more details about SAP CP Destinations: https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/e4f1d97cbb571014a247d10f9f9a685d.html
Hello all !
I've exactly the same error and the same phenomenon as in this article but my situation is a little bit different :
I try to establish a live connection between SAP Cloud Foundry Web IDE project and SAP Analytics Cloud on Cloud foundry to. I follow all the procedure with success for each steps but when I try to create my live connection I've the same error explained in this article.
I don't now where can I fix this error because I try to edit the Hana Analytics Adapter in order to fix my error without success.
Can someone help me to resolve my issue ?
thank's per advance
Maxime
You should create a thread for it: https://answers.sap.com/index.html
Hello guys, the issue in my case was solve by setting the missing patch at the index.html:
data-sap-ui-resourceroots
We need this so the APP recognizes the JS view. Example:
<head>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge” />
<meta charset=”UTF-8″>
<title>MVC App</title>
<script id=’sap-ui-bootstrap’
src=’https://openui5.hana.ondemand.com/resources/sap-ui-core.js’
data-sap-ui-theme=’sap_belize’
data-sap-ui-libs=’sap.m, sap.ui.layout’
data-sap-ui-resourceroots='{“sapui5.demo.mvcapp”:””}’ >
Use whitelisting like in this document: https://help.sap.com/viewer/1ca554ffe75a4d44a7bb882b5454236f/1709.000/en-US/149f40fa2c9b40599b2a61ee9127e20c.html and everything works fine
What If one gets the error while trying to run the OpenUI walkthrough tutorials?
Great write-up thanks for this helped a ton!
That's nice content created on CORS but i want to know if need to use API url instead of OData will it work as expected if i add configuration in destination which you have mentioned.