Security

Authentication is the process of identity verification and authorization is the process of determining access rights to resources in an application.

The authentication and authorization support in Axelor Open Platform is based on Apache Shiro.

In the next few sections we will see how authentication and authorization are supported in Axelor Open Platform.

Authentication

Authentication is the process of identity verification, i.e. allowing users to log in into to the system to use it.

The Axelor Open Platform is web application framework used to create web application. So by default it provided form based user authentication.

User information is backed by the application database and it’s also possible to integrate LDAP backend.

User

The User object has various properties, most important of them are:

  • code - the user login name

  • name - the display name

  • password - the password (stored encrypted in database)

  • blocked - whether the uses is blocked

  • activateOn - the time from when access should be activated

  • expiresOn - the time from when access should be expired

  • groups - the groups assigned to the user

  • roles - the roles assigned to the user

  • permissions - explicit permissions granted to the user

The groups, roles, and permissions are associated with authorization which we will see in next section.

Authorization

Authorization, also called access control, is the process of determining access rights to resources in an application.

Authorization is a critical element of any application but it can quickly become very complex. Based on the simplicity of Apache Shiro, the Axelor Open Platform provides very simple yet powerful way to define authorization rules.

Special user admin and members of group admins have full access to the all resources.

Features

  • Role based permissions

  • Permission defines single access rule (finer granularity)

  • Groups are for organizational structure but also supports roles & permissions

  • Deny all, grant selectively (proven most secure as all permissions are denied by default)

  • Package level permission rules

Authorization has four core elements permissions, roles, groups and users. They are represented by corresponding backing domain objects Permission, Role, Group and User respectively.

Objects

  • User has one Group

  • User has many Role

  • User has many Permission

  • Group has many Role

  • Group has many Permission

  • Role has many Permission

The relationship between the authorization objects allows achieve finer level of granularity on access control.

Permission

The permission object defines the access rule. It has following properties:

  • name - permission name

  • object - the object name (class name or wild card package name)

  • canRead - whether to grant read permission

  • canWrite - whether to grant update permission

  • canCreate - whether to grant create permission

  • canRemove - whether to grant delete permission

  • canExport - whether to grant export data permission

  • condition - permission condition (JPQL where clause with positional parameters)

  • conditionParams - comma separated list of condition params (evaluates against current context)

The condition is optional and the boolean flags are grant only, that is, false value doesn’t mean deny.

Some permission examples (pseudo code):

name: perm.sale.read.all
object: com.axelor.sale.db.*
canRead: true
name: perm.sale.create.all
object: com.axelor.sale.db.*
canCreate: true
name: perm.sale.self
object: com.axelor.sale.db.Order
canRead: true
canWrite: true
canRemove: true
canExport: true
condition: self.createdBy = ?
conditionParams: __user__

The first rule grants readonly permission to all the objects under com.axelor.sale.db package. The second rule grants create permission to all the objects under com.axelor.sale.db package. The third rule grants read, write, delete, export permission on com.axelor.sale.db.Order to the creator user.

The permission resolution is done in this order:

  • check for permissions assigned to the user object

  • check for permissions assigned to the roles of the user

  • check for the permissions assigned to the group of the user

  • check for the permissions assigned to the group’s roles

View Access

Similar to the object authorization, view access permissions can be used to control object view fields for users, groups and roles.

The Permission (fields) defined on User, Group and Role objects can be used to define permission rules for view item.

The permission rules are applied to the all views associated with the given object. The view items should have a name in order to define a rule for them.

The rule also allows setting client side conditions (js expressions) to control readonly/visiblity of the fields/items.

Some examples (pseudo code):

Define a rule to hide total amount
name: perm.sales.hide-total
object: com.axelor.sale.db.Order
rules:
  field: totalAmount
  canRead: false
  canWrite: false
  canExport: false
Define a rule to control customer field
name: perm.sales.customer-change
object: com.axelor.sale.db.Order
rules:
  field: customer
  canRead: true
  canWrite: true
  canExport: true
  readonlyIf: confirmed && __group__ == 'manager'
  hideIf: __group__ == 'user'

The first rule hides the totalAmount field from the views. The second rule defines how the customer field should behave depending on user group.

Unlike the object permission rules, view permission rules follows Grant all → Deny Selectively strategy.

LDAP

The authentication system has built-in support for LDAP integration.

In order to enable LDAP authentication, you have to set following configuration in your application.properties file:

# LDAP Configuration
# ~~~~~
ldap.server.url = ldap://localhost:10389

# can be "simple" or "CRAM-MD5"
ldap.auth.type = simple

ldap.system.user = uid=admin,ou=system
ldap.system.password = secret

# group search base
ldap.group.base = ou=groups,dc=example,dc=com

# if set, create groups on ldap server under ldap.group.base
ldap.group.object.class = groupOfUniqueNames

# a template to search groups by user login id
ldap.group.filter = (uniqueMember=uid={0})

# user search base
ldap.user.base = ou=users,dc=example,dc=com

# a template to search user by user login id
ldap.user.filter = (uid={0})

The most important settings here to understand are:

  • ldap.group.base - the search base for the groups

  • ldap.group.object.class - if set, groups are created on ldap server from database groups

  • ldap.group.filter - a filter template to search groups by user id, the {0} is replaced with user login name

  • ldap.user.base - the search base for the users

  • ldap.user.filter - a filter template to search user by user id, the {0} is replaced with the user login name

When a user first log in using an LDAP account, corresponding User/Group objects are created in the database. These objects can be used to configure permissions.

The LDAP user password is never stored in the database, the authentication is done on the LDAP server only. Also note that, there is no synchronization done between database object and LDAP objects.

SSO/CAS

In order to enable SSO/CAS authentication, you have to set following configuration in your application.properties file:

# CAS configuration
# ~~~~~
cas.server.url.prefix = https://localhost:8443/cas

# replace `https://localhost:8080` with accessible application url
cas.service = http://localhost:8080/axelor-demo/cas

# login url, if not given prepared from server & service url
cas.login.url = https://localhost:8443/cas/login?service=http://localhost:8080/axelor-demo/cas

# logout url, if not given prepared from server & service url
cas.logout.url = https://localhost:8443/cas/logout?service=http://localhost:8080/axelor-demo/

# CAS validation protocol (CAS, SAML)
cas.protocol = SAML

# the attribute to map to user display name
cas.attrs.user.name = name

# the attribute to map to user email
cas.attrs.user.email = mail
  • cas.server.url.prefix - cas server url, must be https

  • cas.service - the application service url (this is special service url to validate cas tickets)

  • cas.login.url - the cas login url, if not given, prepared from server & service url

  • cas.logout.url - the cas logout url, if not given, prepared from server & service url

  • cas.protocol - the cas validation protocol, (CAS, SAML), SAML is default as it supports attributes

  • cas.attrs.user.name - the name of the attribute to map to User.name field

  • cas.attrs.user.email - the name of the attribute to map to User.email field

If internal com.axelor.auth.db.User doesn’t exist for the authenticated user, a new user will be created with given cas.attrs.user.* attributes.