Implement role-based access control for internal users

This section describes the Commerce role-based access control system, and describes how you can use it to limit which internal users can access specific shopper data.

Understand property access control

There are a number of property attributes that are used to specify the behavior of the access control system. In particular, the following are the primary attributes used to control which users can read or write the value of a property:

  • readRole – You can set this attribute to the ID of a role. Users with the specified role can see the property value.
  • writeRole – You can set this attribute to the ID of a role. Users with the specified role can set or change the property value.
  • readAccessRight – You can set this attribute to the ID of an access right. Users with the specified access right can see the property value.
  • writeAccessRight – You can set this attribute to the ID of an access right. Users with the specified access right can set or change the property value.

By default, these attributes are null for any given property, which means that any user who is logged in can see and modify the property’s value. When you set one or more of these attributes, you are actually revoking access from users who lack the specified role or access right. Note that each attribute can only be set to a single ID.

There are several additional attributes that affect how access control works. These attributes are discussed later in this chapter.

Note: Subsystems of Commerce that exchange data with external systems (for example, webhooks and bulk export and import) are not affected by property access control settings. If you want to restrict property access in these subsystems, you may need to implement access control on the external systems.

In addition, the Freemarker email templates included with Commerce are not affected by property access control settings. If you want to restrict property access in emails your store sends, you must manually remove properties from the templates. (See Customize Email Templates for more information.)

The next section describes how roles and access rights are applied to properties and users.

Understand roles and access rights

Oracle CX Commerce includes a number of roles that control access to various parts of the administration interface and the Agent Console. For example, the Catalog role grants access to the Catalog page. One or more roles can be assigned to a user in the administration interface. See Configure Internal User Accounts for more information.

You can also use roles to control which properties a user can see or edit. For example, if you set the writeRole attribute of a property to adminRole, only users with the Administrator role can set the value of the property.

In addition to roles, Commerce can use access rights to control which properties a user can see and modify. An access right is essentially a label that can be associated with properties and with individual users. If a specific access right is associated with a property, only users who have that access right are permitted access to that property. For example, if you create an access right called ar1, and you set the readAccessRight attribute of a property to ar1, then only users who have that access right can view the value of the property.

Users are associated with access rights through roles. An individual role can have multiple access rights assigned to it, and an individual access right can be assigned to multiple roles. Using access rights thus provides greater flexibility than using roles alone.

A user’s ability to access properties is determined both by the roles the user has and by the access rights those roles have:

  • A user has read access to a property if the user has the role that is specified by the property’s readRole attribute, or if the user has a role that has the access right that is specified by the property’s readAccessRight attribute.
  • A user has write access to a property if the user has the role that is specified by a property’s writeRole attribute, or if the user has a role that has the access right that is specified by the property’s writeAccessRight attribute.

You should make sure that your settings for these attributes do not result in any users having write access to a property but not read access. Such a user would be able to modify the property’s values but not be able to see the changes he or she makes.

To avoid this situation, be careful when you set these attributes to ensure that the users with write access to a given property are a subset of those with read access. Here are some examples:

  • If you want all users to be able to see a property’s values, but want only administrators to be able to modify the values, then you could set the writeRole attribute to adminRole, and leave readRole null.
  • If you do not want any users to be able to edit the values of a property, you could set the writeAccessRight attribute to an access right that is not assigned to any roles (and therefore is not associated with any users). You can then use readRole or readAccessRight to assign read access as desired.
  • If you want a certain group of users to have read and write access to a property, but for no other users to have either form of access, you could set writeRole and readRole to the same role.

Bypass access settings for storefront shoppers

Access control can be applied to shoppers as well as to internal users. As a result, when you restrict access to specific profile properties, you may unintentionally prevent shoppers from accessing their own profile data. For example, if you allow only users who have the Administrator role to access shopper email addresses, then shoppers will not be able to see or edit their own email addresses when they view their profiles.

To avoid this issue, the following attributes can be used to enable shoppers to bypass any access restrictions on properties in their own profiles:

  • shopperReadable -- Set this to true to bypass any role or access right security when a shopper views the property on the shopper’s own profile. Default is false.
  • shopperWriteable -- Set this to true to bypass any role or access right security when a shopper edits the property on the shopper’s own profile. Default is false.

Create access rights for internal users and assign them to roles

By default, Commerce does not include any access rights for internal users. If you want to use access rights, you need to create them using the createAdminAccessRight endpoint in the Admin API. For example:

POST /ccadmin/v1/adminAccessRights  HTTP/1.1
Authorization: Bearer <access_token>
Content-Type: application/json

{
    "displayName": "Access Right 1",
    "name": "ar1",
    "repositoryId": "ar1",
    "description": "First of several access rights."
}

Once you have created an access right, you can assign it to existing roles using the updateAdminRole endpoint in the Admin API. For example:

PUT /ccadmin/v1/adminRoles/catalogRole  HTTP/1.1
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "accessRights": [
    {
      "repositoryId": "ar1"
    }
  ]
}

The response is similar to this:

{
    "name": "Catalog",
    "repositoryId": "catalogRole",
    "description": "Catalog Role",
    "links": [
        {
           "rel": "self",
           "href": "http://www.example.com:7002/ccadmin/v1/adminRoles/catalogRole"
        }
    ],
    "accessRights": [
        {
           "displayName": "Access Right 1",
           "name": "ar1",
           "repositoryId": "ar1",
           "description": "First of several access rights."
        }
    ],
    "category": "Commerce"
}

Create custom roles for internal users

In addition to the standard roles it includes, Commerce provides support for creating custom roles. For example, you might want to create a role for providing access to sensitive data, and assign it to a very limited set of users. You could then restrict access to certain properties by setting their readRole and writeRole attributes to this role. Or you could create an access right that you assign to the custom role, and then set the readAccessRight and writeAccessRight attributes to this access right.

To create a custom role, use the createAdminRoles endpoint in the Admin API. For example:

POST /ccadmin/v1/adminRoles  HTTP/1.1
Authorization: Bearer <access_token>
x-ccasset-language: en

{
  "name": "Auditor",
  "repositoryId": "audit",
  "description": "User with access to sensitive data.",
  "accessRights": [
    {
      "repositoryId": "ar10"
    }
  ]
}

The response is similar to this:

{
    "name": "Auditor",
    "repositoryId": "audit",
    "description": "User with access to sensitive data.",
    "links": [
        {
            "rel": "self",
            "href": "http://www.example.com:7002/ccadmin/v1/adminRoles"
        }
    ],
    "accessRights": [
        {
            "displayName": "Access Right 10",
            "name": "ar10",
            "repositoryId": "ar10",
            "description": "Controls access to very sensitive information."
        }
    ],
    "category": "Custom"
}

Note that, as shown in this example, you can create the role and assign access rights to it in the same call. Alternatively, you can create the role and later assign access rights using the updateAdminRole endpoint, or just use the role (without access rights) to control property access.

Configure the data to return

Properties have two attributes, readSecurityLevel and writeSecurityLevel, that control how Commerce responds when a user lacking the necessary role or access right attempts to access the property.

The readSecurityLevel attribute can be set to one of the following values:

  • ignore – Return a masking value rather than the actual value of the property. If readSecurityLevel is not set, it defaults to ignore.
  • deny – Omit the property from the response entirely. This option is available only for custom properties.

The writeSecurityLevel attribute can be set to one of the following values:

  • ignore – Attempts to modify the property value will fail silently. If writeSecurityLevel is not set, it defaults to ignore.
  • deny – Attempts to modify the property value will result in errors. Note, however, if the user attempts to set the value to the same value that was originally returned (that is, either the current value of the property or a masking value, depending on the user’s read access), no error will result. This is to handle cases where a form populated with current values attempts to write all of those values back when it is submitted. This option is available only for custom properties.

Note that the values of these attributes have an effect only if read or write access attributes are set on the property as well. For example, if the readSecurityLevel attribute is set to deny for a custom property, the property is omitted from a response only if read access is restricted by the readRole or readAccessRight attribute, and the user does not have the specified role or access right.

Return masking values

If the value of a property’s readSecurityLevel attribute is ignore, then attempts to access the property by users lacking the necessary access right or role return a placeholder called a masking value. The logic for determining the value is as follows:

  • If the property is not required, null is returned.
  • If the property is required, and its default value is set, the default value is returned. (Note that for a custom property that is required, the default value must be set.)
  • If the property is required, and its default value is not set, a generic value is returned. The value depends on the data type of the property:
    • String – the empty string
    • Numeric value -- 0
    • Date or timestamp -- Jan 1 1970
    • Enumeration -- the first enumerated value

You can override this logic by explicitly specifying a placeholder value for the property using the securityMaskingValue attribute. For example, you might want to set the placeholder value for strings to “XXXXX,” to make it clear that the actual value is being suppressed rather than empty. Note that the securityMaskingValue you specify must match the data type of the property.

Set access control on properties

To set the access control attributes on specific properties, you use the endpoints in the Admin API for modifying the item type for those properties. For example, to configure access control on profile properties, you use the updateShopperType endpoint to modify the user shopper type.

The following example illustrates setting the role and access right attributes of a property, as well as its securityMaskingValue:

PUT /ccadmin/v1/shopperTypes/user  HTTP/1.1
Authorization: Bearer <access_token>
x-ccasset-language: en
Content-Type: application/json

{
 "properties": {
     "lastName": {
         "readRole": "audit",
         "writeRole": "audit",
         "readAccessRight": "ar10",
         "writeAccessRight": "ar10",
         "shopperReadable": true,
         "shopperWriteable": true,
         "securityMaskingValue": "XXXXX"
    }
  }
}

The response shows the attribute values you set:

...
"lastName": {
    "shopperWriteable": true,
    "readRole": "audit",
    "readSecurityLevel": null,
    "readAccessRight": "ar10",
    "securityMaskingValue": "XXXXX",
    "length": 254,
    "shopperReadable": true,
    "label": "Last Name",
    "type": "shortText",
    "writeSecurityLevel": null,
    "writeAccessRight": "ar10",
    "required": false,
    "searchable": false,
    "writable": true,
    "internalOnly": false,
    "uiEditorType": "shortText",
    "default": null,
    "audienceVisibility": null,
    "localizable": false,
    "textSearchable": false,
    "writeRole": "audit",
    "dimension": false,
    "editableAttributes": [
        "shopperWriteable",
        "readRole",
        "readSecurityLevel",
        "readAccessRight",
        "securityMaskingValue",
        "shopperReadable",
        "label",
        "writeSecurityLevel",
        "writeAccessRight",
        "required",
        "searchable",
        "internalOnly",
        "default",
        "audienceVisibility",
        "textSearchable",
        "writeRole",
        "dimension",
        "multiSelect"
    ],
    "multiSelect": null
},
...

These settings restrict both read and write access to only users that either have the audit role or the ar10 access right. If a user has neither of these and attempts to view a shopper’s profile, the lastName property value is masked in the response. For example:

...
"lastName": "XXXXX",
"GDPRProfileP13nConsentDate": null,
"GDPRProfileP13nConsentGranted": false,
"gender": "female",
...

Note that you should not set access-control attributes on a property that points to another object or collection of objects. Instead, set the attributes on the individual properties of the objects.

For a property that holds an array of strings or numeric values, you can set access-control attributes to specify access rights and roles, but you cannot set the securityMaskingValue attribute.