OFBiz Security Permissions - OFBiz Project Open Wiki - Apache Software Foundation
DUE TO SPAM, SIGN-UP IS DISABLED. Goto
Selfserve wiki signup
and request an account.
OFBiz Project Open Wiki
Pages
Space shortcuts
How-to articles
Child pages
Technical Documentation
OFBiz Security Permissions
Content management security - not reviewed
How to secure your deployment
Implementing a Permission Service
Security Administration
Security Services - Developer
Browse pages
Access to add and change pages is restricted. See:
tachments (0)
Page History
Resolved comments
Page Information
View in Hierarchy
View Source
Export to PDF
Export to Word
Copy Page Tree
Jira links
OFBiz Security Permissions
Created by
Hans Bakker
, last modified by
Jacques Le Roux
on
Oct 01, 2025
Security, as discussed in this article, is about permissions being granted to access OFBiz artifacts such as services, screens and data.
How permissions are organised (the 2 levels of security)
The larger domain of security is split into 2 categories in OFBiz:
application/functionality level security
data level security
Category 1 (user permission, eg ORDERMGR_CREATE
is
UserLogin dependent
and doesn't know about anything except the UserLogin, the permissions checked for different screens, services, etc, and the SecurityGroup structure that maps between them.
Category 2 (party permission, eg ORDERMGR_ROLE_CREATE) is
Party dependent
and can be combined with Category 1, usually with special "
role limited
" permissions that require not just the permission, but some
relationship
between the Party and whatever artifact are being controlled. This supports quite a wide range of access control.
It should be possible (in theory, not tested) to use Category 1 security without the party component. However, Category 2 is very dependent on the Party data object and the data object related to it.
This is the general design. What exists OOTB in OFBiz has various examples of both, but no attempt has been made to create a comprehensive or at least "generically complete" set of security settings in either style #1 or #2. Though some effort has been done to add more granular permissions in Category 1 (like ORDERMGR_SALES_CREATE, see above and below for details), this is an area of customization that tends to be pretty complex and there is possibly as much variety in it as there are combinations of relationships of entities in OFBiz.
If you need to know more details look at
Security Administration
Wrong use of "role limited" permissions
Note that a "role limited" permissions to work
requires
an enforcing relationship to be used. There are currently a number of cases in OFBiz where "role limited" permissions are used without enforcing relationships. For instance often the this dev ML thread
. In
this other user ML thread
a solution is proposed to prevent this to spread all over the code. Two other propositions has been discussed some years ago, notably this
OFBiz Security Redesign
There was also this
discussion
about
NIST and RBAC (Role Based Access Control)
started by Ruth. But has Adrian's remarked (many times) we have always this technical discrepancy between users (userLogin) and parties (Party). In OFBiz an user and a party have different meanings (a party may use several different userLogins).
Also note though that there are cases where the alternative permission could be used, but not with "role limited" permissions, only user permissions. For instance someone may not have the right to create all types of order but only sales orders. Then with the primary permission defined ORDERMGR_CREATE this person can't create a sales order but with the alternative permission defined as ORDERMGR_SALES_CREATE it's possible. As you see access permissions can be a very complex topic!
The following is a technical description explaining security and permissions in OFBiz.
How to use permissions
Category 1 is based on
ecurityPermissions
records
. The names of permissions consist out of two parts separated with a '_' character. Most of the time, the first part is the application name and the second part is the action or operation. The application name is normally the same as the component name (or webapp name in case of sub-component webapp) written in uppercase characters. The action can be anything. However VIEW, CREATE, UPDATE, DELETE (related to
CRUD functions
) and ADMIN are the most commonly used. ADMIN is a special action which allows all operations.
For example, the security permission for creating an order, is ORDERMGR_CREATE. The application is the Order Manager (ORDERMGR) and the action is 'CREATE' which indicates that this permission controls the creation of an new order. OOTB, this permission is granted to the 'ORDERENTRY'
ecurityGroup
entity, so every user ID (userLoginId) which is part of the ORDERENTRY group can create orders.
We currently have several systems/levels where this is implemented:
At login level
The
base-permission
defined in the ofbiz-component.xml file as an attribute of the To login an user must have at least the permission COMPONENT-NAME_VIEW or COMPONENT-NAME_ADMIN permission. Most of the components have the values
OFBTOOLS
coupled with generally a COMPONENT-NAME permission. This means that
both
OFBTOOLS and (comma is used as an
AND
operator in the definition of base-permissions) COMPONENT-NAME_VIEW (or COMPONENT-NAME_ADMIN permission) are required to get access to the web app. The OFBTOOLS is needed to allows permission to every web application configuration.
Note also that the NONE base-permission allows anyone without any specific permission to access to the component. Also, due to how permissions constituents are parsed, you can't have underscores in the COMPONENT-NAME.
The
base-permission,
which is still widely used in OFBiz OOTB, has been deprecated.
A new
access-permission
attribute of has been introduced
after this exchange
but has not yet replaced base-permission (there are none occurrences of access-permission in OOTB trunk code)
Note (to be reviewed/discussed)
After Adrian's 1s post in the thread above, I checked if OFBTOOLS is really strictly needed to gain access to a component. This is not the case for a number of components (take assemaint for instance) which can be at least accessed by the admin. But this needs to be clarified
(only the admin?)
and it seems we should no
longer
wait to replace base-permission by the clearer access-permission in trunk. I don't know why
Adrian Crum
did not continue, maybe only lack of time?
At the component menu level
It's pretty simple to use. The component top-level menu will only show the components to which a logged-on user has at least the WEBAPP-NAME_VIEW or COMPONENT-NAME_ADMIN permissions, i.e. the same as on the login level. This is done in appbar.ftl which defines which tabs are visible in the applications tabs bar.
At the request (controller.xml) level
Though not related with permissions, there are two important parameters here. Every request (At screen level
In the ''  or '' can be shown.
You may also use At Freemarker template snippet level
The session variable
security
is always
present in the screen context
. You can use it to request security informations using Security class public methods: hasPermission, hasEntityPermission, hasRolePermission.
At service definition level
This functionnality allows the (re-)usage of services in other components with a different security schema. An example is the project manager component which uses many services of the workeffort component but has a different security schema.
In the service definition, (files in the servicedef directory) the 'You can extend the base permission service using ECA rules on the permission service used by the service you want to reuse. Just have it run your permission service after the main one IFF the main one results in an error (failed permission check), and make sure your ECA rule has it put its results in the context if your security scenario succeeds.
A good basic implementation example is exampleGenericPermission in the Example component
At service implementation level.
Minilanguage.
Using the
check-permission
and
if-has-permission
tags to check the access.
Java and Groovy.
Using the
org.ofbiz.security.Security API
methods such as
hasEntityPermission.
At record level, by using Role limited permissions or related means
The purpose of role-limited permissions is to tie a SecurityPermission to record level security using the RoleType/PartyRole and related entities. In OFBiz this is how record level permissions are done, i.e. somehow the user (through her Party record) is associated with another record in the database and that specific relationship must exist in order for the role-limited permission to take effect.
A good example is in the secondary hasPermission method in OrderServices class or how ProductStoreRole, ContentAndRole, PartyRole, entities are used in Java code (and at large
ENTITY-NAME
Role entities).
Note how the main OrderService.hasPermission() method uses the OrderRole entity without explicit role-limited permission. See also checkStoreCustomerRole in ProductEvents class for the same with the ProductStoreRole entity.
A view entity can also be used to define a path from the Party in question to the target/desired entity through relationships. This is usually do-able and easy to do with a single view entity, and if a query on that entity with the proper constraints returns any results then you know the user/party has the permission. See for instance the ProductCategoryMemberAndRole view entity in the checkProductRelatedPermission (in the ProductServices.xml file) and how are the catalog role limited permissions defined and used for an example.
You can imagine your own ways in function of your requirements...
Protected views
This is another mechanism which is used to protect from data leakage (data stolen from a login/password couple compromised). It works like the well known grey list anti-spam feature (aka tarpitting). It's pretty simple to use.
You define the views you want to protect under a Security Group using the Protected Views menu.
There you define the
View name using uri attribute of request-map element (controller.xml file)
Maximum number of visits (per period)
Duration during which the visits are considered (in seconds)
Duration during which the view will not be accessible (in seconds). This parameter defines the tarpitting period.
You don't have to define anything else for the protected views mechanism to work. If you don't define a "protect" response, in case of blocked screen, it will be rendered blank by default.
But you may define a generic (per instance) "protect" response view which will be rendered by default using the default.error.response.view parameter in security.properties.
Instead of only per request or per instance (setting in security.properties), you may also define a "protect" view by application using a element in controller.xml. If the "protect" response is not found, first it will check for an application default before falling back to per instance.
The code use a simple strategy as we don't need something very sophisticated to trap malignants. It's all in ProtectViewWorker.java.
Data model
All these levels rely on several database tables:
SecurityPermission
: the lowest level where all basic permissions are defined. Typically used to set up the standard permissions (_ADMIN, _CREATE and _DELETE). If there is a need, the same set of permissions may be created with a "_ROLE" in there. Examples are: CATALOG_ADMIN, CATALOG_CREATE, CATALOG_DELETE, CATALOG_ROLE_ADMIN, CATALOG_ROLE_CREATE.
SecurityGroup
: where the permission group is defined. For setting up groups that typically have blanket permissions. FULLADMIN and PARTYADMIN are examples.
SecurityGroupPermission
: permissions are grouped together in this table. Associates SecurityPermission with SecurityGroup.
UserLoginSecurityGroup
: Which userLogin id's have access to which permission groups. This is where parties can be associated with SecurityGroup. Note: Parties are associated with SecurityGroup by their userLoginId, but when adding a party to an entity role entity, the partyId is used.
PartyRelationship
: security groups can be set for certain party relationships.
ENTITY-NAME
Role
(OrderRole, PartyRole, etc.):
The org.ofbiz.core.security.OFBizSecurity class contains methods for applying/using these tables.
Here is some stuff that David wrote in an email that shows 2 cases where group permissions are used:
has CONTENTMGR_VIEW (or CONTENTMGR_ADMIN, handled by hasEntityPermission method)
has CONTENTMGR_ROLE_VIEW (or CONTENTMGR_ROLE_ADMIN) and partyId of current userLogin is associated with the Content in the ContentRole table (in this case with any roleTypeId) (see
Content management security
But finally In an exchange with Anil
, David did not recommend to use these "old" Security class public methods (hasPermission, hasEntityPermission, hasRolePermission) but to rather use the "new" pattern used in
ProductServices.xm::checkProductRelatedPermission Groovy method:
Expand source
/**
* Check Product Related Permission
* a method to centralize product security code, meant to be called in-line with
*/
Map checkProductRelatedPermission(String callingMethodName, String checkAction) {
callingMethodName = callingMethodName ?: UtilProperties.getMessage('CommonUiLabels', 'CommonPermissionThisOperation', parameters.locale)
if (UtilValidate.isEmpty(checkAction)) {
checkAction = 'UPDATE'
List roleCategories = []
// find all role-categories that this product is a member of
if (parameters.productId && !security.hasEntityPermission('CATALOG', "_${checkAction}", parameters.userLogin)) {
Map lookupRoleCategoriesMap = [productId: parameters.productId,
partyId: userLogin.partyId,
roleTypeId: 'LTD_ADMIN']
roleCategories = from('ProductCategoryMemberAndRole')
.where(lookupRoleCategoriesMap)
.filterByDate('roleFromDate', 'roleThruDate')
.queryList()

if (!(security.hasEntityPermission('CATALOG', "_${checkAction}", parameters.userLogin)
|| (roleCategories && security.hasEntityPermission('CATALOG_ROLE', "_${checkAction}", parameters.userLogin))
|| (parameters.alternatePermissionRoot &&
security.hasEntityPermission(parameters.alternatePermissionRoot, "_${checkAction}", parameters.userLogin)))) {
String checkActionLabel = "ProductCatalog${checkAction.charAt(0)}${checkAction.substring(1).toLowerCase()}PermissionError"
return error(UtilProperties.getMessage('ProductUiLabels', checkActionLabel,
[resourceDescription: callingMethodName, mainAction: checkAction], parameters.locale))
return success()
technical
security
Overview
Content Tools
Atlassian Confluence Open Source Project License
granted to Apache Software Foundation.
Evaluate Confluence today
Atlassian Confluence
8.5.31
Printed by Atlassian Confluence 8.5.31
Report a bug
Atlassian News
Atlassian
{"serverDuration": 76, "requestCorrelationId": "708bf074b6fa4498"}