Product Guy & Entrepreneur
Any enterprise product you can imagine has roles & access controls from Emails to CRM to Accounting packages. Let’s start by understanding what Roles and Access controls are and why we need them.
Let’s take an example- an accounting software. The Accounting department does the following:
- Enter invoices
- Approve expenses of lower value
- Update Tax Rates
- Approve outflows of higher value
Different people could be performing these actions. Each of them has their own designation like junior accounts officer, Accounts Manager, Finance Controller etc. Each of them has a set of privileges based on expertise allowing them to perform operations of varying degrees of risk.
The accounts manager for payables should have access to only payables and can approve payments. The Accounts manager for receivables can approve incoming invoices and reconcile incoming payments.
There are a few aspects to understand:
Job Function: This defines what the actor is supposed to do in the system. It is a set of actions that encompass his/her job.
Actions: These are the individual activities that the actor has to perform. In the example above, it is the recording of invoices, raising payment requests, raising invoices, approving invoices etc.
In the world of products, job functions correspond to Roles. Each role has a set of associated actions which are assigned through controls.
Roles are a good way of managing permissions. It is easier to assign a role to a user than assigning each individual permissions. It is easy to manage when somebody starts performing a new role or moves departments. If there is a new action expected out of a job function, the role can be updated to reflect this. The alternative is to update every user associated with the action. Let’s talk about a few principles and things to consider when building roles & permissions.
Creation and management of roles should be independent of users. In other words, creation or modification of roles should be an activity independent of associating the role with a user.
Ideally, I should be able to create any number of roles in the system. Each role can have its own set of associated permissions. For example, Role 1 can allow Approve Payments and Role 2 can Disallow Approve Payments. If both Role 1 and Role 2 are associated to the same user, the system needs to have a conflict resolution mechanism. It could be a pessimistic resolution where Disallow always super cedes Allow or the other way around. I am sure there are audit implications based on the choices you make so consult a professional on this, I am not a CISSO.Permissions should be unambiguous and granular
In the accounting system example, let us assume there is a screen where payments can be raised in the system. The workflow is as follows:
It can be seen from the above process that there are several granular actions that go into the completion of one transaction — making a payment. A fatal design mistake would be to create a permission like “Payments Processing”. This means essentially 5 actions have been rolled into one without consideration that these could be done by different people in the real world. I have lived through the horrors that this mistake creates .This stems from the fact that people build products disconnected from how the user is going to use the product. In other words, lack of user research. Reworking access controls is like plunging a knife through the heart of your code if engineered poorly.
Another ground rule is to design the permissions such that any user can comprehend it. A good way to ensure this is to match the permission names to screen and action names. See the example below, Different names are assigned to the actions in the product and in the permissions list.
If an admin has to assign the permission to a role, how will he/she know what corresponds to these actions? If the action is called authorise on the screen, call it authorise in the access control list as well. These are the kind of mistakes that make your support phones to ring all day. Third party consultants implement your product because customers can’t do it themselves. This drives up implementation cost and lowers product adoption.
Strictly speaking, this is not something that falls under access control but it may cause a lot of problems if left unattended. Going back to our example, the payables manager should only see outgoing payments as opposed to the receivables manager who should see only incoming payments. This could be one listing with a flag indicating if it is an incoming or outgoing payment. The permissions assigned to the user are at the list level. To handle the next level of granularity, the system needs to handle data level permissions. I would do this at the user level rather than at a role level. So roles and data permissions can be associated independently with users. A word of caution, it is easy to overdo this, so build only if it is necessary and is a real problem for users in your application.
Allowing users to create roles requires a lot of thinking through and handling negative scenarios. I would advise an early stage startup that is still discovering its customers to wait longer before implementing this. For example, when you allow users to modify permissions within a role, you need to make sure there is an audit trail. Imagine that I had permissions to approve payments in my role a week ago. At that point, I had approved 3 payments. Someone decided to modify the role and revoke that permission yesterday. When an auditor looks at the transaction data, it will look like I performed an action for which I don’t have the permission. Unless you can prove through a trail that I had the permission as of the time of approval, your auditor will report an anomaly. This could go very badly in financial institutions dealing with public money.
A pre-shipped role that manages this problem. Users can edit the role so there is no need to expend effort on audit framework. The downside is that you need to have a really good understanding of your user or you are likely to mess it up. On the flip-side, if you don’t have a grasp of your user’s roles will be least of your worries.
You need to open up channels to your product so that it can live and breathe within an ecosystem of applications. This is especially true for SaaS products. So, roles & access need to be handled for other systems accessing your APIs. In other words, don’t put in place access controls only from the perspective of your front end accessing your APIs. Typically, you would allow third-party apps to access your APIs using a key. The key will act as an identifier and restrict the access to different parts of your application using roles.
A lot of products put in place the access controls in the front end and forget to secure it in the backend. If you are a product manager, make sure you mention this and ask your tech team to account for the backend in the estimate. A common mistake is to enable and hide links based on permissions and assume the user can’t break what he/she can’t see. An attacker can intercept the response and enable the screen very easily. This is a simple privilege escalation. The attacker can then assume admin rights, change passwords and lock legitimate users out of the system. Ensure that the backend does validations for every request.
If you are in the MVP stage of your product or even version 1, don’t try to build all these features in. Remember to distinguish between privacy, data safety, and access controls. I would prioritise the former over the latter.
Hope you found this post useful. On a related note, you can check out my post on building user registration flows in products here.
Create your free account to unlock your custom reading experience.