The move to the cloud and microservices has introduced new challenges in managing permissions. Software has been broken down into small, independently-deployable microservices, each with its own unique set of permissions. These permissions make it excruciatingly hard to ensure and track correct access. While this technological shift is challenging, it pales in comparison to the cultural and organizational shifts it has caused—one of which is the challenge of authorization for authorization. The challenge of authorization for authorization, or “controlling access control,” is a crucial but often misunderstood aspect of system design, and its recursive nature is quite confusing.
At its core, authorization for authorization deals with ‘meta-permissions’—the permission to grant and revoke permissions for the designed system.
Controlling Access Control
Deciding who can do things inside an application is one thing. Deciding who can decide (or, in other words, dealing with meta-permissions) is another story entirely. Once you start dealing with authorization for authorization, there are two main problems to contend with: Recursiveness, which is a technical challenge, and the question of trust, which can be hard to handle and can have dire consequences if handled incorrectly.
Naively, developers often choose to be the superusers—the ones calling the shots; retaining all of the power with them. This can produce a very stable and secure application, but will quickly put a strain on precious R&D resources, turning developers into bottlenecks for the entire business operation.
The opposite approach—delegating all of the power away from developers to other stakeholders—is equally dangerous, often creating a slow-moving, inefficient bureaucracy (looking at you, security and compliance) or an unstable, risk-filled environment (looking at you, sales and product).
At the end of the day, it’s a question of balance—one that varies for every company and application.
When building this balance, it’s important to empower the various stakeholders (and customers) working with the application, giving them a significant amount of control and decision-making abilities to enable the business to move quickly and securely while enabling developers to monitor the flow without becoming a bottleneck.
To keep you on track as you tackle this challenge, here are some guidelines, do’s, and don’ts:
Common Pitfalls to Avoid
● Don’t mix up authentication and authorization: This might seem trivial, but it happens all the time. Authentication is the process of identifying the user, while authorization is the process of granting access to specific resources based on the authenticated user’s roles or privileges. Solutions are required for both.
● Thinking you won’t need authorization for authorization: Simple systems may require meta-permissions functionality and advanced ones will undoubtedly need it. It’s important to consider when you’d need this ability and set the groundwork for it accordingly.
● Limiting access control to the vendor side: It’s not enough to delegate access control from developers to the rest of the organization. Doing so merely moves the bottleneck up the chain. To appropriately delegate the workload, you must be able to assign at least some access controls to the end customers themselves, providing them with true self-service.
● Thinking access control is limited to direct human use: Your first users are likely to be human users, but with increasing automation, more and more of your “users” will be automated agents—other applications and AI agents acting on behalf of humans. You will need to cater to them, too, and it might be sooner than you think.
● Delaying providing interfaces to non-technical people: A powerful interface that’s intuitive to non-technical users is crucial for access control systems.
Best Practices
● Create a cascading waterfall of trust and permissions: By creating a cascading system of permissions and trust, you can ensure that the right permissions are granted to the right users at the right time. Often, developers and security would be the main source of this waterfall, but it mustn’t end with them. Design your flow to gradually delegate more and more between the different levels with each level empowering the ones below it.
● Assign an owner: To avoid conflicts, such as two admins being able to remove each other, always have a primary admin, or “owner,” who takes precedence to avoid conflict. Owners often cannot be removed without transferring the title first.
● Identify bottlenecks early on: Identify potential bottlenecks in permission delegation (permissions that are hard to delegate, or manage) and have a plan and interfaces to mitigate in advance before friction piles up.
● Use a classic policy model (e.g. RBAC, ABAC) for your meta-policy: Just like with your regular permissions, there’s no need to reinvent the wheel. Start with common policy models first.
● Use the same policy model for your meta-policy: This can help to ensure consistency and ease of understanding across the system, lowering the cognitive load on system managers and users.
● Have meta audit logs: The information on who changed the meta-permissions is just as critical, if not more so, than who changed the permissions. Log it and track it.
● Build on top of existing AuthZ for AuthZ: Use tools that have authorization for authorization already baked into them (such as Permit.io), saving the effort of starting this from scratch.
In conclusion, solving the problem of meta-permissions requires a multifaceted approach that considers both the technical and cultural challenges associated with modern software systems. By following the best practices outlined above and by carefully thinking through the design of the interfaces and trust flows that govern the system, it is possible to create a system that is secure, usable and ready to accelerate to the velocity required by modern cloud-empowered business today.