Image by Kerfin7 on Freepik

Authorization in the modern age — Part 01 of 02

Viduranga Gunarathne
Published in
10 min readSep 17, 2024

--

What is Authorization?

Authorization is a mechanism for controlling what someone can do in an application. This allows to have control over the accessibility of data and make sure the users have access to their own data and no other party can access it.

Three main aspects of authorization;

  • Who is making the request?
  • What action are they trying to accomplish?
  • To which resource are they doing the action?

Authentication and Authorization

Authentication is the process of verifying who the actual user is before letting them interact with a system.

It’s like a locked door to a house which only allows users to pass through after verifying their credentials, which would be a key.

These can be a combination of the username and the password, where knowing both of them would complete the verification. Currently there are additional layers of authentication such as MFA for added security.

Forms of authentication include OpenID Connect and SAML (Security Assertion Markup Language). Using either OpenID or SAML, enterprises can handle user authentication and single-sign-on.

OAuth 2.0 is a framework that handles authorization to a protected resource. OpenID and SAML are considered as industry standards for federated authentication. While OAuth is being used in different situations when compared to the other two protocols, it can be used in combination with either OpenID or SAML.

  • OpenID Connect is built on the OAuth 2.0 protocol and uses an additional JSON Web Token (JWT), called an ID token, to standardize areas that OAuth 2.0 leaves up to choice, such as scopes and endpoint discovery. It is specifically focused on user authentication and is widely used to enable user logins on consumer websites and mobile apps.
  • SAML is independent of OAuth, relying on an exchange of messages to authenticate in XML SAML format, as opposed to JWT. It is more commonly used to help enterprise users sign in to multiple applications using a single login.

OAuth vs OpenID vs SAML

  • OAuth: Provides secure delegated access to resources. Lets an application access a resource from a server on behalf of the user. For example, letting an application access the contacts in the phone.
  • OpenID: It is an open standard that organizations use to authenticate users. For example, using a social login option like Facebook to log into a website without having to share credentials with the third party.
  • SAML: It is an XML based standard for sharing authentication and authorization information between identity providers and service providers to verify the user’s identity and permissions and then grant or deny their access to services.

Authorization defines what a user can do in an authenticated system. According to the previous analogy, once you pass the locked door, authorization determines which rooms the user can access.

Fine-Grained Access Control

A mechanism that provides the capability to define granular restrictions on what users can do to the resources in a system. Fine-grained access control (authorization) is a mechanism to define rules which govern what actions a user can perform on a resource even at a granular level.

Cloud-Native Authorization

In the modern world, the requirements for authorization have changed due to the following reasons.

  • With the rise of the cloud and the proliferation of SaaS, authentication moved to the cloud. But authorization and access control didn’t. The reason for this is because every application in the cloud wants its own implementation of access control.
  • Next, is the increase in usage of micro-services which when compared to monolith applications, require authorization on each of the service levels rather than having a single authorization model for the one big application.
  • Move from perimeter-based security to zero-trust. With this the responsibility of security moved from the environment into the application.

The two ecosystems that are emerging around cloud-native authorization are;

  • Policy-as-Code
    Authorization policy is treated as code derived from the application code. Open Policy Agent (OPA) has become sort of a default standard for expressing policy as code in the cloud-native world. The policies implemented as code can be as complex as the business requirement demands. This model is used mostly for attribute based access control (ABAC).
  • Policy-as-Data
    Every authorization decision is based on defined rules and data such as user contexts and resource contexts. If the rules don’t change, the authorization policies can be defined by the subject, resource and the relationship between them. Google’s Zanzibar, used in G-Drive, G-Mail, Calendar etc. would be the best example for a framework based on policy-as-data. It uses a relationship graph to determine the connection between the subjects and objects. This model is known as relationship-based access control (ReBAC).

Access Control Models

01. Role Based Access Control (RBAC)

Role-Based Access Control allows a system to group permissions into a collection called a role and assign that to individual users or user groups. This way it determines what actions each of the users under specified roles are capable of performing. RBAC helps find answers to questions like “If John is a project manager, can John modify the User Management Project?”. RBAC expects the role-to-permission mapping information to be available.

allowed_roles := [“viewer”, “editor”, “admin”]
allowed {
# allow if the user role is one of the allowed roles
input.user.properties.roles[_] = allowed_roles[_]
}

In a normal RBAC policy, we can check if a particular user has the allowed set of roles in order to perform an action.

The issue with RBAC is the scalability once the authorization use case expands. The approach to take would be to create more and more new roles that meet the permissions requirements which results in “role explosion”.

Multi-tenant RBAC

In a multi-tenant scenario, we must ensure that the roles are bound to a single tenant or a selected group of tenants. If we take Github for example, a user should only have administrative access to the repositories of their organization. Hence we need a hierarchical access control model which provides more granularity than generic RBAC. In multi-tenant RBAC, a “system administrator” will have access to the entire system while an “administrator” might only have complete operational control over a specific tenant.

Here we check if a particular user has a role on a specific resource, hence we need a mechanism to capture the relationship between a user, roles and specific resources.

allowed {
ds.check_relation({
“object”: {
“key”: input.resource.tenant,
“type”: “tenant”
},
“relation”: {
“object_type”: “tenant”,
“name” : “member”
},
“subject”: {“id”: input.user.id }
})
}

Above is an example Rego policy in OPA written to ensure that tenant resources are only available to members of that tenant. RBAC policies are quick and easy to set up, but lack the flexibility required for fine-grained
access control.

Pros and Cons of RBAC

Pros:

  • Simplified implementation
  • It is easy to reason, modify and audit a policy
  • Suitable for small simple applications

Cons:

  • Uses coarse-grained roles
  • Static roles add to complexity in administration
  • Role explosion

RBAC is a good model if you have a small set of permissions and if you have a static mapping between users, roles and the resources. However, if more finer-grained permissions are required, such as the capability to manage permissions in a hierarchy, the limitations start to
show up. The potential solutions to those issues would be attribute-based access control and relationship-based access control.

02. Attribute-Based Access Control (ABAC)

As the name suggests, ABAC is using attributes of resources, users, or even environmental attributes (network, location, device etc.) to manage access control. Catering to different compliance requirements in different regions such as GDPR are some use cases that can be handled with ABAC. Access to a resource is granted based on the attributes which are dynamic in nature.

  • User attributes : Username, Role, Team, Age, Project etc.
  • Resource attributes : Owner, Created date/time, Name, Folder etc.
  • Environmental attributes : Network information, Location, Time of access etc.

An example of an ABAC scenario would be restricting the users of an organization from accessing a particular project based on their seniority in the organization and if they connect via a VPN during office hours.

The ease with ABAC compared to RBAC is you can handle a case like an employee changing a department, by just updating attributes of that user rather than updating a bunch of roles.

workdays := [“Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”]
allowed {
ns := time.now_ns()
day := time.weekday(ns)
day == workdays[_]
input.user.department == “Support”
input.user.project == “ACME org”
}

In this ABAC policy, when an access request comes in, we check if the current day belongs to the set of predefined working days and then verify if the user’s department and the project are “Support” and “ACME org” respectively. If these conditions are met, the user is allowed to access the resource.

Pros and Cons of ABAC

Pros:

  • Easy to scale.
  • Good solution to handle permission decisions based on user, resources or environmental criteria.

Cons:

  • Complex to administer and requires more expertise.
  • Setting up takes a long time and more engineering effort.

Compared to RBAC, handling with attributes brings a more dynamic nature to ABAC. The convenience comes with a tradeoff of complexity. You need to handle the policies to cover all the potential values of the attributes. In addition, there is a learning curve to the policy language.

Due to these factors, implementing ABAC takes a considerable amount of time and also maintaining an ABAC model takes expertise.

ABAC can help answer questions like “Can John deploy service Foo to production?”

However, it is not so straightforward to answer a question like “Who has permission to deploy service Foo to production?”, since it is a bit of an open-ended question. This is where a relationship-based access control model comes into play, since it builds relationships between
subjects and objects. We can pick a subject and identify what objects have relationships with it and vice versa.

03. Relationship-Based Access Control (ReBAC)

The ReBAC model builds relationships between subjects (User John) and objects (User Management Project) and it generalizes the relationships between subjects and objects into a graph so that it can be traversed to find available relationships in order to take authorization decisions. Ownership of resources, parent-child relationships, groups and hierarchies can be
modeled as relationships in ReBAC.

Social media such as LinkedIn and Facebook are good examples of this hierarchy where you can allow your friends or first degree contacts to have access to your private information while the rest only have access to the public information.

Google Zanzibar which is an authorization system used all over the Google Cloud Suite (G-Mail, YouTube, G-Drive, Calendar) uses the concept of ReBAC where it creates a relationship graph between the objects and the subjects.

Most applications tend to have a hierarchy, specifically in B2B apps where there could be tenants or organizations and then an internal hierarchy such as projects, applications etc. The ReBAC model gives you the capability to define access control rules at each level helping to conform with the “principle of least privilege”.

Consider a highly simplistic version of Google Drive where you share documents and folders with others. Here the documents and folders would have a hierarchical structure where a folder can contain several documents and users can give other users “view” or “edit” permissions to folders or the documents. In this scenario, we need to verify a user’s permission at two levels.

  • One is to check if the user has a direct permission attached and
  • Second is to check if the user has inherited permissions through a hierarchy (parent folder).
allowed {
ds.check_permission({
“subject”: {“id”: input.user.id},
“permission”: “can-edit”,
“object”: {“key”: input.resource.file_id, “type”: “file”},
})
}
allowed {
file = ds.object({“key”: input.resource.file_id, “type”: “file”})
ds.check_relation({
“subject”: {“id”: input.user.id},
“relation”: {“name”: “manager_of”, “type”: “user”},
“object”: {“id”: file.properties.owner_id},
})
}
  • The first rule grants access to a user with the “can-edit” permission.
  • The second rule grants access if the requesting user is the manager of the owner of a resource.

Pros and Cons of ReBAC

Pros:

  • Dynamic model allowing access control to be defined at the resource level.
  • Can define hierarchical relationships.

Cons:

  • Introduces an additional overhead as the app scales, since every resource needs a representation in the application as well as the authorization database.

04. Mandatory Access Control (MAC)

Mandatory access control is the most stringent security configuration an organization can implement, where all access decisions are centrally managed by an authorized individual who grants or denies permissions. This model is typically employed by organizations with elevated security requirements, such as government agencies and financial institutions, where strict control and traceability over access to sensitive areas and data are essential.

05. Rule-based Access Control

Rule-based access control regulates access to locations, databases, and devices based on a set of predefined rules and permissions, independent of an individual’s role within the organization. In other words, if a user does not meet the specified access criteria, they will be denied access to the control network, regardless of their security clearance level.

Where to apply authorization?

  1. At the network layer.
    This layer has very limited data and only allows for simple network access control measures like allow/deny lists. We shouldn’t focus on authorization here.
  2. At the Proxy or Router.
    This is best for route-level authorization, as more granular access control generally requires an additional call to a service or database to make an authorization decision.
  3. In the Application/Controller.
    Here, all information is available to us, so we can easily apply our authorization requirements. This is a good place to put our authorization logic.
  4. In the Database.
    If the application generates database filters, we can apply our authorization here. This lets us ask more broad questions about access, so when possible, it’s best to enforce authorization here.

Herewith I conclude my first article of this two part series and please look forward to the following topics in Part 02.

  • Authorization as a service
  • Common authorization frameworks

--

--

Viduranga Gunarathne
vlgunarathne

Computer Science Graduate | Software Engineer @WSO2 | Tech enthusiast | Cinephile