- Best Practices
Using OAuth2 Scopes for Authorization? You might regret it
Using OAuth2 scopes for authorization might seem tempting. The thing is, OAuth2 scopes were never meant for this, and you might regret it later. Here's why -
When building a new application, using OAuth2 scopes to meet your authorization needs might seem tempting. The thing is, OAuth2 scopes were never really meant for this purpose - and using them may cause you more harm than good as your application evolves. It’s important to keep in mind the differences between OAuth2 scopes and application-level permissions and adopt the right authorization mechanism. This will help ensure you have the necessary level of granularity and control over protected resources.
What’s the deal with OAuth2?
OAuth2 is a widely used protocol for authorization and authentication of web applications. One of its primary features is the use of scopes, which are used to define the level of access that a client application has to a protected resource. It allows users to grant third-party applications access to their resources without exposing their credentials. OAuth2 provides several mechanisms to help developers define scopes, which represent a set of permissions that a client application can request access to.
OAuth2 scopes were never, however, intended to be used as an in-app authorization mechanism. Yet some developers often fall into the trap of using scopes in every authorization scenario.
The root of the problem
Developers often begin building their applications by implementing an authentication layer. This can be easily achieved by implementing any of the dozens of AuthN SaaS solutions out there.
The second step is often implementing a simple differentiation between two types of users - “Admin” and “Not-Admin”. Creating an OAuth2 scope to represent the “admin” permission is very simple. When an Admin user logs in, the authentication layer adds the admin scope into the JSON Web Token (JWT), and every call to a protected resource checks the JWT for this “admin” scope.
Why is this an issue?
In short, OAuth2 scopes are not a substitute for application-level permissions - Scopes define the level of access that a client has to a protected resource, but they do not provide the granularity necessary to define what the client can do with that resource. Here, the crucial difference between OAuth2 scopes and application-level permissions comes in.
“I’ll just add more scopes”!
As your application develops, simple concepts such as “Admin” and “Not-Admin” become insufficient, as they quickly lead to over-permissioning, which can result in data breaches or unauthorized access to resources. Spoiler alert: Adding a “Super Admin” into the mix is like putting a bandaid on a broken leg.
The amount of different roles, resources, and actions is likely to grow exponentially along with your application. JTWs have a size limit. If we need to give a user access to 1000 files, the JWT length changes from 239 characters to 20,057 (and that’s considering a simple file name). With the full path, it’s even longer.
OAuth2 Scopes are Static
OAuth2 does not account for changes in access requirements over time. Once a client application is granted a scope, it retains that scope until it is revoked. This can become a problem when access requirements change and the same scope is no longer sufficient. For example, if an application adds a new feature that requires more granular access control, it may be challenging to implement this change without breaking backward compatibility. In such cases, developers may need to create new scopes, which can be confusing for users and may lead to scope proliferation.
OAuth2 Scopes Don’t Consider Context
Different resources in an application may require different levels of access depending on the context. For instance, a user may have read-only access to some resources but require write access to others. Scopes do not account for such context-specific access requirements, which can lead to over-privileging or under-privileging users.
OAuth2 Scopes Don’t Support Complex Policies
Access control policies often involve complex logic, such as role-based access control (RBAC) or attribute-based access control (ABAC). OAuth2 scopes are not designed to support such complex policies, which can lead to significant security vulnerabilities.
The solution? Implement Dynamic Authorization
In conclusion, OAuth2 scopes are a limited authorization mechanism that can pose security risks when used as the sole basis for making authorization decisions. Developers should consider more robust authorization mechanisms, such as RBAC or ABAC, to provide fine-grained control over access to resources and allow them to define complex access control policies. By adopting these mechanisms, developers can ensure that their applications are more secure and better suited to meet their users' evolving access control requirements.
Scalable Permission Management
Authorization requirements tend to grow exponentially along with the application. As various requirements from customers, security, compliance, and 3rd party integrations come in, you might end up refactoring your entire authorization system every 3-6 months.
Setting up (Not to mention maintaining) a system as complex as ABAC could take months of complex R&D work and steep learning curves.
For that exact purpose, Permit provides developers with a permission management solution that allows for easy implementation and can be managed using an accessible no-code UI.
Permit’s UI generates Rego code for both RBAC and ABAC (See links for code examples), wrapping it nicely into Git, and API / UI interfaces which you can edit, add to, and manage however you like.
This allows both developers and other stakeholders to set up RBAC policies and add complex attributes and conditions - all without having to write a single line of code.
Want to learn more about Authorization? Join our Slack community, where there are hundreds of devs building and implementing authorization.