How To Build Centralized Authorization System

Ege Aytin - Jul 24 - - Dev Community

In a centralized authorization, control decisions are managed from one single location and serve the entire application.

Thus, instead of each microservice handling permissions separately, they are designed to check with a central authority to see if someone is allowed to access certain resources or perform specific actions.

What you'll learn:

The primary aim of this piece is to illustrate how you can implement a centralized authorization system while presenting a thorough overview of the subject.

Therefore, in the course of this article, we will cover the following and more;

  1. What a centralized control system entails; how it works, real-world organizations using it, the benefits and tradeoffs of having a central access system in your application and the workflow from an architectural level.

  2. Centralized vs Distributed Authorization Systems and how to effectively decide the most optimal solution with practical use cases

  3. A step by step guide to get started implementing your centralized system using Permify

If you are looking to understand the nooks and cranies of access management systems, then this is for you.

By the end of this piece, you would have gained a full understanding of this topic which will aid you in developing resilient and scalable microservices.

Let's get started!

The Decoupling Authorization Concept

Similar to the idea and essence of separation of concerns when writing code, the decoupling authorization concept falls along that path.

This concept means that our authorization logic is not mingled with the core application code rather it is moved into its own dedicated service or component.

By doing authorization this way, you make the application easier to manage such that updates does not break up the rest of your app.

What is a Centralized Authorization System?

A centralized authorization system establishes a single source of truth for managing all access permissions. This means that all services must be connected to it and communicate as often as needed before they can grant or deny access.

For instance, assume you have a web application that involves different levels of users such as regular users and moderators. A centralized access management makes it possible for you to manage and audit these permissions from one point.

Real world examples where centralized systems are used include companies that provide software infrastructure as a service (IaaS).

They loan their servers to the general public so to say. In order to control and allocate the resources efficiently, a central authorization is used to handle things like user management, protecting customer resources and providing other extra services. We can only imagine what the absence of such a centralized system could lead to– ‘cloud chaos’.

Another case study we’ll consider are software systems that are built to serve the needs of large firms, called enterprise applications. These enterprise systems typically handle big volumes of data across the different departments in an organization. It also needs to accommodate growing needs. Hence, a centralized authorization system is a good fit.

Thus far, we have talked about what a centralized authorization system entails and the problem it solves with real world examples of how organizations use it.

Next, we’ll highlight some of the benefits.

What is Distributed Authorization?

Decentralized or distributed access management involves a structure where control is handled by a number of servers spread across nodes.

decentralized

In contrast with a centralized pattern, these respective servers are made to cooperate for the purpose of load balancing and are also able to work independently of each other. So they do not need to check with a chief authority before granting permissions.

Strengths and Weaknesses

According to the CAP theorem, a distributed system can only deliver at most two of these: Consistency, Availability and Partition tolerance.

So, this calls for careful consideration of what your application can let go of without any negative consequences to business operations.

With these in mind, let's now weigh the strengths and weaknesses of a centralized and decentralized access management. We'll consider two use cases.

Use case 1: A banking application

For this use case, we may describe the main business requirement as thus:

  1. Availability, reliability: Providing reliable information on financial transactions is necessary to maintain trust and satisfaction.
  2. Security: Safeguarding user accounts and transactions by ensuring the highest level of security possible.
  3. Scalability: As the customer base grows, the application is expected to adapt to this change.

Next, let's see how both authorization systems might compare in meeting these needs in relation to CAP mentioned earlier.

Centralized Authorization Systems

Strengths:
A centralized access management will easily provide consistent and reliable data among the different interfaces that a customer interacts with their banking application because there is only one single source truth.

The central server is often able to achieve high availability of service if it is well designed in a way that authorization requests and responses flow smoothly.

It’s also feasible to implement comprehensive security measures and policies to protect financial transactions and data.

Weaknesses:

When there's a break in transmission, being a single point of failure, the central server is affected leading to a disruption.

A centralized system may struggle or require extra effort to scale as the user base grows.

Decentralized Authorization Systems

Strengths:

Decentralized systems are designed to thrive even when there is a partition because the nodes function independently of one another.

A decentralized system will have higher availability because of the ability to balance the load effectively.

Weaknesses:

Achieving consistency and high security standards across each and every node can be challenging in a decentralized system

Use case 2: A real-time messaging application

For this use case, we can identify our important business needs as:

  1. High availability: Users expect to send and receive messages at any time even during peak periods without downtimes.
  2. Security: They expect their information to be safe and secure even in transmission
  3. Reliability: Users typically expect no delay or lagging.

Centralized Authorization Systems

Strengths:

It’s easy to achieve consistency with a centralized server managing all data and operations

For a small application with sizable requirements, a centralized system will be easier to design, implement and manage.

Weaknesses:

Users that are located far from the central server will experience high latency due to longer network distances which results in slow response times.

There is a single point of failure, which means that when the central server is down, the entire application will be inaccessible.

A centralized system will require more effort to scale as the user base grows.

Decentralized Authorization Systems

Strengths:

There is more room to scale if the user base increases because the workload is shared across different nodes.

With decentralized architecture, data points can be brought closer to the users who are at far locations which can reduce latency and improve user experience and satisfaction rates.

No single point of failure, when one node is down, others pick things up from there and the impact should not be felt.

Weaknesses:

Security is a major concern. Extra effort and financial resources have to be spent to beef up security otherwise it can render the whole application ineffective.

A decentralized architecture is complex and requires solid sync and coordination,
achieving consistency therefore requires constant effort since data needs to be updated frequently in this use case.

How Centralized Authorization Systems Work?

For this section, let’s talk about the nitty gritty of how a centralized system works.

To kick things off, you need to put in your main player in a centralized system, which is the central authorization server. Other microservices will connect to and receive responses from this single server.

To implement this, we need to follow these key steps before anything;

Step I. Identify requirements: Begin by listing the major requirements of your application, the data it will manage and what kind of interactions it will facilitate in day to day processes.

Step II. Design architecture: Based on the needs of the application, map out the architectural plan of your application showing the major components, their interactions, and the flow of data and control.

Step III. Implement Authorization: Decide whether to outsource your authorization service or build from scratch. Follow along as we’ll discuss some incredible benefits of outsourcing in the next few sections.

Step IV. Build microservices: Implement the other core services and business logic of your application.

Step V. Deploy, test and maintain

Great, let’s now take a look at an demo workflow of a centralized architecture.

centralized-architecture

In the illustration above, our use case is a banking application system.

Here, the client or end-users have their needs met via different provisions such as the web services (online banking portal), mobile app and self service channels.

So within a centralized system, all of these outlets will be connected to a single server behind the scenes.

As shown in the drawing model, we have a Policy Decision Point (PDP) that is responsible for receiving incoming requests and making authorization decisions based on predefined policies and rules.

Now, the PDP works closely with another component known as the Policy Enforcement Point (PEP) which serves as a gateway where endpoint requests hit first, it enforces the decisions sent from the PDP by protecting the app endpoints or resources.

Finally, by application interpolation, developers can make sure that these security and authorization rules are integrated into the core of the application to fulfil the very essence of having it. This means that, for instance, when a user hits a URL /show-document your microservice 'pauses' and places a call over to the policy checkpoint behind the scenes.

As the number of access requests grows however, centralized authorization systems may encounter scalability challenges which could lead to performance issues especially if the authorization service becomes overwhelmed with requests.

The next section will shed more light on these trade-offs for specific use cases which can act like a guide in deciding when centralized management is a fit.

Centralized vs. Distributed Authorization

In this section, we'll talk about a distributed system and discuss more on how it differs from a centralized authorization system.

Weighing these would help you decide which approach suits your application needs making you better prepared to navigate any trade-offs.

Implementing Centralized Authorization Systems with Permify

Permify is an open source service that provides all your authorization needs in one place, a popular choice loved by developers for many reasons.

Thus, delegating your authorization using a service such as Permify ensures that you can get your microservices up and running in good time while having less to worry about.

So, in this section, we will implement a starter centralized access system which you can extend and customize per your application need.

To get started, ensure Docker is running and connect to Permify:

Step I. Connect

In your terminal, type the following command:

docker run -p 3476:3476 -p 3478:3478 ghcr.io/permify/permify serve

You should get a screen showing that Permify service is running.

connect2Perm

Step II. Define Authorization Schema

Now, let's model authorization for our second use case mentioned earlier, a real time application where a user can create groups and send messages.

Entites in Permify schema are just like how tables work in a relational database context. It's recommended that you name them similar to your database tables.

We will be using the Permify playground to model our schema.
The complete schema file can be found here

Let's dig in!

entity user {}

entity roles {}

entity message {}

entity chatroom {}
Enter fullscreen mode Exit fullscreen mode

Here, we create 4 entities; user, roles, message, chatroom.

entity roles {
 relation admin @user
}
Enter fullscreen mode Exit fullscreen mode

For the roles entity which would contain privileges, we add a new role to define an admin user.

entity message {
    relation owner @user
    permission create  = owner
}
Enter fullscreen mode Exit fullscreen mode

Next is the message entity. It defines the owner as user and the permission to create a message.

entity chatroom {

    relation parent @roles
    // represents owner of this repository
    relation owner  @user

    // permissions
    permission delete = parent.admin or owner 
}
Enter fullscreen mode Exit fullscreen mode

The chatroom entity links the roles entity as its parent, stating that the user is the owner of the chatroom. Owner and any other admin can delete chatroom.

That's it for our schema.

The Permify playground contains a helpful visualizer tool that shows the schema relationships.

Step III. Connect your schema with Permify authorization service

We have an authorization schema ready. The next thing we'll do is notify Permify server of this schema.

Open up your API design platform and do a POST query to the Write Schema endpoint, supplying the schema we have just created;

localhost:3476/v1/tenants/t1/schemas/write

Make sure to click "Copy" on the Permify Playground to get the string version of your schema.

write2schema_n

Great. The above screenshot shows that we have successfully queried the Permify API and received a schema ID back.

Step IV. Store Authorization Data

Permify gives you the ability to store your authorization data in any database of choice and work with it using the Permify DataService.

To do this, we'll send some JSON data to the Write Data API endpoint to add new record which we will then use to perfom access checks.

localhost:3476/v1/tenants/t1/data/write

{
    "metadata": {
        "schema_version": ""
    },
    "tuples": [
        {
            "entity": {
                "type": "chatroom",
                "id": "2"
            },
            "relation": "owner",
            "subject":{
                "type": "user",
                "id": "1",
                "relation": ""
            }
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

step-iv

Here, we are assigning a chatroom with id 1 to belong to user with id 4. In other words, the relationship between the user and chatroom is "owner", as defined in our schema.

From our Postman API* screen above, you will notice that Permify returns us a snap token. This feature makes it possible for you to get an up to date results at all times even if your schema later changes.

Step V. Perform authorization checks in your self hosted microservices and receive responses

Now that we have authorization data in place, we are ready to perform checks to and fro.

In essence, your application can now send a request to the authorization service on Permify to verify if a user can be given access to perform the specified action.

Let’s implement this in our demo; We want to verify that a user can delete a chatroom they own.

Make a POST request to the CheckAPI service, include the following JSON in the body section of your request:

localhost:3476/v1/tenants/t1/permissions/check

{
  "metadata": {
    "schema_version": "",
    "snap_token": "",
    "depth": 20
  },
  "entity": {
    "type": "chatroom",
    "id": "2"
  },
  "permission": "delete",
  "subject": {
    "type": "user",
    "id": "1",
    "relation": "owner"
  },
  "context": {
    "tuples": [
      {
        "entity": {
          "type": "chatroom",
          "id": "2"
        },
        "relation": "owner",
        "subject": {
          "type": "user",
          "id": "1",
          "relation": "owner"
        }
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

check_allowed
The screen above shows a successful check. With this your microservice receives the response CHECK_RESULT_ALLOWED and user can therefore proceed with the required action.

This completes the authorization cycle from our authorization service.

Summary and Conclusion

In this article, we have discussed the types of authorization systems in microservices. Also, we have looked extensively on centralized authorization systems and how it works considering practical use cases.

To solidify our understanding, we have implemented a centralized system in our application using Permify authorization services.

Using the different Permify services, we have gone from constructing a schema to performing access checks in our application. This demonstrates the realism and benefits of outsourcing your authorization needs.

By leveraging the practical knowledge gained from this article, you can implement an efficient centralized authorization system, providing optimal security in your microservices.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player