JavaScript Embedding API Questions

30 views
Skip to first unread message

Aaron Spike

unread,
Aug 27, 2021, 4:57:09 PM8/27/21
to Orbeon Forms
Now that I have set up Apache to forward requests with appropriate authentication headers, I notice that I can use this server like a second Orbeon Forms server. I'd like to prevent this to avoid confusing my users. Is there a subset of URIs that I can allow through the proxy that will enable the embedding API to function without allowing access to everything?

Sometimes complex forms take a little while to load when embedded in a page. Is there any way to bind an event listener to the embedded form to let me know when it is loaded? I'd like to be able to display a loading message and hide that message once the form loads.

Right now I use roles to set the visibility of various buttons on the form. Is there a way to control form visibility based upon whether the form is being embedded? I'd like to allow the use of the PDF button in the standard interface, but hide it when embedded because it doesn't work.

Aaron Spike

Alessandro Vernet

unread,
Aug 27, 2021, 5:46:30 PM8/27/21
to Orbeon Forms
Hi Aaron,

Now that I have set up Apache to forward requests with appropriate authentication headers, I notice that I can use this server like a second Orbeon Forms server. I'd like to prevent this to avoid confusing my users. Is there a subset of URIs that I can allow through the proxy that will enable the embedding API to function without allowing access to everything?

Yes, typically, users should then not access Orbeon Forms directly. So you could completely block requests that are not coming from the proxy, but this is something that you would do outside of Orbeon Forms, for instance with a Remote Filter at the Tomcat level (https://tomcat.apache.org/tomcat-9.0-doc/config/filter.html).
 
Sometimes complex forms take a little while to load when embedded in a page. Is there any way to bind an event listener to the embedded form to let me know when it is loaded? I'd like to be able to display a loading message and hide that message once the form loads.

 
Right now I use roles to set the visibility of various buttons on the form. Is there a way to control form visibility based upon whether the form is being embedded? I'd like to allow the use of the PDF button in the standard interface, but hide it when embedded because it doesn't work.

There is no such function right now, but it could be added fairly easily, I think, and I've created an RFE for this. https://github.com/orbeon/orbeon-forms/issues/4976

-Alex 

Aaron Spike

unread,
Aug 28, 2021, 10:36:03 PM8/28/21
to Orbeon Forms
Alex,

Thank you for the link to the client-side JavaScipt API documentation. I totally missed that! I think it might be helpful to include a link there from https://doc.orbeon.com/form-runner/link-embed/javascript-api too.

I appreciate the RFE.  I think this would be a useful distinction to provide access to.

I think we may be talking past each other a little bit with regard to access control. I am not allowing direct access to Orbeon Forms. All access is mitigated by a proxy. I would like to prohibit all requests through the proxy that are not necessary for the form I am embedding. For example, if all traffic generated by embedding a form is directed to paths below /orbeon/xforms-server/ then I could completely disallow paths below /orbeon/fr/ through the proxy. What is the minimal set of paths I need to allow through the proxy to enabled a form to be embedded with the JavaScript embedding API?

Aaron Spike

Aaron Spike

unread,
Aug 30, 2021, 12:56:31 PM8/30/21
to Orbeon Forms
I'm still interested to hear what you have to say on the URI that are necessary to allow through the proxy for an embedded form. But I'd like to add a couple additional questions to my list.

I'm following the example for setting a control value found at https://doc.orbeon.com/form-runner/api/other-apis/form-runner-javascript-api#setting-a-controls-value . It seems that ORBEON.fr.API.findControlsByName('control-name') cannot locate a control that isn't found on the currently active section of the wizard. Is there a way for me to set the value of a hidden control from JavaScript while handling the orbeonLoaded event?

In regard to the headers passed for header-driven authentication, is there any negative consequences of choosing not to pass a group? A single group per user is not useful in my application so I am using roles instead.

Aaron Spike

Alessandro Vernet

unread,
Aug 30, 2021, 5:38:27 PM8/30/21
to Orbeon Forms
Hi Aaron,

Thank you for the link to the client-side JavaScript API documentation. I totally missed that! I think it might be helpful to include a link there from https://doc.orbeon.com/form-runner/link-embed/javascript-api too.

Yes, this is now done, from a "See also" section, at the bottom of the page.

I think we may be talking past each other a little bit with regard to access control. I am not allowing direct access to Orbeon Forms. All access is mitigated by a proxy. I would like to prohibit all requests through the proxy that are not necessary for the form I am embedding. For example, if all traffic generated by embedding a form is directed to paths below /orbeon/xforms-server/ then I could completely disallow paths below /orbeon/fr/ through the proxy. What is the minimal set of paths I need to allow through the proxy to enabled a form to be embedded with the JavaScript embedding API?

Got it! Good question, I don't have a list of paths you can exclude, and am just thinking "out loud" here: those requests should only be for the XForms server and assets (JavaScript, CSS, images), so a possible strategy might be only allow POSTs to `/xforms-server` and `/xforms-server/upload`, allow GET only if the content type returned by Orbeon Forms is different than `text/html`, and refuse all other methods?

I'm following the example for setting a control value found at https://doc.orbeon.com/form-runner/api/other-apis/form-runner-javascript-api#setting-a-controls-value . It seems that ORBEON.fr.API.findControlsByName('control-name') cannot locate a control that isn't found on the currently active section of the wizard. Is there a way for me to set the value of a hidden control from JavaScript while handling the orbeonLoaded event?

The JavaScript code shouldn't be allowed to do something that the user isn't allowed to do, since the user can run JavaScript, so yes, you can't access fields in sections other than the one currently shown with JavaScript. Maybe you can move those fields to the first section?

In regard to the headers passed for header-driven authentication, is there any negative consequences of choosing not to pass a group? A single group per user is not useful in my application so I am using roles instead.

I think that not passing the group should be fine.

-Alex

Aaron Spike

unread,
Aug 30, 2021, 6:21:39 PM8/30/21
to Orbeon Forms
On Monday, August 30, 2021 at 4:38:27 PM UTC-5 Alessandro Vernet wrote:
I think we may be talking past each other a little bit with regard to access control. I am not allowing direct access to Orbeon Forms. All access is mitigated by a proxy. I would like to prohibit all requests through the proxy that are not necessary for the form I am embedding. For example, if all traffic generated by embedding a form is directed to paths below /orbeon/xforms-server/ then I could completely disallow paths below /orbeon/fr/ through the proxy. What is the minimal set of paths I need to allow through the proxy to enabled a form to be embedded with the JavaScript embedding API?

Got it! Good question, I don't have a list of paths you can exclude, and am just thinking "out loud" here: those requests should only be for the XForms server and assets (JavaScript, CSS, images), so a possible strategy might be only allow POSTs to `/xforms-server` and `/xforms-server/upload`, allow GET only if the content type returned by Orbeon Forms is different than `text/html`, and refuse all other methods?

 Thanks for those ideas. I will ponder this a little more and perhaps do some experimentation. I figure there is no danger, because the access is determined by the headers that are sent by the proxy. A user can't do something they wouldn't be able to do when logged into Orbeon directly. The confusion is simply that the "navigation" buttons (e.g. summary, edit, etc.) do currently work. They simply navigate to the raw Form Runner page in the URL-space of the proxy. This allows the user to escape the embedding application. I plan to work around this by assigning a different role when accessing through the embedding proxy than through the Orbeon Forms Server proxy. And then I will write conditions in my properties-local.xml to hide or show the appropriate buttons based upon the context determined from the roles. This would be made much easier if I could simply ask if the form was embedded.
 
I'm following the example for setting a control value found at https://doc.orbeon.com/form-runner/api/other-apis/form-runner-javascript-api#setting-a-controls-value . It seems that ORBEON.fr.API.findControlsByName('control-name') cannot locate a control that isn't found on the currently active section of the wizard. Is there a way for me to set the value of a hidden control from JavaScript while handling the orbeonLoaded event?

The JavaScript code shouldn't be allowed to do something that the user isn't allowed to do, since the user can run JavaScript, so yes, you can't access fields in sections other than the one currently shown with JavaScript. Maybe you can move those fields to the first section?

I would argue that the user _can_ edit the field just not until the wizard section switches. :-)

Thanks again for the assistance.
 

Alessandro Vernet

unread,
Aug 30, 2021, 7:18:50 PM8/30/21
to Orbeon Forms
I plan to work around this by assigning a different role when accessing through the embedding proxy than through the Orbeon Forms Server proxy. And then I will write conditions in my properties-local.xml to hide or show the appropriate buttons based upon the context determined from the roles. This would be made much easier if I could simply ask if the form was embedded.

This sounds like a good idea.

I would argue that the user _can_ edit the field just not until the wizard section switches.

Fair enough; the thing with the wizard is that the markup for those sections that are not currently visible is not present in the DOM (this for performance reasons), so allowing access to those fields without first switching to the section that contains the fields wouldn't be an easy thing to do.

-Alex

Aaron Spike

unread,
Aug 31, 2021, 8:39:45 AM8/31/21
to Orbeon Forms
My current approach to setting the field values on load is to use a database service. But it would be really handy if I could cut the cord so to speak. Setting the values through JS on the client-side feels so much lighter. Is there any way to do this through XForms rather than the DOM? For example, could I do something via dispatching events? (https://doc.orbeon.com/xforms/core/client-side-javascript-api#dispatching-events) I skimmed this section of the docs, but I confess I didn't fully grasp what is prohibited and what is permitted. I suppose another option would be to pass the few values as query parameters through the embedForm call. In your opinion what would be the advantages/disadvantages of these approaches?

Alessandro Vernet

unread,
Sep 2, 2021, 4:10:13 PM9/2/21
to Orbeon Forms
Hi Aaron,

Yes, you can do this by dispatching an event, passing the values through properties (see 1st link below). Then in XForms, in a custom model (see 2nd link below), you need to allow that event to come from the browser (`xxf:external-events="do-something"`), and add your own event handler, in which you can access the value of the properties with `event('p1')` and run a number of `<xf:setvalue>`.

https://doc.orbeon.com/xforms/core/client-side-javascript-api#custom-properties
https://doc.orbeon.com/form-runner/advanced/custom

I think this is also a good way to do it. Of course, keep in mind that since the event is dispatched from the browser, users can dispatch it "on their own", and pass any value they want, so this might be a security issue (which isn't the case for services and actions, as those run on the server).

-Alex

Alessandro Vernet

unread,
Sep 2, 2021, 4:34:48 PM9/2/21
to Orbeon Forms
There is no such function right now, but it could be added fairly easily, I think, and I've created an RFE for this. https://github.com/orbeon/orbeon-forms/issues/4976

As a quick update on this, #4976 is now implemented, will be in 2021.1, and you can find the documentation on:


-Alex
Reply all
Reply to author
Forward
0 new messages