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 (Create Read Update Delete) 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
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 the following roles:
relos.role.REGISTERED
This role applies to an authenticated user with a 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
andPUBLIC
customers. The role restricts customers to access only their own carts, orders, and so on. Other customers, who are not theOWNER
of the cart, order, and so on cannot access them.For example, carts have the following configuration:
relos.role.OWNER=CREATE,READ,UPDATE,DELETE:{base.scope}:{carts.cartId}
. Only the owner of a cart, whetherPUBLIC
orREGISTERED
users, canCREATE
,READ
, orUPDATE
their cart. Other customers, who are not the owner of the cart, do not have access to that cart
Roles are hierarchical. The higher-level roles inherit the permissions assigned to roles below them. For example, by default, REGISTERED
is above PUBLIC
so REGISTERED
inherits the permissions of PUBLIC
.
note
Adding 'relos.role.
' before each role is the required syntax. Any role defined without this syntax are ignored.
Permissions
In Shiro, a permission defines what a user can do in Cortex.
By default, Cortex has the following role permissions:
CREATE
Specifies that the users can create new information in the resource.
READ
Specifies that the users can read from the resource.
UPDATE
Specifies that the users can update data in the resource.
DELETE
Specifies that the users can delete data from the resource.
LINK
Specifies that the users can link between certain resources.
INFO
Provides meta information on a resource. Currently supports maximum age of a resource only.
ADVISE_READ
Users may advise certain resources on a
READ
operationADVISE_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:
{base.scope}
- The scope of the store that the user belongs to
Special Parameters
In addition to the permission parameters described above, Cortex has special permission parameters to further refine your permissions:
*
A wildcard parameter. Applies the permission to all the resource’s elements and subresources.
default
A parameter that can be used in place of
CartId
,PaymentMethodId
,profile-id
andwishlistId
.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 fromPUBLIC
.Only applicable for the registrations resource. You must manually apply this parameter when you extend or change the registrations resource
URIs and Permissions
The pattern for URIs in permissions is: :{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 the orders resources, do the following: relos.role.PUBLIC=CREATE:{base.scope}:{orders}:EOL
With Shiro, you can use wild cards at any point in the URI, using *
. For example: relos.role.PUBLIC=CREATE:{base.scope}:*:{orders}:EOL
The above would apply the CREATE
permission to any URI with the pattern scope/[something]/orders
, but not to scope/orders/[something]
.
note
You must add EOL
at the end of the permission string to ensure that the same permissions are not applied to the child resources within the resource. To apply changes to the child resources within the resource, add the wild character *
at the end of the permission string.
For example, to apply permissions only to a resource, use EOL
at the end of the permission string: relos.role.PUBLIC=CREATE:{base.scope}:{orders}:EOL
Configuring Roles and Permissions in a Custom Resource
After creating a custom Cortex resource, you must assign roles and permissions to restrict the operations a user can perform with the resource. You can use the available roles and permissions or any new roles and permission you created. For instructions on creating roles and permissions, see Creating Your own Roles and Permissions.
Defining Default Roles and Permissions
In your resource project’s root directory, navigate to
src/main/resources
(or for old resources navigate tosrc/main/resources/OSGI-INF/config
)With a text editor, open
permission.properties
In
permission.properties
, define your resource’s default role permissions. For information on how to define role permissions, see Assigning Permissions to a Role.
Assigning Permissions Note
When assigning your resource permissions in permission.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
:
With a text editor, open
applicationContext-resource-server.xml
Modify the
overrideRolePermissionsProvider
bean’spersistent-id
to the name of the resource’s role and permissions configuration file.For example, in items:
For information on the role and permissions configuration file, see Modifying the Roles and Permissions of an Existing Resource.
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:
With a text editor, open your resource’s
src/main/resources/spring/applicationContext-resource-server.xml
Add constructor arguments to the
permissionParameterResolver
bean to specify each parameter and its resolution strategyFor example, to define the
permissionParameterResolver
for aREAD:{base.scope}:{resourceFamilyId.resourceId}
permission:<bean name="permissionParameterResolver" class="com.elasticpath.rest.authorization.parameter.PermissionParameterResolver"> <constructor-arg> <map> <entry key="scope" value-ref="scopeParameterStrategy"/> <entry key="resourceId" value-ref="yourResourceIdParameterStrategy"/> </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:
- 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:
Create a
roleHierarchy.config
file in either the/ep/conf/cortex/permissions
or${user.home}/ep/conf/cortex/permissions
directory.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"]
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 <Family_Name>RolePermissions.config
file. Permissions take effect without having to restart Cortex.
note
When the Cortex detects a <Family_Name>RolePermissions.config
file, the API ignores the resource’s predefined role permissions and applies only the permissions defined in the <Family_Name>RolePermissions.config
file.
Assigning Permissions to a Role
Create a
<Family_Name>RolePermissions.config
file in either the/ep/cortex/conf/permissions
or${user.home}/ep/conf/cortex/permissions
directory.To assign permissions to a role, add the role and its permissions in the following format to the resource’s
<Family_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}
`EOL` Warning
Do not surround default, EOL
and *
permission parameters with curly braces.
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}
Link
Parameters
The LINK
permission uses different permission parameters. For this permission, you specify the resources the role can link to. For example, the following LINK
permission allows only the carts and items resources to link to your resource when the user is anonymous:
relos.role.PUBLIC=LINK:carts,items
Do not surround LINK
parameters with curly braces.
To permit all resources to link to your resource, use *
:
relos.role.PUBLIC=LINK:*
Advise Parameters
The following ADVISE
permissions use the same permission parameters as LINK
.
ADVISE_READ
ADVISE_CREATE
ADVISE_UPDATE
ADVISE_DELETE
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 <Family_Name>RolePermissions.config
file, you can modify your resource’s permissions through the Apache Felix Web Console.
note
Without a <Family_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:
Log into the Felix Web Console:
Navigate to
http://[server]:[port]/system/console/configMgr
. If Cortex is running locally at port8080
, the URL ishttp://localhost:8080/cortex/system/console/configMgr
.Enter the User Name and Password in the Authentication dialog box:
The default credentials are as follows:
- Username:
admin
- Password:
admin
- Username:
Set the permissions:
- Click
<Resource Name>RolePermissions
- Modify your resource’s role permissions. For information on how to define role permissions, see Assigning Permissions to a Role
- Click Save
- Click
Permissions save to the <Family_Name>RolePermissions.config
file will take effect immediately.