Announcement: You can find the guides for Commerce 7.5 and later on the new Elastic Path Documentation site. This Developer Center contains the guides for Commerce 6.13.0 through 7.4.1.Visit new site

This version of Elastic Path Commerce is no longer supported or maintained. To upgrade to the latest version, contact your Elastic Path representative.

Cortex Authorization

Cortex Authorization

Apache Shiro is a role-based access control framework (RBAC). Shiro provides a dynamic security model where roles and permissions can be configured at run time.

Role Based Access Control works by restricting the CRUD operations logged in users can perform on Cortex resources. Depending on a user's role, they may only have permission to view (Read) a resource, or they may be able to insert (Create), update, or delete data through a resource.

Resource Authorization Workflow

When Cortex receives a request with an access token, it generates a Subject object. The subject represents the user's log in state and contains a list of operations the user is authorized to perform.

When the request reaches the resource, the ResourceKernel verifies the Subject object and checks the user's permissions. If the request has the proper permissions, the resource kernel forwards the request to the resource for processing. If the request does not have the proper permissions, a 401 or 403 status code is returned.

Roles and Permissions

What are Roles and Permissions?

Roles

In Shiro, a role is a set of permissions. When a user logs into Cortex, a role is assigned to the user. Depending on the role, a customer may be restricted from executing create, read, update, or delete operations in the API.

Out of the box, Cortex has three roles:

Role Description
relos.role.REGISTERED This role applies to an authenticated user with an customer account.
relos.role.PUBLIC This role applies to an authenticated user that does not have a customer account.
relos.role.OWNER

This role applies to REGISTERED and PUBLIC customers. The role restricts customers (PUBLIC and REGISTERED) to access only their own carts, orders, and so on. Other customers, who are not the OWNER of the cart, order, and so on cannot access them.

For example, carts has the following configuration: relos.role.OWNER=CREATE,READ,UPDATE,DELETE:{base.scope}:{carts.cartId} This means only the owner of the cart, whether they are PUBLIC or REGISTERED, can CREATE,READ,UPDATE, etc. their cart. Other customers, who are not the owner of the cart, do not have access to that cart.

Roles are hierarchical, meaning that higher-level roles inherit the permissions assigned to roles below them. For example, out of the box, REGISTERED is above PUBLIC so REGISTERED inherits all of PUBLIC's permissions.

Note: Adding 'relos.role.' before each role is required syntax. Any role defined without this syntax are removed through a permissions filter.

Permissions

In Shiro, a permission defines what a user can do in Cortex.

Out of the box, Cortex has five role permissions:

Permission Description
CREATE Users may create new information in the resource
READ Users may read from the resource
UPDATE Users may update data in the resource
DELETE Users delete data from the resource
LINK

Users may link between certain resources.

INFO Provides meta information on a resource. Currently only supports maximum age of a resource.
ADVISE_READ

Users may advise certain resources on a READ operation.

ADVISE_CREATE

Users may advise certain resources on a CREATE operation.

ADVISE_UPDATE

Users may advise certain resources on an UPDATE operation.

ADVISE_DELETE

Users may advise certain resources on a DELETE operation.

Permission Parameters

Permission parameters refine permissions, allowing you to apply permissions to a specific instance of a resource. For example, the cartId parameter restricts a user's permissions so they only apply to the user's own cart.

Out of the box, Cortex has the following permission parameters. The following parameters are exclusive to a resource:

Parameter Description Resource
addresses.address-id The user's address Addresses
carts.cart-id The user's cart Carts
emails.email-id The user's email Emails
orders.order-id The order associated with a user's cart Orders
paymentMethodId The user's payment method PaymentMethods
profiles.profile-id The user's profile Profiles
purchases.purchase-id The user's purchase Purchases
shipmentdetails.shipment-details-id The user's shipment details ShipmentDetails
wishlists.wishlist-id The ID of the user's wishlist Wishlists

The following parameters are available for all resources:

Parameter Description
{base.scope} The store scope the user belongs to
Special Parameters

In addition to the permission parameters described above, Cortex has special permission parameters to further refine your permissions:

Parameter Description
*

A wildcard parameter. Applies the permission to all the resource's elements and subresources.

By default, Shiro appends a * parameter at the end of all role permissions.

default

A parameter that can be used in place of CartId, PaymentMethodId, profile-id and wishlistId.

Cortex resolves default to the id of the logged in user.

EOL

A parameter that prevents permissions from applying to the resource's elements and subresources.

{unauthenticated}

A parameter that prevents REGISTERED from inheriting this permission from PUBLIC.

Only applicable for the Registrations resource. You must manually apply this parameter when extending or altering the Registrations resource.

URIs and Permissions

When assigning permissions to resources, it can be helpful to understand how URI and URI-parts map from their display in Cortex Studio to their use in the permissions files.

The overall pattern for URIs in permissions is the following:

:{RESOURCE-FAMILY.PARAMETER}:{URI-PART}               
               

Where {RESOURCE-FAMILY.PARAMETER} is the resource's base family, and {URI-PART} is a resource identifier, like form. In many cases, {RESOURCE-FAMILY.PARAMETER} is {base.scope}. For more information on resource identifiers, see Resource Identifiers.

For example: The URI of the Orders resource displays in Cortex Studio as scope/orders/. To apply the CREATE permission to Orders, you would do the following:

relos.role.PUBLIC=CREATE:{base.scope}:{orders}
               

Shiro allows for wildcards at any point in the URI, using *. For example:

relos.role.PUBLIC=CREATE:{base.scope}:*:{orders}
               

The above would apply the CREATE permission to any URI with the pattern scope/[something]/orders, but not to, say scope/orders/[something].

By default, Shiro applies * to the end of all URIs. Meaning relos.role.PUBLIC=CREATE:{base.scope}:{orders} applies CREATE to scope/orders and all resources below it. For example, if scope/orders/profiles/ existed, profiles would recieve CREATE as well.

Sometimes you only want to apply permissions to a resource, but not its children. To do this, use EOL:

relos.role.PUBLIC=CREATE:{base.scope}:{orders}:EOL                  
               

Configuring Roles and Permissions in a Custom Resource

After creating a custom Cortex resource, you need to assign roles and permissions to restrict the operations a user can perform with the resource. You can use the provided roles and permissions and any new roles and permission you created. For instructions on how to create your own roles and permissions, see Creating Your own Roles and Permissions.

Defining Default Roles and Permissions

  1. In your resource project's root directory, navigate to src/main/resources (or for old resources navigate to src/main/resources/OSGI-INF/config)
  2. With a text editor, open permissions.properties
  3. In permissions.properties, define your resource's default role permissions. For information on how to define role permissions, see Assigning Permissions to a Role.
    Note: Assigning Permissions Note

    When assigning your resource permissions in permissions.properties, don't surround your permissions and parameters with double quotations. For example:

    relos.role.PUBLIC=LINK:*

Making Roles and Permissions Configurable During Runtime

To support the ability to configure your resource's roles and permissions during runtime, modify your resource's src/main/resources/spring/applicationContext-resource-server.xml:

  1. With a text editor, open applicationContext-resource-server.xml
  2. Modify the overrideRolePermissionsProvider bean's persistent-id to the name of the resource's role and permissions configuration file.
  3. For example, in items:

overrideBean.png

For information on the role and permissions configuration file, see Modifying the Roles and Permissions of an Existing Resource.

Defining Permission Parameter Strategies

Permission parameter strategies for Helix resources and legacy resources are defined in slightly different manners.

Permission Parameter Strategies for Helix Resources

Permission parameters are configured in a Helix resource by extending the AbstractHelixModule class, and binding PermissionParameterStrategy to the class:

For more information, see Configuring Prototypes.

Permission Parameter Strategies for Legacy Resources

To add permission parameters to a custom legacy resource's resource permissions, assign the parameter to a parameter strategy in the resource's permissionParameterResolver.

The following steps show how to add a permissionParameterResolver to your custom resource:
  1. With a text editor, open your resource's src/main/resources/spring/applicationContext-resource-server.xml
  2. Add constructor arguments to the permissionParameterResolver bean to specify each parameter and its resolution strategy.
  3. For example, to define the permissionParameterResolver for a READ:{base.scope}:{resourceFamilyId.resourceId} permission:
    <bean name="permissionParameterResolver" class="com.elasticpath.rest.authorization.parameter.PermissionParameterResolver">
    		<constructor-arg>
    			<map>
    				<entry key="scope" value-ref="scopeParameterStrategy"/commerce-legacy/>
    				<entry key="resourceId" value-ref="yourResourceIdParameterStrategy"/commerce-legacy/>
     			</map>
    		</constructor-arg>
    	</bean>

The scopeParameterStrategy is predefined in Cortex, but the custom yourResourceIdParameterStrategy needs to be implemented.

Out of the box,Cortex has the following parameter types and strategies:

Parameter Type Strategy
Scope ScopeParameterStrategy

Creating Your own Roles and Permissions

Adding New Roles to the Role Hierarchy

Cortex uses a role hierarchy to enable roles to implicitly include the parent role's access rights. Out of the box, a role hierarchy has been defined where Customer is above Anonymous so Customer inherits all of Anonymous' permissions. If you want to define or add to the Role Hierarchy, edit the roleHierarchy.config file. Once a new roleHierarchy.config file is created, the API overrides the predefined role hierarchy with the hierarchy defined in the new config file.

Role hierarchy takes effect without having to restart Cortex.

To add new roles to the role hierarchy:
  1. Create a roleHierarchy.config file in either the /ep/cortex/conf/permissions or ${user.home}/ep/cortex/conf/permissions directory.
  2. Add roles starting with the lowest-level role (role with the least permissions) to highest-level role (role with the most permissions) following this format:
  • roles=["ROLE_LOWEST","ROLE_HIGHER",...,"ROLE_HIGHEST"]

    For example, to add a new IDENTIFIED role that inherits from PUBLIC:

    roles=["PUBLIC","IDENTIFIED","REGISTERED"]
    Note: Role Hierarchy

    Role Hierarchy must start with the role of an unauthenticated user, eg. PUBLIC

Modifying the Roles and Permissions of an Existing Resource

Cortex resources have predefined roles and permissions. Configure an existing resource's permissions by defining new permissions in a <Resource_Name>RolePermissions.config file. Permissions take effect without having to restart Cortex.

Note: RolePermissions.config Note

When the Cortex detects a <Resource_Name>RolePermissions.config file, the API ignores the resource's predefined role permissions and applies only the permissions defined in the <Resource_Name>RolePermissions.config file.

Assigning Permissions to a Role

  1. Create a <Resource Name>RolePermissions.config file in either the /ep/cortex/conf/permissions or ${user.home}/ep/cortex/conf/permissions directory.
  2. To assign permissions to a role, add the role and its permissions in the following format to the resource's <Resource Name>RolePermissions.config file:
ROLE=ROLE_PERMISSION:{RESOURCE-FAMILY.PARAMETER}

PARAMETER can be included optionally if you want to refine your permission to a specific instance of a resource. For a list of permission parameters supported for each out of the box resources, see Permission Parameters.

For example, to allow anonymous customers to create and read their own order, create an ordersRolePermissions.config file in your permissions directory and set the following role permissions:

relos.role.PUBLIC=LINK:*;CREATE,READ:{base.scope}:{orders.orderId}
Warning: EOL Warning

Do not surround default, EOL and * permission parameters with curly braces.

Warning: Empty Permission Warning

Do not assign empty permission strings to your roles. Roles with empty permission strings throw exceptions and the last known valid permissions assignment will be used.

To prevent a role from accessing your resource, use EOL:

relos.role.PUBLIC=EOL

Assigning Multiple Permissions to a Role

Role permissions are defined on a single line. To assign multiple role permissions and permission parameters, structure your permission assignment as shown:
  • To assign same parameter to multiple role permissions, separate permissions with commas as shown:
    ROLE=ROLE_PERMISSION_1,ROLE_PERMISSION_2:{RESOURCE-FAMILY.PARAMETER}
  • To assign multiple parameters to the same role permissions, separate parameters with colons as shown:
    ROLE=ROLE_PERMISSION:{RESOURCE-FAMILY.PARAMETER_1}:{RESOURCE-FAMILY.PARAMETER_2}
  • To assign different parameters to different role permissions, separate sets of role permissions and parameters with semicolons as shown:
    ROLE=ROLE_PERMISSION_1:{RESOURCE-FAMILY.PARAMETER_1};ROLE_PERMISSION_2:{RESOURCE-FAMILY.PARAMETER_2}

Advise Parameters

The ADVISE permissions ADVISE_READ, ADVISE_CREATE, ADVISE_UPDATE and ADVISE_DELETE use the same permission parameters as LINK. For example, the following ADVISE_READ permission allows only the carts and items resources to be advised when the user is anonymous:
relos.role.PUBLIC=ADVISE_READ:carts,items

Do not surround ADVISE_* parameters with curly braces.

To permit all resources to use any ADVISE capability, list each of the ADVISE operation and use *:
relos.role.PUBLIC=ADVISE_READ:*,ADVISE_CREATE:*,ADVISE_UPDATE:*,ADVISE_DELETE:*

Configuring Role Permissions through the Felix Web Console

After creating your <Resource_Name>RolePermissions.config file, you can modify your resource's permissions through the Apache Felix Web Console.

Note: RolePermissions.config Note

Without a <Resource_Name>RolePermissions.config file, you cannot modify your resource's role permissions through the Felix Web Console.

To configure your permissions through the Felix Web Console:
  1. Log into the Felix Web Console:
    1. Navigate to http://[server]:[port]/system/console/configMgr. If Cortex is running locally at port 8080, the URL is http://localhost:8080/cortex/system/console/configMgr.
    2. Enter the User Name and Password in the Authentication dialog box:

      Felix Login

      The default credentials are as follows:
      User Name Password
      admin admin
  2. Set the permissions:
    1. Click <Resource Name>RolePermissions WebConsoleRolePermissions.jpg
    2. Modify your resource's role permissions. For information on how to define role permissions, see Assigning Permissions to a Role. WEBCONSOLE.png
    3. Click Save

    Permissions save to the <Resource Name>RolePermissions.config file will take effect immediately.