-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sap.ui.model.odata.v4.ODataModel cannot be used with a standard odata4 service without CSRF token support #2288
Comments
Hello @cjohn001 ! Thanks a lot for your interest in OData V4. Apart from the failed network request, do you experience any other issues? From our perspective, X-CSRF-Token is not a prerequisite. We usually try to fetch it early on, but everything should work fine without it (as long as the server does not require it). You might want to turn off earlyRequests, which triggers the early request of $metadata and X-CSRF-Token. Both will be requested on demand, then. We apologize for any inconvenience caused. Best regards, |
Hello Thomas,
And I am now ending up with the following errors
I also attach the metadata file:
|
The "Term" attribute is missing here: |
Hello Thomas, Request URL: http://localhost:9001/odata4/svc/my_nutri_diary/$batch GET Account?$select=uuidUser&$skip=0&$top=100 HTTP/1.1 --batch_id-1542311330723-11-- |
Hello @cjohn001 ! BEWARE: Authorization: Basic can reveal your user and password. It's not encrypted, just encoded. I would remove this header before I post publicly. You refer to "this multipart/mixed header that is missing". That part is not clear to me. Why do you think that a header is missing? I could not understand that from the given information. "406 Not Acceptable" means that the server cannot provide a response in a format which the client requested. Maybe it's Accept: multipart/mixed, maybe it's the Accept-Encoding: gzip, deflate, br header. That might appear in your server's log. (I see you are already discussing this at https://developer.jboss.org/thread/279113). Best regards, |
Hello Thomas, |
Hello Christoph! Our V4 OData model can only handle $batch as multipart (currently). Thus Accept: multipart/mixed is a perfectly fine header from our point of view. If wildfly knows how to handle multipart, it should learn to deal with this header as well. That's the piece that I recommend to fix, not UI5. Best regards, |
Hello Thomas, |
Hello Christoph! No worries. You're welcome. The "earlyRequests" parameter is pretty simple. It will send GET requests for /$metadata and all annotation XML files (see parameter "annotationURI"). It will also send a HEAD request to with header "X-CSRF-Token" : "Fetch" in order to fetch the security token. If Teiid/Olingo does not implement CSRF protection by requiring such a header, there should be no need to properly answer the HEAD request at all. Else it would be nice to return the right CSRF token value in the response's headers. Please see Cross-Site Request Forgery Protection and Gateway protection against Cross-Site Request Forgery attacks for some background infos. Do not hesitate to ask for further details in case I missed anything. Best regards, |
Hello Thomas,
|
Hello Christoph! It might be better to move the new discussion to a different issue, but I leave that up to you. If you do, please link it from here and I will follow-up there. You are right, we have considered "cache synchronization" early on and thus introduced the synchronizationMode flag, but there is almost nothing implemented so far. It is a bit tricky to explain because you need to understand the concept of when (or why) a binding sends its own data requests. If it does, it stores the received data in a data structure we call "cache" and informs the attached controls, e.g. via a "change" event. The controls then call s.th. like PropertyBinding#getValue and get the data from that cache. In your code, when you call bindContext("/...") or bindElement("/...") you create a v4.ODataContextBinding with an absolute binding path (starting with a slash). Each of these bindings will send its own data requests and that is why you experience the missing synchronization. The easiest solution would be to send just a single data request and reuse that binding's cache across different views. Then no synchronization is needed and you save HTTP requests. (Of course, it is only a good idea if you need more or less the same data, e.g. $select=*, and not totally different projections.) You can call oControl.setBindingContext(gConfOptsContextBinding.getBoundContext()) to achieve this reuse. This should simplify your first example. The list binding is a bit more complicated. Currently, it is meant to be used by a single control only and does not offer a good API for controller code. You already noticed that there is no counterpart for requestObject(). First of all, we should understand if you can do the reuse trick here as well. For that, we would need a better understanding of your data, which views you have and what they have in common resp. what differences they have. Until then, let me shed some light on how a control roughly uses a context binding, because that is what you need to do as a controller as well. Disclaimer: Not all of these methods are public! In the simplest case, call getContexts(0, Infinity) to request all data. It should trigger a request automatically if the group ID is "$auto", else submitBatch is needed as usual. It returns an empty array with an "annotation" dataRequested : true. You should add a "change" listener to the binding and will be called back once the response arrives. Then call getContexts(0, Infinity) again and you get one v4.Context instance for each data row. Call getObject() on these or use them as a binding context for a detail view. WeightListBinding.initialize(); // not needed Best regards, P.S.: I wondered about this line of code: |
@ThomasChadzelek It would be nice if there is an option to request only the
The sample makes use of the TripPin service, which is the only registration-free V4 service available out there AFAIK. But it doesn't support handling CSRF tokens. I.e.: All demos with TripPin have to turn In one of the previous comments:
I'm not sure if this is true. If |
Hello @boghyon! I agree that the error message "405 Method Not Allowed" in your developer tools is not nice, but then again it should not really hurt. It is no reason why the application should not work. If you experience issues, please describe them in more detail. Regarding the 2nd question: if TripPin does not support CSRF tokens, then there is no need for the v4.ODataModel to request one on demand. It is never missing. What would you expect to happen? Best regards, |
There are two issues I see with leaving the
About the 2nd part: I was referring to the sentence "Both will be requested on demand" (#2288 (comment)). But in the app, I see only that the |
Hello @boghyon ! I have to look into the issue with About the 2nd part: the v4.ODataModel would fetch a CSRF token on demand if any request fails with status code 403 and header Best regards, |
Hello @boghyon ! I tried to reproduce the failure via https://embed.plnkr.co/qatUyq/?show=manifest.json,preview, but saw it only once when I clicked that "Refresh live preview" button very quickly many times. W/o such a nervous finger, everything was fine except for an "Uncaught (in promise) Error: 405 Method Not Allowed" which has been fixed already for 1.63 If you can reproduce it, please attach more details from console or network tab. Sorry. Best regards, |
Hello @ThomasChadzelek,
Unfortunately, in JSBin, v4.ODataModel fails way too often if Succeeds sometimeswith the previously mentioned error message: which is fine. Breaks quite oftenwith another error message:
The app fails to work. With |
Hello @boghyon, I could reproduce your issue and will check how that can be improved. Generally, I would not recommend to use earlyRequests if the server does not require the x-csrf token as a pointless request goes out in this case. Best regards |
Hello @boghyon , your issue is caused by the following functionality. A request with method !== "GET" will wait for a pending x-csrf token request and be executed only if the related promise is resolved. This introduces the randomness you observe. If the token request is not pending, everything works fine. To code against the special case of TripPin not supporting HEAD requests does not seem to be a good solution. We expect that productive services can handle HEAD requests. The real solution would be to allow to specifically request only the root metadata early. This is a feature request. Could you please explain whether and when you would require that feature for productive applications? Best regards |
Hi @uhlmannm I see, thanks for the reply. So if the service would actually handle HEAD requests properly as expected but without the
Well, if my assumption above is true, I think it's ok not to have the feature.
It's a bit of a mystery to me, why fetching |
Hi @boghyon ,
Yes, the HEAD request needs to be successful but it does not need to contain the x-csrf-token header.
Well ... the two points came up together and SAP services have to do something about cross side request forgery. So this is basically how it ended up behind the same parameter without the possibility to just have one of the two. Have you tried the following in your Component.js to enforce an early request of metadata without parameter Best regards |
OpenUI5 version:
openui5-sdk-1.58.5
Browser/version (+device/version):
Google Chrome Version 70.0.3538.77 (Offizieller Build) (64-Bit)
Any other tested browsers/devices(OK/FAIL):
n/a
URL (minimal example if possible):
n/a
User/password (if required and possible - do not post any confidential information here):
n/a
Steps to reproduce the problem:
What is the expected result?
What happens instead?
I see two issues here.
The text was updated successfully, but these errors were encountered: