-
Notifications
You must be signed in to change notification settings - Fork 221
Form Runner ~ Access Control
This page describes how to secure Form Runner depending on your usage scenario.
When it comes to access control, Orbeon Forms leverages and delegates as much as possible to your existing security infrastructure:
- You define users and roles outside of Orbeon Forms.
- Whenever possible, access control is path-based, so you can define who can access what based on the path in the URL with your existing security infrastructure.
You can have access control at two levels:
- Form level – Can the current user access this form?
- Field level – If the current user can access the form, can they access a particular field? If they can, can they change the field or just read its value?
You implement the later in your form definition, by using the $fr-roles
in the in the visibility and read-only XPath expressions of the Form Builder control validation dialog. You can make a control non-visible to the current user by defining a visibility expression that returns false. If the control is visible, you can make it read-only to current user by defining a read-only expression that returns true. The rest of this page focuses on form-level access control.
Form Runner uses the username, group, and roles to control who can access Form Builder and the forms you create with Form Builder (see the two sections above for more details on how those are setup). Form Runner can obtain this information by calling a standard servlet API implemented by your application server (container-driven method) or by using HTTP headers (header-driver method), typically set by a front-end (e.g. Apache module) or a servlet filter.
[SINCE 2011-07-01]
You want to use container roles if your users are setup at the application server level, with container managed security. In Tomcat, this would correspond to using a security realm, which in its simplest form gets users from Tomcat's conf/tomcat-users.xml
. To setup container-driven roles, configure your form-builder-permissions.xml
as described above, then:
-
Enable container-driven method – To do so, set the following property in your
properties-local.xml
:<property as="xs:string" name="oxf.fr.authentication.method" value="container"/>
-
List possible roles – There is no container API for Orbeon Forms to ask for all the roles for the current user; instead Orbeon Forms can only ask if the current user has a specific role. Because of this, you need to list the possible roles in the following property. For instance, if you have two roles
form-builder-hr
andform-builder-finance
define it as:<property as="xs:string" name="oxf.fr.authentication.container.roles" value="form-builder-hr form-builder-finance"/>
There is no container API for Orbeon Forms to get the user's group; in fact the concept of _group_is foreign the container API. So, when using container-driven method, Orbeon Forms takes the first role listed in oxf.fr.authentication.container.roles
that the user has as the user's group. If you need more flexibility in determining what the user's group is, you might want to use header-driven method instead, which allows you to explicitly set through a header what the user's group is (more on this below).
3. Require authentication – You'll also want to have another role, say form-builder
, that you grant to all the users who can access Form Builder. Hence, in our example, users will have either the two roles form-builder
and form-builder-hr
, or the two roles form-builder
and form-builder-finance
. In Orbeon Forms WEB-INF/web.xml
, add the following to require users to login to access Form Builder. This assumes that you're using basic authentication:
```xml
<security-constraint>
<web-resource-collection>
<web-resource-name>Form Builder</web-resource-name>
<url-pattern>/fr/orbeon/builder/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>form-builder</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>form-builder</role-name>
</security-role>
```
You want to use header-driven method if you have a servlet filter, single sign-on software, or other system that sets the roles for the current user in an HTTP header. To use header-driven method, configure your form-builder-permissions.xml
as described above, then:
-
Enable header-driven method – To do so, set the following property in your
properties-local.xml
:<property as="xs:string" name="oxf.fr.authentication.method" value="header"/>
-
Header name – Tell Orbeon Forms what is the name of the HTTP headers that will contain the username, group, and roles for the current user.
<property as="xs:string" name="oxf.fr.authentication.header.username" value="My-Username-Header"/> <property as="xs:string" name="oxf.fr.authentication.header.group" value="My-Group-Header"/> <property as="xs:string" name="oxf.fr.authentication.header.roles" value="My-Roles-Header"/>
The header oxf.fr.authentication.header.roles
consists of a list of comma- or pipe-separated role names, for example: "Administrator, Power User, User" or"Administrator | Power User | User". White space around the commas or pipes is ignored. In addition or alternatively, multiple role headers can be provided, and each of them is split according to those roles. The resulting set of roles is the combination of all roles extracted from all role headers.
3. Forwarding headers — When using header-based authentication, in addition to defining the name of the headers Form Runner gets the username and role from oxf.fr.authentication.header.username
and oxf.fr.authentication.header.roles
, you need to add those header names to the oxf.xforms.forward-submission-headers
property, so the headers are forwarded by the XForms engine to Form Runner. For instance:
```xml
<property
as="xs:string"
name="oxf.xforms.forward-submission-headers"
value="My-Username-Header My-Group-Header My-Roles-Header"/>
```
-
LDAP-style header syntax (Optional) – The value of the header is a list of roles separated by spaces, commas, or pipes (
|
). Furthermore, they can optionally be composed of properties in the form ofname=value
, wherename
is specified by a configuration property, andvalue
is the value of the role. This is typically useful the value if the header follows an LDAP-style syntax, for instance:cn=role1,dc=acme,dc=ch|cn=role2,dc=acme,dc=ch
. If your header follows a LDAP-style syntax, set the following property to configure what "name" contains the header, which in this example iscn
:<property as="xs:string" name="oxf.fr.authentication.header.roles.property-name" value="cn"/>
[SINCE 2011-05-18]
-
Username/role from headers or container — Orbeon Forms automatically adds two headers, which are available within Orbeon Forms applications, in particularForm Runner:
-
Orbeon-Username
— if present, the value contains the current username- if
oxf.fr.authentication.method == "container"
:- obtained through the servlet/portlet container's
getRemoteUser()
function
- obtained through the servlet/portlet container's
- if `oxf.fr.authentication.method == "header"
- obtained via the header specified by
oxf.fr.authentication.header.username
- obtained via the header specified by
- if
-
Orbeon-Roles
— if present, is a list of values, each with one role- if
oxf.fr.authentication.method == "container"
:- each role listed in
oxf.fr.authentication.container.roles
is checked against the container'sisUserInRole()
function
- each role listed in
- if
oxf.fr.authentication.method == "header"
- obtained via the header specified by
oxf.fr.authentication.header.roles
- obtained via the header specified by
- if
-
Persistence — These headers are forwarded to the persistence layer, which can make use of them. In particular, the relational persistence layers store the current username when doing any database update.
See also: Accessing liferay users and roles.
[SINCE Orbeon Forms 4.0]
For forms created in Form Builder, you can restrict which users can access which forms, and what operations they can perform. Those restrictions apply to the forms you create once they are deployed, not to editing those forms in Form Builder (for the latter, see the section that follows: Access control for editing forms).
By default, no restriction is imposed on who can do what with forms you create in Form Builder. You enable permissions by going to the Form Builder sidebar, and under Advanced, clicking on Set Permissions.
This shows the following dialog:
After you click on the checkbox, you'll be able to set access restriction on the create, read, update, and delete operations:
- On the Anyone line, set the operations allowed to all users.
- On the Owner line, set the operations allowed to the user who created the data. [SINCE Orbeon Forms 4.3]
- On the_Group members_line, set the operations allowed to users in the same group as the owner. [SINCE Orbeon Forms 4.3]
- On the following lines, you can enter a role name, and define what operations users with that role can perform.
In the example below:
- Any user to fill out a new form.
- Users with the role _clerk_to read data.
- Users with the role admin to do any operation, including deleting form data.
- Permissions you set in the dialog are additive –Say you defined permissions for two roles, where users with the_reader_role can read and users in the_clerk_role can delete, users with both roles (reader_and_clerk)are allowed to perform both operations (reading and deleting).
- Operation on Anyone apply to all other rows – When you select a checkbox for a given operation on the first Anyone row, that checkbox will be automatically checked and disabled so you can't change it, for any additional row, since you wouldn't want to authorize users with additional roles to perform less operations.
- Update implies read – On any row, if you check update, then read will be automatically checked, as it wouldn't make sense to say that some users can update data, but can't read it, as when updating data, obviously, they must be shown the data they are updating.
- Create can't be set for the owner and group members – The owner/group is a piece of information attached to existing form data, keeping track of the user who create the data, and the group in which this user is. This information is only known for existing data, so assigning the create permission to the owner or group members doesn't make sense, and the dialog doesn't show that checkbox.
- Permissions for the owner and group members can be setindependently– If you want data to be accessible only by people who created it, check read/update/delete for the owner but not for group members. If you want data to be accessible by all people in the same group,check read/update/delete for the group members and don't check them for the owner if you want the owner to loose access to that data in case the owner changes group. (The latter highlights the need for permissions owner and group member to be set independently.)
This part of the documentation has moved.
Which operations the current user can perform drives what page they can access, and on some pages which buttons are shown:
-
On the Form Runner home page, all the forms on which the current user can perform at least one operation are displayed. Then, for each one of those forms:
- If they can perform the create operation on the form, a link to the new page is shown.
- If they can perform any of the read, update, or delete operation on the form, a link to the summary page for that form is shown.
-
For the summary page:
- Access is completely denied if the current user can't perform any of the read, update, or delete operations.
- The delete button is disabled if the current user can't perform the delete operation.
- The review and pdf button are disabled if the current user can't perform the read operation.
- Clicking in a row of the table will open the form in edit mode if the current user can perform the update operation, in view mode if they can perform the read operation, and do nothing otherwise.
-
For the view page, access is denied if the current user can't perform the read operation.
-
For the new page, access is denied if the current user can't perform the create operation.
-
For the edit page, access is denied if the current user can't perform the update operation.
[SINCE 4.3] In Orbeon Forms 4.2 and earlier, role-based permissions set in Form Builder could only be driven by container-based roles and the value of the oxf.fr.authentication.method
property was not taken into account. Since version 4.3, those permissions also apply if you are using header-driven roles.
Given the assumptions made in the previous section, the paths used by Form Builder look as follows:
Path | Description |
---|---|
/orbeon/fr/orbeon/builder/new |
To create a new form. |
/orbeon/fr/orbeon/builder/edit/{id} |
To edit a form with the given id. |
/orbeon/fr/orbeon/builder/summary |
To view all the editable forms. |
If you have multiple classes want to give access to Form Builder to one class of users, and those users are able to edit any form in any app, the you can use path-based access restrictions, as described the previous section.
This is configured with form-builder-permissions.xml
.
If you'd like to have multiple classes of Form Builder users where some case edit, say, form in the hr
app, while other can edit forms in the sales
app, then you'll want to setup the form-builder-permissions.xml
.
NOTE: [SINCE 2011-09-07] The file is now called form-builder-permissions.xml
file. It replaces the file called form-runner-roles.xml
. For backward compatibility, form-runner-roles.xml
is still supported.
In this file you map role names to applications and forms. For instance, the following tells Orbeon Forms that only users with the role hr-form-editor
can edit or create forms in the hr
app, and only users with the role sales-form-editor
can edit or create forms in the sales
app. As you can infer from the syntax, you could be even more specific and only give access to users with a given role to a specific form in a specific app.
<roles>
<role name="hr-form-editor" app="hr" form="*"/>
<role name="sales-form-editor" app="sales" form="*"/>
</roles>
NOTE: Each <role>
element refers to as single role name. It is not possible to place multiple space-separated roles in the name
attribute.
Orbeon Forms can infer the roles for the current user either based on information it gets from the container or from an HTTP header. Those two cases are detailed in the following two sections. Once you've defined your form-builder-permissions.xml
and done the appropriate setup for container-driven or header-driven roles, as described below:
- The Form Builder summary page will only show the forms users have access to.
- When they create a new form, if users don't have the right to create a form in any app, instead of seeing a text field where they can enter the application name, they will see a drop-down listing the possible application, as shown in the following screenshot:
[LIMITATION] Restrictions on the form name in form-builder-permissions.xml
are at this point not supported; only restrictions on the app name are supported. This means that you should always use form="*"
. If you define a restriction on the form name, it won't be enforced at the time the form is created, allowing users to create, save, and publish a form with an undesirable name. However they then won't be able to see the form they created when going back to the summary page.
[SINCE Orbeon Forms 4.3]
form-builder-permissions.xml
also impacts the Form Runner Home page, which supports unpublishing and publishing forms.
If the configuration is unchanged, by default users cannot unpublish/publish from the Home page. In order to allow this feature, you must configure at least one <role>
.
In general, the behavior is as follows:
-
by default no
<role>
elements are present- for the Form Builder Summary and New pages, this is equivalent to:
<role name="*" app="*" form="*">
-
for the Form Runner Home page
- no
<role>
elements- user cannot unpublish/publish any forms
- user cannot see unavailable forms
- with
<role name="*" app="*" form="*">
:- user can unpublish/publish any forms
- user sees unavailable forms
- no
This logic ensures:
- that Form Builder is usable out of the box even without setting Form Builder permissions
- that the Form Runner Home page, which can by default be accessed by any user unless it is explicitly protected, does not inadvertently provide access to administrative functions
-
Setup at least one user and role for your container.
- The easiest way to do this with Tomcat, if you don't have already users setup within your system (via a Tomcat realm for example), is to modify Tomcat's
tomcat-users.xml
file, for example as follows:
<tomcat-users> <user username="orbeon-admin" password="Secret, change me!" roles="orbeon-admin"/> </tomcat-users>
- The easiest way to do this with Tomcat, if you don't have already users setup within your system (via a Tomcat realm for example), is to modify Tomcat's
-
Enumerate the role in the following property:
<property as="xs:string" name="oxf.fr.authentication.container.roles" value="orbeon-admin"/>
-
Protect Form Builder and, optionally, the Form Runner Home page
- In web.xml, uncomment the permissions section.
- Replace:
<url-pattern>/fr/*</url-pattern>
with:
<url-pattern>/fr/orbeon/builder/*</url-pattern> <!-- Optional, to prevent anonymous users from accessing the Form Runner Home Page --> <url-pattern>/fr/</url-pattern>
and replace the role name:
<role-name>orbeon-user</role-name>
-
Set, in
form-builder-permissions.xml
:<role name="orbeon-admin" app="*" form="*"/>
-
Remove demo forms and apps from Orbeon Forms.
- Within Form Builder
- make sure that all your forms have permissions enabled (PE feature only)
- set the
create
permission for all users - set all permissions for the role
orbeon-admin
- republish your forms
- see also #1860)
- Configure forms' buttons
- You will want only a "Send" or "Submit" button, as a plain "Save" button doesn't make sense in this case.
With this setup:
- Published forms are not protected by the container. They are protected by Form Runner permissions.
- Form Builder is protected by the container so that anonymous users can't create new forms.
- Form Builder also requires
orbeon-admin
at the Orbeon Forms level. - Any user, logged in or anonymous, can create form data from any published form.
- All other operations (
read
,update
,delete
) are not available to anonymous users or logged in users without theorbeon-admin
role. Users with theorbeon-admin
role have - Users with the
orbeon-admin
role can perform any operations on the form data after they are logged in.
Limitations:
- Anonymous data entry does not support autosave.
- As an administrator, you first have to login, for example by accessing Form Builder, before accessing published forms' Summary page (issue #1292).