The topic of authorization has seen a recent resurgence in interest from developers and security folks alike. The OWASP Foundation, a trusted voice on web application security, just updated its Top 10 Web Application Security Risks and for the first time rated 'Broken Access Control' as the top vulnerability facing developers. Also this year, Airbnb, Carta, and Intuit each separately published deep-dives detailing their newly built internal authorization services.
Authorization is by no means a new security concept. So why this renewed attention to it? In this post, we’ll look at authorization as it stands today, what's changed in the landscape, and go over some best practices developers should follow.
As previously mentioned, authorization is not a new concept. NIST defines it as “the process of verifying that a requested action or service is approved for a specific entity.” One addition we'd make to this definition is that good authorization also ensures proper gating and access controls on data.
Still, this is a very broad definition of authorization. There are no standards defining exactly how access checks should be implemented or what should be used to check permissions. But if you've read up on authorization, you've probably come across a couple of specific ‘types’ of authorization: ‘coarse-grained’ and ‘fine-grained’ authorization. Again, there isn’t an official definition or standards governing these two types but it’s generally accepted that coarse-grained authorization is more straightforward and simplistic (ex. Any user can access any report if they are an ‘admin’) while fine-grained authorization takes in many more inputs to determine access (ex. User [A] can edit report [X] if they have the [edit report X] permission).
Even though both are often described as two exclusive types, in practice it's more helpful to think of authorization as a spectrum with coarse-grained and fine-grained authorization serving as the two ends. Depending on the product and use-case, a system can be closer to coarse-grained, closer to fine-grained or even somewhere in between. It's also likely for systems to shift along this spectrum over time as usage and functionality change.
Going back to our original question, if authorization is nothing new, why is there a renewed interest in it as a security concern? For one, the market for B2B software (particularly SaaS) has exploded over the past decade. Enterprises large and small are more comfortable than ever before in adopting new software products for their internal and customer-facing needs. It used to be that implementing proper authorization, especially fine-grained authorization, was a topic of concern for internal software development teams at Fortune 500s or enterprise software companies selling multi-million dollar contracts to large companies. These days, even smaller startups are competing for large enterprise deals where fine-grained authorization is considered table stakes. I'd argue that this market shift is being driven by a few key product themes. In no particular order, here are a few that stick out to me the most in B2B software.
Modern B2B and enterprise software applications are collecting and processing more data than ever before. Whether it’s user-generated (documents, notes, messages, comments) or machine-generated (ML training data, logs, analytics data), modern apps are data-hungry. And the more data applications collect, the better the authorization schemes need to be in order to safeguard against costly data leaks and exploits.
After working for years with tools like Google Docs and Dropbox, enterprise users expect to be able to share and collaborate on their content in whatever application they’re using. This expectation has pushed B2B apps to offer collaboration out of the box as a first-class feature. Implementing collaboration functionality is non-trivial and requires fine-grained authorization to ensure users can share and restrict access to specific content in real time.
The rise of API-driven platforms and more recently ‘no/low-code’ tools has led to a plethora of integration opportunities between applications. But again, exposing programmatic data exports and uploads requires robust authorization in order to safeguard against unintended data leakage or access.
Whether you're a solo developer building an indie SaaS product or a developer at a big software company, hopefully this overview shows you the importance of implementing proper authorization in your system. While we won't get into specifics, there are some best practices (some borrowed from OWASP) you should consider:
- As fine-grained as possible. Going back to the authorization spectrum, you want your authorization checks to be as specific as possible. Ideally, this means your system has the ability to check access based on specific records and resources (ex. User [A] can edit report [B]) instead of generic behaviors (ex. Any admin user can edit any report).
- Deny by default. Application behavior and data should not be accessible by default. This makes it easier to enforce that only the right users have access to the right data and actions.
- Implement once and reuse. Authz logic will get more complex the longer your application exists. Don’t spread out multiple implementations across the codebase because it will lead to missed cases and potential holes in your system.
- Maintain an audit log. Keep an authorization log in your system (all allow/deny responses) so you can track access checks and conduct audits where necessary.
These are just some high-level starting points but should at least help you think of and protect against common authorization and access control related exploits.