Authorization Policy examples

Authorization Policy examples

This article presents example Authorization Policy configurations for some typical uses cases. For SSO Authorization Policy documentation, please refer to:

Manage authorization policies - SSO

Expression language API - SSO

These configuration examples have been tested with Ubisecure SSO 8.8.1.

Contents

User and method attributes

In a typical configuration, either user attributes (attributes from Ubisecure Directory, external LDAP directory or external SQL database) or method attributes (claims from external Identity Providers) are passed on to applications with the Authorization Policy configuration. Simple examples are shown below:

Group

Name

Value

eIDMUser

given_name

${user['givenName']}

FTN Users

given_name

${method['urn:oid:1.2.246.575.1.14']}

Azure Users

email

${method['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']}

 

When external identities are mapped to Ubisecure identities (see Management UI Directory User Mappings - SSO and User driven federation - SSO), both user attributes and method attributes may be available. In this case, the method attributes can be accessed by using a local user group, typically eIDMUser, instead of a group configured for the Identity Provider. For example, name is taken form the local user directory and job title from an Azure AD claim as follows:

Group

Name

Value

eIDMUser

given_name

${user['givenName']}

eIDMUser

family_name

${user['sn']}

eIDMUser

job_title

${method['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/title']}

Single-value and multi-value attributes

By default, all attributes are processed as multi-value attributes. Attributes can be defined as single-value attributes on the main screen of the Authorization Policy configuration:

In JWT tokens, single-value attributes are passed as string values and multi-value attributes as string lists. Boolean and numeric values are converted to strings. Whenever an attribute is known to take only one value, it is recommended to define the attribute as a single-value attribute. Below, an example JWT is presented with a default configuration and with single-value attributes defined:

Default configuration
{ "sub": "ubisecure.demo@example.com", "iss": "https://login.ubidemo.com:8443/uas", "amr": [ "https://login.ubidemo.com:8443/uas/saml2/names/ac/password.2" ], "aud": [ "0baaf7ce-8df8-4cb9-9ecc-de9a6e00a792" ], "azp": "0baaf7ce-8df8-4cb9-9ecc-de9a6e00a792", "auth_time": 1640871824, "iat": 1640871827, "exp": 1640875426, "session_index": "_208fb80205c891f3ec45cf4e5cd0379e403c211e", "email": [ "ubisecure.demo@example.com" ], "family_name": [ "Demo" ], "given_name": [ "Ubisecure" ], "roles": [ "services/RoleRequester", "eIDM/eIDMMainUser" ], "surname": "Demo" }

 

Single-value attributes defined
{ "sub": "ubisecure.demo@example.com", "iss": "https://login.ubidemo.com:8443/uas", "amr": [ "https://login.ubidemo.com:8443/uas/saml2/names/ac/password.2" ], "aud": [ "0baaf7ce-8df8-4cb9-9ecc-de9a6e00a792" ], "azp": "0baaf7ce-8df8-4cb9-9ecc-de9a6e00a792", "auth_time": 1640871518, "iat": 1640871524, "exp": 1640875124, "session_index": "_af24c0650721e4795ee796a2e567779ad846144a", "email": "ubisecure.demo@example.com", "given_name": "Ubisecure", "roles": [ "services/RoleRequester", "eIDM/eIDMMainUser" ], "family_name": "Demo" }

String value operations

String value attributes can be modified by using Java EL statements with Java String methods. Information on Java String methods can be found, for example, at https://www.w3schools.com/java/java_ref_string.asp. Some configuration examples are presented below:

Name

Value

Example Data

Example Result

given_name

${user['givenName'][0].toUpperCase()}

givenName=Michael

"MICHAEL"

full_name

${user['givenName'][0].concat(' ').concat(user['sn'][0])}

givenName=Michael, sn=Jones

"Michael Jones"

is_employee

${user['mail'][0].toLowerCase().endsWith('@ubisecure.com')}

mail=user.demo@customer.com

"false"

email_domain

${user['mail'][0].substring(user['mail'][0].indexOf('@')+1)}

mail=ubisecure.demo@example.com

"example.com"

test_account

${user['givenName'][0].toLowerCase().contains('application_test')}

givenName=Application_Test

"true"

birthdate

${method['urn:oid:1.2.246.21'][0].contains('-') ? "19".concat(method['urn:oid:1.2.246.21'][0].substring(4, 6)).concat("-").concat(method['urn:oid:1.2.246.21'][0].substring(2, 4)).concat("-").concat(method['urn:oid:1.2.246.21'][0].substring(0, 2)) : "20".concat(method['urn:oid:1.2.246.21'][0].substring(4, 6)).concat("-").concat(method['urn:oid:1.2.246.21'][0].substring(2, 4)).concat("-").concat(method['urn:oid:1.2.246.21'][0].substring(0, 2))}

150990-304Y

100302A017X

1990-09-15

2002-03-10

mobile

${user['mobile'][0].startsWith('0') ? '+358'.concat(user['mobile'][0].substring(1)) : user['mobile'][0]}

0401234567

+4422334456

+358401234567

+4422334456

 

String values can also be modified by using regular expressions with the re:replace function, for example as follows:

Name

Value

Comment

Example Data

Example Result

given_name

${re:replace(method['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/displayname'], ".*, ", "")}

Replace all characters until the first comma followed by a space, by a null string

Jones, Michael

"Michael"

family_name

${re:replace(method['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/displayname'], ", .*", "")}

Replace the comma and anything after that by a null string

Jones, Michael

"Jones"

employee_id

${re:replace(method['employee_id'], ".*-", "")}

Replace all characters until '-' by a null string

Operations-123456

"123456"

email_domain

${re:replace(user['mail'][0], ".*@", "")}

Replace all characters until '@' by a null string

ubisecure.demo@example.com

"example.com"

given_name

${re:replace(method['name'], "^([^ ]+) (.+)$", "$1")}

Define anything until the first space as the 1st capturing group and the remaining characters as the 2nd group

Michael Jones

"Michael"

family_name

${re:replace(method['name'], "^([^ ]+) (.+)$", "$2")}

Define anything until the first space as the 1st capturing group and the remaining characters as the 2nd group

Michael Jones
Michael De Jong

"Jones"
"De Jong"

given_name

${re:replace(method['name'], "^(.*) (.+)$", "$1")}

Define anything until the last space as the 1st capturing group and the remaining characters as the 2nd group

Michael Jones
Michael M Jones

"Michael"
"Michael M"

 

List value matching and filtering

Note: Ubisecure CustomerID SSO Adapter can also be used for filtering the roles, see Authorization configuration - CustomerID.

Typical claims presented as lists are users' role and group assignments. If there are a limited number of known groups or roles, and there is a need to filter out any other groups/roles, it is straightforward to use the contains function for filtering. This way the generic group/role names can also be mapped to application specific names when needed. Some examples are given below.

Name

Value

Comment

Example Data

Example Result

groups

${user['memberOf'].contains('CN=SEAdmins,OU=abc,DC=example,DC=com') ? 'SEAdmins' : null}
${user['memberOf'].contains('CN=PrintUsers,OU=abc,DC=example,DC=com') ? 'PrintUsers' : null}

Use CN instead of the whole Distinguished Name

CN=SEAdmins,OU=abc,DC=example,DC=com, CN=PrintUsers,OU=abc,DC=example,DC=com

["SEAdmins", "PrintUsers"]

groups

${user['memberOf'].contains('CN=SEAdmins,OU=abc,DC=example,DC=com') ? 'Admin_Group' : null}

Map the group name to an application specific name, filter out all other groups

CN=SEAdmins,OU=abc,DC=example,DC=com, CN=PrintUsers,OU=abc,DC=example,DC=com

["Admin_Group"]

roles

${eidm['roles'].contains('services/extranet/User') ? 'services/extranet/User' : null}
${eidm['roles'].contains('services/extranet/MainUser') ? 'services/extranet/MainUser' : null}

Filter out all but the application specific roles

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, services/extranet/Mainuser

["services/extranet/Mainuser"]

roles

${eidm['roles'].contains('services/extranet/User') ? 'ExtranetUser' : null}
${eidm['roles'].contains('services/extranet/MainUser') ? 'ExtranetMainUser' : null}

Map role names to application specific roles, filter out all but the application specific roles

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, services/extranet/Mainuser

["ExtranetMainuser"]

 

If the groups or roles are not known (for example, defined by an external Identity Provider) or there can be a big or unlimited number of them (for example, roles with organization name as prefix), a more generic way for filtering is required. In this case, Java EL streams can be used for matching and filtering the string lists. For more detailed information, please refer to Java EL documentation: https://download.oracle.com/otndocs/jcp/el-3_0-fr-eval-spec/index.html. Some example configurations are presented below.

Name

Value

Comment

Example Data

Example Result

user_type

${eidm['roles'].stream().anyMatch(r -> r.endsWith('OrganizationMainUser')).orElse(false) ? 'adminuser' : 'normaluser'}

User is adminuser if they have OrganizationMainUser role in any organization

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser

"adminuser"

is_admin

${eidm['roles'].stream().anyMatch(r -> r.contains('OrganizationMainUser')).get()}

True / False based on OrganizationMainUser role in any organization

SmartPlan/OrganizationUser

"false"

enduser_roles

${eidm['roles'].stream().filter(r -> not r.contains('OrganizationMainUser')).toList()}

All roles excluding OrganizationMainUser roles

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser

["SmartPlan/OrganizationUser"]

service_admin_roles

${eidm['roles'].stream().filter(r -> r.toLowerCase().contains('mainuser')).filter(r -> not r.contains('OrganizationMainUser')).toList()}

All roles containing "mainuser" regardless of case, excluding "OrganizationMainUser"

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, extranet/Mainuser

["extranet/Mainuser"]

roles

${eidm['roles'].stream().filter(r -> not (r.startsWith('Users/') or r.startsWith('eIDM/'))).toList()}

All roles excluding roles in organizations "Users" and "eIDM"

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, eIDM/eIDMMainUser, Users/VerifiedUser

["SmartPlan/OrganizationMainUser", "SmartPlan/OrganizationUser"]

nr_of_roles

${eidm['roles'].stream().filter(r -> not (r.startsWith('Users/') or r.startsWith('eIDM/'))).toList().size()}

Number of roles, excluding roles in organizations "Users" and "eIDM"

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, eIDM/eIDMMainUser, Users/VerifiedUser

"2"

roles

${eidm['roles'].stream().sorted().toList()}

All roles sorted alphabetically

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, extranet/Mainuser

["SmartPlan/OrganizationMainUser", "SmartPlan/OrganizationUser", "extranet/Mainuser"]

roles

${eidm['roles'].stream().sorted().substream(1).toList()}

All roles sorted alphabetically, then excluding the first one

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, extranet/Mainuser

["SmartPlan/OrganizationUser", "extranet/Mainuser"]

List value modifications

For modifying string values within the lists, a new list can be created with the Java split function. In the examples below, we use split("&") for converting a string to a list with one element. Here we assume that the data does not contain any '&' characters.

Name

Value

Comment

Example Data

Example Result

roles

${eidm['roles'].stream().flatMap(r -> r.toLowerCase().split("&").stream()).toList()}

Convert all role names to lower case

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser

["smartplan/organizationmainuser", "smartplan/organizationuser"]

roles

${eidm['roles'].stream().flatMap(r -> r.substring(r.lastIndexOf('/')+1).split("&").stream()).toList()}

Exclude the path of role names

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser

["OrganizationMainUser", "OrganizationUser"]

roles

${eidm['roles'].stream().flatMap(r -> r.substring(r.lastIndexOf('/')+1).toLowerCase().split("&").stream()).sorted().distinct().toList()}

Exclude the path of role names, convert to lower case, sort and remove duplicates

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, Citygroup/OrganizationUser

["organizationmainuser", "organizationuser"]

groups

${user['memberOf'].stream().flatMap(r -> r.substring(3, r.indexOf(',')).split("&").stream()).toList()}

Extract CN from the DN strings: take the characters from the 4th position until the next comma

CN=SEAdmins,OU=abc,DC=example,DC=com, CN=PrintUsers,OU=abc,DC=example,DC=com

["SEAdmins", "PrintUsers"]

groups

${user['ubiloginMemberOf'].stream().flatMap(r -> r.split(",").stream()).filter(r -> r.contains('CN=') and not r.contains('CN=Ubilogin')).toList()}

Extract CN from the DN strings, exclude "CN=Ubilogin"

CN=Test Group,OU=Test,CN=Ubilogin,DC=login,DC=smartplan,DC=com, CN=Test Group 2,OU=Test,CN=Ubilogin,DC=login,DC=smartplan,DC=com

["CN=Test Group", "CN=Test Group 2"]

Hashing and encoding examples

The following examples show hashing and encoding. Note data type requirements for hashing and encoding functions.

Name

Value

Comment

Example Data

Example Result

Name

Value

Comment

Example Data

Example Result

email

${attribute.name("email").values(sha256.text('exampleAppString'.concat(user.telephoneNumber[0])).toString().concat('@example.com'))}

Generate a virtual email address formed by hashing user attributes.

Here a hash is a made of application specific string concatenated together a custom userId that is stored in user.telephoneNumber. The email domain is added to the resulting string.

123456

794f037115472dd0831df46a01e300a970507b6632a493915c8e1e59fa1a0d47@example.com

uidbase64

${base64:encode(utf8:bytes(user['uid'][0]))}

Base64 encode user.uid. Because base64:encode() function requires a bytearray as input parameter, and user.uid is String, it needs to be converted to bytearray using utf8:bytes().

jsmith

anNtaXRo

Role Based Access Control

The Ubisecure SSO Authorization Policies can be used for implementing Role Based Access Control (RBAC). With RBAC, only users having application specific role(s) assigned, are allowed to access the application. Other users see an error message which is configurable for each application.

Note: RBAC can be enforced either by Ubisecure SSO or by the application user is trying to access. When access is denied, it may be more straightforward to configure the application to give user-friendly instructions for requesting access rights. 

To enforce RBAC in Ubisecure SSO, define a required attribute on the main screen of the Authorization Policy configuration, for example "extranet-access":

Then use the "Attributes" tab to define the required attribute, for example as follows:

Name

Value

Example Data

Example Result

extranet-access

${eidm['roles'].contains('services/extranet/User') ? 'true' : null}
${eidm['roles'].contains('services/extranet/MainUser') ? 'true' : null}

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser, services/extranet/Mainuser

SmartPlan/OrganizationMainUser, SmartPlan/OrganizationUser

"true"

not set

For instructions on defining application specific error messages and other user interface properties, please refer to:

Login user interface customization files - SSO
Show different help text depending on the application used