<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Cerbos</title>
    <description>The latest articles on Forem by Cerbos (@cerbos).</description>
    <link>https://forem.com/cerbos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7005%2F1a1f2ae5-0b11-48cc-b982-3f9fdd62372e.png</url>
      <title>Forem: Cerbos</title>
      <link>https://forem.com/cerbos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cerbos"/>
    <language>en</language>
    <item>
      <title>Authorization needs to be dynamic, declarative, and decoupled</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Tue, 12 Nov 2024 10:00:00 +0000</pubDate>
      <link>https://forem.com/cerbos/authorization-needs-to-be-dynamic-declarative-and-decoupled-2omd</link>
      <guid>https://forem.com/cerbos/authorization-needs-to-be-dynamic-declarative-and-decoupled-2omd</guid>
      <description>&lt;p&gt;&lt;em&gt;Guest article written by Fatuma Abdullahi. Thanks! For more great community content and discussions, join our Slack today!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Authorization mechanisms have traditionally been closely tied to the main application logic, and while this works in traditional monolithic systems, maintaining this coupling becomes harder as application complexity grows.&lt;/p&gt;

&lt;p&gt;As authorization is a significant aspect of creating and maintaining secure systems, it is better to have it &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/decoupled-authorization" rel="noopener noreferrer"&gt;decoupled&lt;/a&gt; (or "externalized"); that is, to reduce the dependence between authorization and core application logic. Decoupling simultaneously increases the reliability of the authorization functionality whilst decreasing the complexity of the core system itself.&lt;/p&gt;

&lt;p&gt;It is also advantageous to have authorization logic expressed in declarative terms to describe the rules and expected outcomes. This allows the system to make decisions rather than explicitly stating how decisions should be made, making the authorization system accessible to less technical members of an organization. This leads to a dynamic authorization system, or one that makes real-time decisions as requests come in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjk6hfdxa1nfzr39a8is3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjk6hfdxa1nfzr39a8is3.png" alt="A flowchart that shows the process for user access to a resource. It starts with " width="800" height="1226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Decoupled, or externalized, authorization
&lt;/h2&gt;

&lt;p&gt;Using an authorization system that is external to your primary system offers some hard-to-beat advantages, including:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;External authorization providers are more secure because they are specialized, and are designed from the ground-up with domain-specific experience. They are more aware of the landscape and know what to look out for better than any team whose focus is pulled in many different directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simpler Policy Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;External authorization providers offer a standard way of writing policies and rules, making policy management predictable and allowing the team to move faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Straightforward Scaling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;External authorization systems have the concept of scale built in. They can be adapted at any size, and when the application grows or its authorization needs change, the external system grows with it seamlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of externalizing authorization
&lt;/h2&gt;

&lt;p&gt;Decoupling authorization shares advantages with using an external system because both rely on the separation of authorization and business logic as a central pillar. However, additional advantages appear when using an internally-decoupled system. These include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increased System Resilience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Separating authorization logic and rules from your main application increases your systems' resilience as the interdependence between them reduces. This allows your system to withstand outages without affecting all your functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplified Workflows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keeping authorization external to your primary system simplifies setting up authorization logic and rules. It keeps the teams' focus on how authorization should look independent of any core logic, reducing chances of blind spots and increasing clarity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easier Maintenance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using separate authorization systems makes maintaining the authorization engine more straightforward because of the decoupling that occurs. This makes it simpler to debug and increases the team's developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  RBAC and decoupled authorization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/rbac" rel="noopener noreferrer"&gt;Role-based access Control (RBAC)&lt;/a&gt; is an authorization technique that uses a user's role in a system to determine what resources they can access. It is a common way to enforce authorization across systems by assigning permissions to roles rather than to individual users and then assigning roles to users. When enforcing decoupled authorization, RBAC is implemented by centralizing all roles and their related permissions across the system.&lt;/p&gt;

&lt;p&gt;There are some trade-offs when using RBAC to manage authorization, including:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role Explosion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a system grows, the number of roles and permissions might rapidly multiply leading to too many role definitions overall. This makes it harder to manage and reason about the authorization policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Granular Permissions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, RBAC is used even in situations better served by more granular access controls. Scenarios requiring dynamic or context-specific permissions might be better served using other techniques like ABAC (Attribute-Based Access Control), which offer more control and flexibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reduced Flexibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Making changes to RBAC-based policies can be difficult in a growing system, and changes may cause system-wide repercussions. This can lead to a system being slower in adapting to changing authorization needs.&lt;/p&gt;

&lt;p&gt;It is important to consider these trade-offs when designing RBAC-based authorization policies and to consider whether other access control techniques might be a better fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization and microservices architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://solutions.cerbos.dev/monolith-to-microservices-migration-ebook" rel="noopener noreferrer"&gt;Microservice architecture&lt;/a&gt; refers to organizing application logic into services that typically carry out one thing and can be deployed independently while loosely coupled. For example, edge functions are microservices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzzkywpiqsbf32kv7cmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzzkywpiqsbf32kv7cmk.png" alt="A flowchart diagram showing a client communicating with an API Gateway, which routes requests to four services: Auth Service, User Service, Payment Service, and Notification Service. Each service connects to its respective database: Auth Database, User Database, Payment Database, and Notification Database." width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a system where the backend isn’t distributed in this way (i.e. monolithic architecture), managing authorization queries is reasonably straightforward, as all the data is available in a central location. The challenge with authorization in a microservice architecture is that the services are separated by definition, and often may not talk to each other, making consistent access control and synchronization hard.&lt;/p&gt;

&lt;p&gt;There are several ways to handle authorization in a microservices architecture, including implementing a gateway API (Application Programming Interface) service. Cerbos can be integrated into a microservices architecture as a mechanism deployed alongside microservices (e.g. a sidecar in Kubernetes), such that every service has consistent access to the authorization endpoint.&lt;/p&gt;

&lt;p&gt;This flexible approach ensures that policies stay consistent across the entire system, regardless of the many services involved. This further simplifies policy management while enhancing security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization best practices
&lt;/h2&gt;

&lt;p&gt;There are several principles to keep in mind to help make your authorization system robust and to follow best practices, including:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Principle of Least Privilege&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This principle emphasizes that users should only ever have the minimum access to perform the required role and no more. This reduces the risk of unauthorized access and the chances of a breach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Monitoring and Logging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Logging authorization requests is good practice. This makes it easier to monitor and detect any anti-patterns. Implementing this makes your authorization system more robust and secure, and it also simplifies compliance and audit procedures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separation of Concerns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keeping authorization logic and policies decoupled increases your system's resilience, as any issues in parts of the application will not bring down the entire system. Additionally, decoupling authorization increases flexibility, extensibility, and maintainability at a system level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more!
&lt;/h2&gt;

&lt;p&gt;You can learn more about decoupled / externalized authorization using the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/blog/authentication-vs-authorization" rel="noopener noreferrer"&gt;AuthN vs AuthZ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/blog/why-organizations-are-turning-to-decoupled-authorization-solutions" rel="noopener noreferrer"&gt;On decoupled authorization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>authorization</category>
      <category>authz</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Authentication and authorization in Node.js applications</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Tue, 08 Oct 2024 13:00:00 +0000</pubDate>
      <link>https://forem.com/cerbos/authentication-and-authorization-in-nodejs-applications-12fk</link>
      <guid>https://forem.com/cerbos/authentication-and-authorization-in-nodejs-applications-12fk</guid>
      <description>&lt;p&gt;&lt;em&gt;Thanks to our friendly Cerbos community member—who wishes to remain anonymous—for this tutorial. For more great community content and discussions, &lt;a href="https://go.cerbos.io/slack" rel="noopener noreferrer"&gt;join our Slack&lt;/a&gt; today!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will discuss authentication and authorization, and how to implement both JWT authentication and Cerbos authorization in a Node.js application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Understanding authentication
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.cerbos.dev/blog/authentication-vs-authorization" rel="noopener noreferrer"&gt;Authentication&lt;/a&gt; is the process of verifying the identity of a user. In a Node.js application, we typically authenticate a user based on a set of credentials, such as a username and password, to gain access to the application.&lt;/p&gt;

&lt;p&gt;Some common authentication methods are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username and password&lt;/li&gt;
&lt;li&gt;Token-based authentication&lt;/li&gt;
&lt;li&gt;Single Sign-On (SSO)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The authentication process works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user provides their credentials.&lt;/li&gt;
&lt;li&gt;The server verifies the provided credentials.&lt;/li&gt;
&lt;li&gt;If the credentials are valid, the server generates an authentication token or session ID for the user.&lt;/li&gt;
&lt;li&gt;The newly generated token/session ID is sent back to the client and stored for future use.&lt;/li&gt;
&lt;li&gt;To prove their authenticity, the user includes the token/session ID in each request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Understanding authorization
&lt;/h1&gt;

&lt;p&gt;Authorization is the process of giving access to users to do specific work/actions. It decides what an authenticated user is allowed to do within the application. After authentication, authorization makes sure that the user only does what they're allowed to do, following specific rules and permissions.&lt;/p&gt;

&lt;p&gt;Some common authentication models are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/rbac" rel="noopener noreferrer"&gt;Role-based access control (RBAC)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/abac" rel="noopener noreferrer"&gt;Attribute-based access control (ABAC)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/pbac" rel="noopener noreferrer"&gt;Policy-based access control (PBAC)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does authorization work?
&lt;/h2&gt;

&lt;p&gt;The authorization process works like this: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The authenticated user makes a request to the server.&lt;/li&gt;
&lt;li&gt;The server verifies the user and gets their assigned roles and permissions.&lt;/li&gt;
&lt;li&gt;The server evaluates if the user has permission for the requested actions.&lt;/li&gt;
&lt;li&gt;If the user is authorized, the server allows the user to perform the requested actions.&lt;/li&gt;
&lt;li&gt;Otherwise, it denies access and returns an appropriate error response.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is RBAC?
&lt;/h2&gt;

&lt;p&gt;Role Based Access Control, or RBAC, is an access control method that gives permissions to the user based on their assigned roles within our applications. In simple words, it controls what users can do within the application.&lt;/p&gt;

&lt;p&gt;Instead of assigning permissions to individual users, RBAC groups users into roles, and then assigns permissions to those roles. This makes it easier to manage access control, as we only need to update permissions for a role, rather than for each individual user. &lt;/p&gt;

&lt;p&gt;Key components of RBAC are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role: Defines a set of responsibilities, tasks, or functions within the application.&lt;/li&gt;
&lt;li&gt;Permissions: Represents specific actions that users can perform.&lt;/li&gt;
&lt;li&gt;Role Assignments: Users are assigned to one or more roles, and each role is associated with a set of permissions.&lt;/li&gt;
&lt;li&gt;Access control policies: Dictate which roles can access particular resources and what actions they can take.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foeijuj5c5d5ub200d9bw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foeijuj5c5d5ub200d9bw.png" alt="{User} -- is assigned to --&amp;gt; {Role} -- has --&amp;gt; {Permission} -- grants access to --&amp;gt; {Resource}" width="632" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RBAC is powerful, but implementing and managing it yourself is not easy. The open-source Cerbos PDP (or Policy Decision Point), acts as a &lt;a href="https://www.cerbos.dev/blog/authorization-as-a-service" rel="noopener noreferrer"&gt;stand-alone service&lt;/a&gt;, streamlining access control by centralizing both policy decisions and audit log collection, and decoupling authorization logic from your application. &lt;/p&gt;

&lt;p&gt;Cerbos can function effectively within diverse software environments, from monoliths to fully decentralized architectures. It’s stateless and can be deployed via a Kubernetes sidecar, in a Docker container, or even as a single binary on a virtual machine. Cerbos exposes a rich HTTP API, which makes it language-agnostic, and allows it to interact and scale seamlessly with other services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementing authentication and authorization in Node.js
&lt;/h1&gt;

&lt;p&gt;Now that we have an understanding of authentication and authorization, let’s explore how to implement them in our Node.js application. In this section, we’ll build a simple Node.js app and integrate authentication and authorization functionalities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting the project, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm installed on your system.&lt;/li&gt;
&lt;li&gt;Docker installed on your machine (for running the Cerbos container).&lt;/li&gt;
&lt;li&gt;Postman or a similar tool for testing API endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;

  &lt;a href="https://cta-service-cms2.hubspot.com/web-interactives/public/v1/track/redirect?encryptedPayload=AVxigLJA2octU4MHpvkByVY8c8GGX54s4sv%2FREy0FQ%2BENY%2BVh7GayBJpPBkDBHlFn%2BKRuPaVeZltIDeDoMZ69iqehJYl0A4MPFRzo00stUk2S%2Bttd%2FH6pEZn4tU%2FfISJxM5G0vTcoT514DqmX7ZIbcifP4z4zly5UN2NRmyOeKg%3D&amp;amp;webInteractiveContentId=168994186087&amp;amp;portalId=20289770" rel="noopener noreferrer"&gt;
    &lt;img alt="BlogCTA - PDP" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fno-cache.hubspot.com%2Fcta%2Fdefault%2F20289770%2Finteractive-168994186087.png" width="538" height="277"&gt;
  &lt;/a&gt;

&lt;/center&gt;

&lt;h2&gt;
  
  
  Set up a Node.js project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create the project
&lt;/h3&gt;

&lt;p&gt;To start with, we need to set up a Node.js project. Run the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize a new Node.js project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the dependencies
&lt;/h3&gt;

&lt;p&gt;Next, install the required dependencies for our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express jsonwebtoken dotenv bcryptjs nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the following packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;express&lt;/code&gt;: A popular web framework for Node.js.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jsonwebtoken&lt;/code&gt;: For generating and verifying JSON Web Tokens (JWT) for authentication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dotenv&lt;/code&gt;: loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bcryptjs&lt;/code&gt;: to hash the password.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nodemon&lt;/code&gt;: nodemon helps Node.js-based application restarts automatically when there is a change in the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Environment variables
&lt;/h3&gt;

&lt;p&gt;Next, create a &lt;code&gt;.env&lt;/code&gt; file to securely store our sensitive information, such as API credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Your_Secret_Key_Here"&lt;/span&gt;
&lt;span class="py"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the Express server
&lt;/h3&gt;

&lt;p&gt;Now, we'll create an &lt;code&gt;index.js&lt;/code&gt; file in the base directory and set up a simple Express server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//middleware provided by Express to parse incoming JSON requests.&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top of the project, we're loading environment variables using &lt;code&gt;dotenv.config()&lt;/code&gt; to make them accessible throughout the file. This way, we can use the &lt;code&gt;dotenv&lt;/code&gt; package to access the &lt;code&gt;PORT&lt;/code&gt; number from the &lt;code&gt;.env&lt;/code&gt; file, instead of hardcoding it directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the project
&lt;/h3&gt;

&lt;p&gt;In this step, we'll add a start script to the package.json file to easily run our project.&lt;/p&gt;

&lt;p&gt;By default we'd have to restart our server each time we make changes to a file. To avoid this, we can use &lt;code&gt;nodemon&lt;/code&gt;, which will scan for changes and restart automatically.&lt;/p&gt;

&lt;p&gt;Add the following item to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon index.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, we test!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3r2g8u6ilmxsu7v1im1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3r2g8u6ilmxsu7v1im1.png" alt="Screenshot of npm run start, running successfully" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, open &lt;code&gt;http://localhost:3000/&lt;/code&gt; in a browser, and if everything went to plan, you'll see the default "Hello World" page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing authentication with JWT
&lt;/h2&gt;

&lt;p&gt;Our basic project setup is done! Next, we’ll implement authentication using JWT tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create routes for authentication
&lt;/h3&gt;

&lt;p&gt;The authentication route will allow users to sign up and log in. Commonly, routes go in &lt;code&gt;routes/&lt;/code&gt;, and since this is an authentication mechanism, we'll name it &lt;code&gt;authentication.js&lt;/code&gt;. I've split this into multiple sections to make it easier to read, but it's the same file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bcryptjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// in-memory database to keep things basic for this tutorial&lt;/span&gt;

&lt;span class="c1"&gt;// Register route&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/signup, (req, res) = &amp;gt;{

  const { username, password, role } = req.body;

  if (!Array.isArray(role)) {
    return res.status(400).json({ message: "Role must be an array" });
  }

  const userExists = users.find(user = &amp;gt;user.username === username);
  if (userExists) {
    return res.status(400).json({
      message: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;already&lt;/span&gt; &lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
    });
  }

  const hashedPassword = bcrypt.hashSync(password, 8);

  users.push({
    username,
    password: hashedPassword,
    role
  });

  res.status(201).json({
    message: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;registered&lt;/span&gt; &lt;span class="nx"&gt;successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
  });
});
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Login route &lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;password&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPasswordValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compareSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPasswordValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;token&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signup route allows users to register by providing a username and password. Upon receiving the data, it creates a new user instance and saves it to the in-memory database.&lt;/p&gt;

&lt;p&gt;And, the login route verifies the user's credentials against the in-memory database. If the username and password match, it generates a JWT token and returns it to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware for JWT verification
&lt;/h3&gt;

&lt;p&gt;Now, we’ll add one middleware function called &lt;code&gt;verifyJWT&lt;/code&gt; that verifies the JWT token sent by the client, and which authenticates the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;authenticateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allowedRoles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
      });
    }

    jwt.verify(token, process.env.JWT_SECRET, (err, user) = &amp;gt;{
      if (err) {
        return res.status(403).json({
          message: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;Invalid&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
        });
      }

      if (!allowedRoles.includes(user.role)) {
        return res.status(403).json({
          message: ‘You do not have the correct role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authenticateToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Protected route
&lt;/h3&gt;

&lt;p&gt;Finally, we'll integrate these authentication routes with our express application in the &lt;code&gt;index.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/protected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;authenticateToken&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Welcome Admin &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have created a &lt;code&gt;/protected&lt;/code&gt; route that uses &lt;code&gt;authenticateToken&lt;/code&gt; to check if the user is authenticated.&lt;/p&gt;

&lt;p&gt;If the user is authenticated, the server sends back a response saying "This is a Protected Route. Welcome [username]".&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;[username]&lt;/code&gt; is replaced with the username of the authenticated user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the endpoints
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sign-up
&lt;/h4&gt;

&lt;p&gt;To validate the sign-up endpoint, we'll make a POST request to this route:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://localhost:3000/auth/signup&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this header:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Content-Type : application/json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the following JSON body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arindam Majumder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"071227"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"roles"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzclu41leah8wi4b6hbci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzclu41leah8wi4b6hbci.png" alt="Screenshot of a postman interaction" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We got the token back as a response. We will copy the token as we'll need it in the next section.&lt;/p&gt;

&lt;h4&gt;
  
  
  Protected route
&lt;/h4&gt;

&lt;p&gt;Now that we have obtained a JWT token from the login endpoint, we will test the protected route by including this token in the request headers.&lt;/p&gt;

&lt;p&gt;For that, we'll make a GET request to the protected route URL &lt;code&gt;http://localhost:3000/protected&lt;/code&gt;. In the request headers, we'll include the JWT token obtained from the login endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwgyx6244kp4a64eq21x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwgyx6244kp4a64eq21x.png" alt="Screenshot of a postman interaction" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this, we have successfully implemented JWT authentication in Node.js!&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing authorization with Cerbos
&lt;/h2&gt;

&lt;p&gt;Now that we have added authentication to our project, we can now proceed authorization using the Cerbos PDP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Launch the Cerbos container
&lt;/h3&gt;

&lt;p&gt;We will begin by launching the Cerbos container via Docker.&lt;/p&gt;

&lt;p&gt;In the base directory, use the following command to run the Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; cerbos &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/cerbos/policies:/policies &lt;span class="nt"&gt;-p&lt;/span&gt; 3592:3592 &lt;span class="nt"&gt;-p&lt;/span&gt; 3593:3593 ghcr.io/cerbos/cerbos:0.34.0 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a quick &lt;code&gt;docker ps&lt;/code&gt; to verify that the container persists.&lt;/p&gt;

&lt;p&gt;For more information about the Cerbos container, see the &lt;a href="https://docs.cerbos.dev/cerbos/latest/installation/container.html" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize the Cerbos client
&lt;/h3&gt;

&lt;p&gt;Next, we set up the Cerbos client using the &lt;code&gt;@cerbos/grpc&lt;/code&gt; library, which we first need to install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @cerbos/grpc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we initialize the client with a few lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GRPC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@cerbos/grpc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GRPC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost:3593&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a CRUD policy
&lt;/h3&gt;

&lt;p&gt;After initializing the Cerbos client, we’ll define a simple CRUD policy in place for our application. Add this basic policy into the policies folder at &lt;code&gt;cerbos/policies/contact.yaml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.cerbos.dev/v1&lt;/span&gt;
&lt;span class="na"&gt;resourcePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;contact&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EFFECT_ALLOW&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EFFECT_ALLOW&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Access control middleware
&lt;/h3&gt;

&lt;p&gt;Next, we'll create some middleware to check access for requests. In &lt;code&gt;middleware/access.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GRPC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@cerbos/grpc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GRPC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost:3593&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwtToPrincipal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;roles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;jwtToPrincipal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;writeAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;jwtToPrincipal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;readAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;writeAccess&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;jwtToPrincipal&lt;/code&gt; function is a utility function that converts a JSON Web Token (JWT) payload into a Cerbos principal object. It extracts the &lt;code&gt;sub&lt;/code&gt; (subject), &lt;code&gt;iat&lt;/code&gt; (issued at), and &lt;code&gt;roles&lt;/code&gt; properties from the JWT payload and assigns them to the corresponding properties of the principal object&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;readAccess&lt;/code&gt; function is an asynchronous middleware function that checks if the current user has permission to read a contact resource. It uses the &lt;code&gt;cerbos.checkResource&lt;/code&gt; method to make an authorization decision. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;writeAccess&lt;/code&gt; function is similar to the &lt;code&gt;readAccess&lt;/code&gt; function, but it checks for permission to write to the contact resource instead of reading. It uses the "write" action in the &lt;code&gt;cerbos.checkResource&lt;/code&gt; method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement authorized routes
&lt;/h3&gt;

&lt;p&gt;Finally, let's implement routes to check user access using Cerbos.&lt;/p&gt;

&lt;p&gt;Import the required middleware functions for read and write access checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;readAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;writeAccess&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./middleware/access&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;index.js&lt;/code&gt; file to include the following routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read Access Granted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;writeAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Write Access Granted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! By following these steps, we have successfully implemented authorization and RBAC in our Node.js application using Cerbos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the authorized route
&lt;/h2&gt;

&lt;p&gt;Now, we’ll test to see if the user has permission to do specific tasks. &lt;/p&gt;

&lt;p&gt;To check if the user has write access, we'll make a POST request to &lt;code&gt;http://localhost:3000/write&lt;/code&gt; with the following headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Content-Type: application/json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Authorization: JWT_TOKEN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvt5629hfx909l9g014j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvt5629hfx909l9g014j.png" alt="Screenshot of a postman interaction" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user with the admin role has access to this route.&lt;/p&gt;

&lt;p&gt;Next, to check if the user has read access, we'll make a GET request to &lt;code&gt;http://localhost:3000/read&lt;/code&gt; with the following headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Content-Type: application/json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Authorization: JWT_TOKEN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If successful, that will return as &lt;code&gt;Read Access Granted&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;Finally, let's check a user with the &lt;em&gt;user&lt;/em&gt; role to see if it has write access or not. Make a POST request to &lt;a href="http://localhost:3000/write" rel="noopener noreferrer"&gt;http://localhost:3000/write&lt;/a&gt; with the following headers &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Content-Type: application/json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;`Authorization: JWT_TOKEN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As expected, we got an &lt;em&gt;unauthorized&lt;/em&gt; response. That means the user doesn’t have access to that route. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we covered the basics of authentication and authorization, and how to integrate JWT authentication and Cerbos authorization into a Node.js application.&lt;/p&gt;

&lt;center&gt;

  &lt;a href="https://cta-service-cms2.hubspot.com/web-interactives/public/v1/track/redirect?encryptedPayload=AVxigLJcZiZ24z6ZSah4IpOn8dABnds9mrKKh6e4PJqvKxet7ffhWKXW0MdjhgVQy4mpPiz%2BmP6afTEqsC16yImlV%2FKtxCF9SLhJub2UaJVdW9FJFbjqw2pDljc4t3o7wysyDZUCo3QHGt4JiG3yBqSqDFxK%2FhbxRSgua197Oqt7wTaa07SsSxBmDYqFpmLr&amp;amp;webInteractiveContentId=168996984756&amp;amp;portalId=20289770" rel="noopener noreferrer"&gt;
    &lt;img alt="BlogCTA - Hub" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fno-cache.hubspot.com%2Fcta%2Fdefault%2F20289770%2Finteractive-168996984756.png" width="538" height="277"&gt;
  &lt;/a&gt;

&lt;/center&gt;

</description>
      <category>authorization</category>
      <category>node</category>
      <category>tutorial</category>
      <category>express</category>
    </item>
    <item>
      <title>We Are Developers World Congress; an Engineer's Travelogue</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 07 Aug 2024 14:33:53 +0000</pubDate>
      <link>https://forem.com/cerbos/we-are-developers-world-congress-an-engineers-travelogue-3di7</link>
      <guid>https://forem.com/cerbos/we-are-developers-world-congress-an-engineers-travelogue-3di7</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by Cerbos engineer Sam Lock (connect on &lt;a href="https://www.linkedin.com/in/samuellock" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://github.com/Sambigeara" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thursday
&lt;/h2&gt;

&lt;h3&gt;
  
  
  06:50
&lt;/h3&gt;

&lt;p&gt;My alarm shouts in my ear that it’s time to wake up. I sit up and am momentarily confused, but then remember that I’m in Berlin, in a hotel room, and I’m staffing our company booth at a conference today. My body is aching; I wonder why, but then I remember the 50km I scooter’d across the city the day before. The scooters are electric but the Berlin streets are cobbled and unforgiving. The botanical gardens are nice, though.&lt;/p&gt;

&lt;p&gt;I fall out of bed, stand up, glance at the coffee machine. It looks confusing to my sleep-addled brain. I glance at the time, it’s 6:52; “oh, I have loads of time”. I sit down again to catch my breath. A few seconds later, I glance at the time again: 7:10, “but how?”. I pick myself up and hurl myself into the bathroom.&lt;/p&gt;

&lt;p&gt;The shower is angry and powerful; I desperately swing for the shower curtain as the torrent pushes me backwards with the force of a thousand rivers. Any residual sleepiness is washed away by adrenaline and the desire to live.&lt;/p&gt;

&lt;p&gt;I’m clean and awake now. My bag is packed, I have my ticket ready to go. I glance at the coffee machine again; it looks less intimidating. I fill the reservoir, stab in a capsule, and press the button. It rumbles to life and spits coffee downwards in the general direction of the mug. The table is given a healthy dose, too. I stop briefly to admire the Jackson Pollock-esque artwork adorning the wooden top.&lt;/p&gt;

&lt;h3&gt;
  
  
  07:28
&lt;/h3&gt;

&lt;p&gt;I feel more alert now. The coffee that made it into the mug has further lifted me from my haze and I head downstairs to meet my colleagues. I realise at this point that I forgot to have breakfast. I reason that I could probably do with skipping a meal and push it to the back of my mind. Not today, hunger.&lt;/p&gt;

&lt;p&gt;Our team of four piles into a taxi. I’m kindly offered the front seat. The driver scrambles to clear the newspaper and pastry wrappers before I fold myself in. I’ve been on holiday for a little while, so open up Slack to peruse through the backlog of missed messages from the week prior as we head through the busy roads of rush-hour Berlin.&lt;/p&gt;

&lt;h3&gt;
  
  
  07:51
&lt;/h3&gt;

&lt;p&gt;We arrive at Messe Berlin. Although I’ve been here the year prior, I’m once again impressed by the sheer size of the place. It’s early, but already there are eager crowds forming. We climb out the car and retrieve the various sacks of merch from the boot. We walk down the grand steps towards the entrance to pick up our passes and wristbands. I’m overcome by a feeling of power and belonging.&lt;/p&gt;

&lt;p&gt;I follow my colleagues through the various exhibitor spaces towards our own. My fight-or-flight response kicks in as we pass a booth with a carnival hammer game. The attendee scores well; a couple of our team pledge to better the score later on. We discuss optimal swinging techniques but before we can come to a conclusion, we reach our own booth. Game time.&lt;/p&gt;

&lt;h3&gt;
  
  
  08:04
&lt;/h3&gt;

&lt;p&gt;We pounce into action. One team member volunteers for a hunter-gatherer mission to find coffee. The remaining members start distributing merch around our allotted square of exhibitor space. There are four of us and two chairs. Thankfully, an unused booth behind us presents us with an additional chair. Only one weary stander. Thank you, conference.&lt;/p&gt;

&lt;p&gt;We disappear off to have a swing of the hammer. Our CEO tops the leaderboard early on. Myself and another colleague are less pleased with our results. Probably rigged, I think to myself. Back to the booth.&lt;/p&gt;

&lt;p&gt;With the distant thuds of the hammer ringing out, we settle in and get ready for the day as the first attendees start to appear.&lt;/p&gt;

&lt;p&gt;“Hello! How are you? What’s Cerbos?”&lt;/p&gt;

&lt;p&gt;“Well, tell me what you do, and I’ll see how it could apply…”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8krxz3roajyr0osyagxu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8krxz3roajyr0osyagxu.jpg" alt="Cerbos Booth with people milling about" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  10:17
&lt;/h3&gt;

&lt;p&gt;The conversations are rich and varied. Some have felt the pain of authorization and eagerly listen as we share the wonders of Cerbos. Others don’t understand authorization, but have seen our Cerbie plushies from afar. “How can I get one of those”, they ask. “You must care about Cerbos, first.” The denials are awkward, but necessary. Cerbies are finite and surprisingly expensive to produce. Some people come up and shout their desire for a Cerbie to my face. I weather the storm and stand my ground. “No”, I say, bravely.&lt;/p&gt;

&lt;p&gt;Talking about authorization is thirsty work. I scour the halls for a water fountain, but alas, no water to be found. I ask a volunteer who offers me no clues but wishes me luck on my search. “Surely, it’s somewhere”. I eventually give up, find a coffee stand, and reluctantly pass over the €4.10 for a small bottle. I get a couple extra for my equally dehydrated colleagues. As I walk back to the stand, I debate with myself whether or not I should tell my boss how much I just spent on water.&lt;/p&gt;

&lt;h3&gt;
  
  
  13:08
&lt;/h3&gt;

&lt;p&gt;Lunch beckons. I step outside and wait for my eyes to adjust to the light. It’s warm in Berlin; almost too warm. I spy my prize, the fabled “hotdog wrap” van from the year prior. Glorious, gravy and mashed potato filled things. I make haste, buy my food, and refuel. Back to the booth.&lt;/p&gt;

&lt;h3&gt;
  
  
  15:22
&lt;/h3&gt;

&lt;p&gt;I’ve been tasked with a mission for doughnut retrieval. I’m briefed by a colleague; the doughnut deliverer has set off to the famous “Brammibal’s” (the best doughnut makers in Berlin?). I make a mental note, then return to authorization conversations and Cerbie denials.&lt;/p&gt;

&lt;h3&gt;
  
  
  16:02
&lt;/h3&gt;

&lt;p&gt;The doughnuts are en route.&lt;/p&gt;

&lt;p&gt;My hips start to get sore because I’m a delicate desk-sitter by profession. I do some ad-hoc yoga to limber up.&lt;/p&gt;

&lt;h3&gt;
  
  
  17:09
&lt;/h3&gt;

&lt;p&gt;Call from the driver. Even closer. I suggest a location and set off across Messe, passing the hammer booth. The exhibitors' faces suggest that they regret their noisy choice of attraction. I continue for about 10 minutes in one direction, find a spot, share my location on Whatsapp, then set up camp.&lt;/p&gt;

&lt;h3&gt;
  
  
  17:27
&lt;/h3&gt;

&lt;p&gt;Call from the driver. They’re nearby. “Did you see my location?”, I ask. “Yes, I’ll see you there soon”, they reply. Excellent.&lt;/p&gt;

&lt;h3&gt;
  
  
  17:31
&lt;/h3&gt;

&lt;p&gt;Call from the driver: “I can’t see you”, they say. “Share your location?”, I suggest. 500 yards away. “Damn you”, I think to myself, before setting off in the opposite direction to meet with the confused driver.&lt;/p&gt;

&lt;p&gt;I eventually find them, state my name, and claim my prize. “Can I go to the toilet?”, they ask. I’m puzzled. I’m not the toilet gatekeeper. “Probably”, I reply.&lt;/p&gt;

&lt;h3&gt;
  
  
  18:00
&lt;/h3&gt;

&lt;p&gt;We officially transition to the “booth crawl” section of the day. A colleague procures some beers. They’re slightly warm but taste like liquid wheaty gold. The doughnuts are revealed. I eat one. They’re light and fluffy and delicious. More conversations are had. More people ask for Cerbies. We give out a few. I eat another doughnut. Then another.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs73jwi9ickhqfkoart12.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs73jwi9ickhqfkoart12.jpg" alt="Many colourful doughnuts in a pink box" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  19:30'ish
&lt;/h3&gt;

&lt;p&gt;I feel some regret for the quantity of doughnuts I’ve consumed. I feel a bit poorly as we pack up the booth and head out to find a taxi to get back to the hotel, then each disappear off for a short, much needed rest in our rooms before dinner.&lt;/p&gt;

&lt;h3&gt;
  
  
  21:00'ish
&lt;/h3&gt;

&lt;p&gt;I’m tasked with finding a restaurant so I scour Google maps and find the perfect one nearby. Traditional German food, classic wood furnishings; lovely. I brief my boss that they may be cash-only and he heads off to find some cash. We set off and eventually find the restaurant, but they’ve stopped serving food. I feel ashamed, but thankfully we find a burger joint nearby. They accept card payments.&lt;/p&gt;

&lt;p&gt;The burgers were very good; we finish them off then return to the hotel. No hotel beers for this tired lot – straight off to bed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Friday
&lt;/h2&gt;

&lt;h3&gt;
  
  
  06:50
&lt;/h3&gt;

&lt;p&gt;My alarm shouts at me again. I’m bleary-eyed, but today I’m better prepared for the hell-shower and the over-excited coffee machine. I go about my morning routine and prepare for the day.&lt;/p&gt;

&lt;h3&gt;
  
  
  07:28am
&lt;/h3&gt;

&lt;p&gt;I head downstairs for breakfast. Straight to the cereal bar. I add a spoonful from every jar to my bowl to form a single “super-cereal”. No hungry start for me today. I join my colleague and polish it off before getting some fruit to counteract my thus far beige breakfast.&lt;/p&gt;

&lt;h3&gt;
  
  
  08:00
&lt;/h3&gt;

&lt;p&gt;Into a taxi and off to the conference. We know the drill – a colleague finds us some coffees and we settle down ready for day 2.&lt;/p&gt;

&lt;p&gt;Rumours start to circulate of a little software bug that might be impacting some computers somewhere in the world. Meh – don’t think we need to worry about that.&lt;/p&gt;

&lt;h3&gt;
  
  
  08:07
&lt;/h3&gt;

&lt;p&gt;We definitely do need to worry about that. We all struggle to check in via our airline apps for our various flights home later in the day, and passively watch on different news outlets as a simple (highly privileged) update brings the world to its knees. Oh well, we’ll talk about authorization until then.&lt;/p&gt;

&lt;h3&gt;
  
  
  10:42
&lt;/h3&gt;

&lt;p&gt;It’s been a hectic couple of days and our t-shirt supplies are nearly depleted. Only a handful of size “S” remain.&lt;/p&gt;

&lt;p&gt;I have an in-depth conversation with someone about their authorization needs. We’re both satisfied with the eventual outcome – they will go away and try to implement Cerbos and we will be happy to answer any questions that they might have. Great!&lt;/p&gt;

&lt;p&gt;They ask for a t-shirt. “Sure!”, I say. “Are you [a] small?” I ask. “Yes, I am quite small”, they reply. I curse myself for an unfortunate choice of wording.&lt;/p&gt;

&lt;h3&gt;
  
  
  12:00
&lt;/h3&gt;

&lt;p&gt;It’s raffle time. A crowd gathers around our booth for the chance to win our grand prize: a Super Nintendo System Lego set! My boss throws some Cerbies into the crowd to warm them up, much like a bouquet-toss at a wedding, and people scrap for them with a surprising level of urgency. People really do love our plushies. Thankfully no-one was hurt.&lt;/p&gt;

&lt;p&gt;All the entries were placed into a virtual hat, and a name pulled. A delighted looking recipient came forward on the first draw and we handed it over.&lt;/p&gt;

&lt;h3&gt;
  
  
  14:23
&lt;/h3&gt;

&lt;p&gt;More yoga. I’m no good at standing up it seems.&lt;/p&gt;

&lt;p&gt;The exhibition halls have started to quieten down. People are running out of steam. Not us, though – we’ve depleted our merch-reserves, but the conversations are still flowing.&lt;/p&gt;

&lt;h3&gt;
  
  
  15:48
&lt;/h3&gt;

&lt;p&gt;Time to go. I share a similar timed flight with our CEO, so we pack up together and head off. As we leave, he points out the water fountain just a stone’s throw from our booth. Whoops. We get in our Uber and anxiously make our way to Berlin Brandenburg to see what havoc CrowdStrike has unleashed upon the airport.&lt;/p&gt;

&lt;h3&gt;
  
  
  PM
&lt;/h3&gt;

&lt;p&gt;None, it seems. Security and passport control is seamless. I and other travellers play a small game of plane Hokey Cokey as they struggle to find us one with working air conditioning. But we eventually lift off, and bid farewell to Berlin and to We Are Developers for another year.&lt;/p&gt;

&lt;p&gt;See you all again next time ✌️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1hf9ficeyyixlg7orl2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1hf9ficeyyixlg7orl2.jpg" alt="Sam sitting at the Cerbos booth" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;Cerbos is an open-source, scalable authorization layer for software applications. It simplifies access control by separating authorization logic from business logic, allowing developers to define and enforce complex policies with ease. Cerbos integrates seamlessly with existing applications and supports various environments, ensuring secure and efficient permission management.&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, or to chat to us and other like-minded technologists, please &lt;a href="https://community.cerbos.dev/" rel="noopener noreferrer"&gt;join our Slack community!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>conference</category>
      <category>humour</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Introduction to RBAC in Kubernetes</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Tue, 30 Jul 2024 13:51:52 +0000</pubDate>
      <link>https://forem.com/cerbos/introduction-to-rbac-in-kubernetes-5hh5</link>
      <guid>https://forem.com/cerbos/introduction-to-rbac-in-kubernetes-5hh5</guid>
      <description>&lt;p&gt;&lt;em&gt;Guest article written by &lt;a href="https://www.linkedin.com/in/tania-duggal-07a297220/" rel="noopener noreferrer"&gt;Tania Duggal&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this article, you will learn what RBAC is, the key challenges and approaches to managing RBAC in Kubernetes, and how Cerbos can help you in your application security.&lt;/p&gt;

&lt;p&gt;In Kubernetes, when a request comes to the API Server to create resources, it processes the request in different steps. It first checks from where a request is made and whether a user is valid or not. This process is called authentication. There are two categories of users: normal users and service accounts. Service accounts are managed internally by Kubernetes, and are used by applications that access the cluster, such as the Monitoring Application. Normal users are external entities that may include administrators, developers, and other humans. &lt;/p&gt;

&lt;p&gt;After authentication, the next process is &lt;a href="https://www.cerbos.dev/blog/authorization-as-a-service" rel="noopener noreferrer"&gt;authorization&lt;/a&gt; for the requested action and permissions. While Kubernetes supports multiple authorization methods, the one we’ll concentrate on in this article is called &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/rbac" rel="noopener noreferrer"&gt;RBAC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14ls4ln8chm4osfzj05r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14ls4ln8chm4osfzj05r.png" alt="A graphical workflow of how a kubectl command is authenticated, authorized, and passed along to action" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is RBAC?
&lt;/h2&gt;

&lt;p&gt;RBAC stands for Role Based Access Control. It is a method through which we can control access to resources and actions based on the roles assigned to the users. In Kubernetes, RBAC is how the administrator can control and allow which actions the users can perform on which resources, respectively. RBAC is managed just like everything else in Kubernetes: as objects that can be described via YAML or kubectl. To enable RBAC, the &lt;code&gt;--authorization-mode&lt;/code&gt; flag must be set to RBAC when starting the API server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kube-apiserver &lt;span class="nt"&gt;--authorization-mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;RBAC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Core Objects of Kubernetes RBAC
&lt;/h2&gt;

&lt;p&gt;The RBAC API declares four core objects. These are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; It is a way of defining what actions users can perform within a namespace. This defines which actions such as get, list, create, delete, etc., can be performed on specific resources like pods, services, and deployments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cluster Role:&lt;/strong&gt; This is similar to the role, but it is used for cluster-wide permissions. It means it is not limited to a specific namespace and can be used in all namespaces of the cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RoleBinding:&lt;/strong&gt; RoleBinding binds the role with one or more users, groups, and service accounts in a particular namespace. In this way, whatever permissions we have defined in a role get allotted to the users, groups, or service accounts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ClusterRoleBinding:&lt;/strong&gt; ClusterRoleBinding binds the ClusterRole to one or more users, groups, and service accounts throughout the cluster. This allows the permissions defined in ClusterRole to be assigned to users in all namespaces of the cluster.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How RBAC is implemented in Kubernetes
&lt;/h2&gt;

&lt;p&gt;It depends on your requirements and what you want to create for your resources, whether it be a Role or a ClusterRole. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a Role and assign it with RoleBinding&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# "" indicates the core API group&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;update"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delete"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have permitted pods to get, list, update, delete, and create the resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;devuser-developer-binding&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;User&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev-user&lt;/span&gt; &lt;span class="c1"&gt;# "name" is case sensitive&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RoleBinding binds the &lt;strong&gt;developer&lt;/strong&gt; Role to a user named &lt;strong&gt;dev-user&lt;/strong&gt; in the default namespace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a ClusterRole and assign it with ClusterRoleBinding&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRole&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-administrator&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# "" indicates the core API group&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nodes"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delete"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have permitted nodes to get, list, delete, and create the resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-admin-role-binding&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;User&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-admin&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRole&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-administrator&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ClusterRoleBinding binds the &lt;strong&gt;cluster-administrator&lt;/strong&gt; ClusterRole to a user named &lt;strong&gt;cluster-admin&lt;/strong&gt; in all namespaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges in Kubernetes RBAC
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Difficulty in Management:&lt;/strong&gt; It's difficult to manage RBAC in Kubernetes when you have so many roles and permissions. Each user and service requires particular permission, which can be time-consuming and complex. As the number of users, applications, and namespaces grows, it becomes difficult to handle the RBAC configuration.&lt;br&gt;&lt;br&gt;
For example, if you have a team of developers in different namespaces, you must ensure that each developer can only access the resources that they need. Mistakenly, if any developer gets too many permissions, they can unintentionally modify other's resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability Issues:&lt;/strong&gt; As the organization grows, so does the number of users and roles. This growth is asymmetrical, and the challenge of scaling RBAC manually can quickly become overwhelming. It becomes a huge task to manage and define permissions for each employee. A minor error can lead to a security breach or any operational issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Process:&lt;/strong&gt; When you configure and define RBAC roles and permissions manually, it can be quite dangerous. Even a small mistake can lead to a security breach.&lt;br&gt;&lt;br&gt;
For example, if an administrator has to permit the developer only to read but mistakenly gives permission to him to write as well, then the developer can modify data, which can lead to vulnerabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs Auditing and Compliance&lt;/strong&gt;: It is necessary to maintain accurate and detailed records for auditing and compliance. To follow standards such as GDPR and HIPAA, you have to maintain detailed logs that show which users performed what actions and when. Kubernetes provides limited tools for RBAC auditing, which makes compliance challenging.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Approaches to Addressing Kubernetes RBAC Challenges
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementing Principle of Least Privilege:&lt;/strong&gt; Least Privilege means you have to give minimum permissions to the users they need to do their work. Too many permissions can result in security issues. You should follow the least privilege approach to enhance security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Policy Management Tools:&lt;/strong&gt; Managing too many policies can be difficult. You can use policy management tools to reduce the burden of managing policies. These tools can create, update, and manage policies for you and ensure RBAC policies are up-to-date and secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Namespaced Roles:&lt;/strong&gt; You should use namespace roles to limit the scope of your resources. With a namespaced role, you can ensure that a user or service only gets access to the resources in that namespace that are necessary for their function. This isolation helps us prevent accidental access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auditing RBAC regularly:&lt;/strong&gt; You should audit your RBAC configuration regularly. With regular lookups on these configurations, you can timely identify issues and fix them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's clear that managing Kubernetes access and permissions is quite complex, but it provides a robust security feature at the infrastructure level, and is well worth considering for your future deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bring powerful RBAC to your applications
&lt;/h3&gt;

&lt;p&gt;Finally, if you're looking to bring that same infrastructure-level power to the application layer, you should check out Cerbos. The &lt;a href="https://www.cerbos.dev/product-cerbos-pdp?utm_campaign=topic_authorization&amp;amp;utm_source=dev.to&amp;amp;utm_medium=text&amp;amp;utm_content=&amp;amp;utm_term="&gt;Cerbos Policy Decision Point (PDP)&lt;/a&gt; is the scalable, open source authorization layer for implementing roles and permissions at the application layer. It can be deployed easily as a sidecar alongside your Kubernetes-managed applications. Try it today!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>rbac</category>
      <category>authorization</category>
      <category>authz</category>
    </item>
    <item>
      <title>Cerbos Hub: A complete authz management system</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Thu, 25 Jul 2024 09:45:02 +0000</pubDate>
      <link>https://forem.com/cerbos/cerbos-hub-a-complete-authz-management-system-4a3e</link>
      <guid>https://forem.com/cerbos/cerbos-hub-a-complete-authz-management-system-4a3e</guid>
      <description>&lt;p&gt;Good news everyone: &lt;a href="https://www.cerbos.dev/news/cerbos-hub-is-now-generally-available?utm_campaign=cerbos_hub_ga&amp;amp;utm_source=dev.to&amp;amp;utm_medium=text&amp;amp;utm_content=&amp;amp;utm_term="&gt;Cerbos Hub&lt;/a&gt; is now generally available! In this post, we’re going to explain what Cerbos Hub is, why it's useful, and how it solves some of the hardest challenges with externalizing authorization. &lt;/p&gt;

&lt;h1&gt;
  
  
  Cerbos: Fine-grained authorization and access control
&lt;/h1&gt;

&lt;p&gt;New to all of this? No problem. Cerbos is a scalable and extensible authorization service for developer, product and security teams. It enables teams to implement fine-grained authorization and access control in their applications, services, and infrastructure in an auditable, programmatic, and scalable way. Maybe you’ve heard of RBAC, ABAC, ReBAC, PBAC and so forth? That’s what Cerbos is all about.&lt;/p&gt;

&lt;p&gt;The Cerbos &lt;a href="https://www.cerbos.dev/product-cerbos-pdp?utm_campaign=cerbos_hub_ga&amp;amp;utm_source=dev.to&amp;amp;utm_medium=text&amp;amp;utm_content=&amp;amp;utm_term="&gt;open source Policy Decision Point&lt;/a&gt; (PDP) is a popular solution for technical teams who’ve made the decision to separate the authorization process from their core application code, freeing them up to concentrate on their core business. It can be deployed as a binary on metal, in a sidecar, as a service in a VM—anywhere on your infrastructure, any way you want.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cerbos Hub: manage centrally, deploy anywhere
&lt;/h1&gt;

&lt;p&gt;One of the great things about the PDP is how powerful and extensible it is. &lt;a href="https://www.cerbos.dev/product-cerbos-hub?utm_campaign=cerbos_hub_ga&amp;amp;utm_source=dev.to&amp;amp;utm_medium=text&amp;amp;utm_content=&amp;amp;utm_term="&gt;Cerbos Hub&lt;/a&gt; is designed from the ground up to help you harness that power and control that extensibility. The industry term is Policy Administration Point (PAP), but it can be thought of as a control plane. Cerbos Hub is all about unlocking the full potential of the PDPs by providing an intuitive user interface, collaborative policy management, and a powerful testing and deployment pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplified policy management
&lt;/h2&gt;

&lt;p&gt;Cerbos Hub centralizes policy management no matter where or how your PDPs are deployed. With a managed CI/CD pipeline, you can deploy and test policies seamlessly across development, testing, and production environments. No more juggling tools and processes—Cerbos Hub coordinates the rollout of authorization policies across your apps, APIs, and infrastructure.&lt;/p&gt;

&lt;p&gt;Whether your infrastructure is on-premise, cloud-based, or serverless, Cerbos adapts to your needs. It supports edge devices, security hardware, and even in-browser runtimes for frameworks like React and Angular through its Embedded Policy Decision Point capability. This means you can authorize anywhere, keeping your policies in sync regardless of the environment. And with Cerbos Hub, managing that synchronization is easier than ever!&lt;/p&gt;

&lt;h2&gt;
  
  
  Embedded PDP
&lt;/h2&gt;

&lt;p&gt;As one of our engineers so eloquently put it: “This requires some explanation.” Traditionally, when you’re thinking about service delivery, you’re thinking about a binary running in a container or sitting on a virtual machine somewhere. That’s fine, but it’s not the only model.&lt;/p&gt;

&lt;p&gt;If you want to perform authorization checks directly from the end-user device, that would mean both exposing your PDP to the Internet and inviting network latency with every call. Another approach is to run those authorization checks on the device, in the browser, or from the edge—that’s where Embedded PDP comes into play.&lt;/p&gt;

&lt;p&gt;The Cerbos Embedded Policy Decision Point is a WebAssembly module that runs right in your application, putting authorization checks as close to the user as possible. This reduces your security footprint, improves latency, and unlocks powerful functionality; for example, you can embed authorization checks in your user interface to only render the buttons they actually need to see!&lt;/p&gt;

&lt;p&gt;When you update your policies in Cerbos Hub, Embedded PDPs are automatically compiled and distributed to your end-users via global CDN. This simplifies updates and streamlines management of your policies no matter where your end users are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Robust policy authoring and testing
&lt;/h2&gt;

&lt;p&gt;Cerbos Hub's web IDE lets you collaboratively build and test policies right in your browser! Create policies in YAML with our useful templates, then use the playground to refine, validate, and test those authorization rules. And since everything is ultimately code, this can be tied into your existing deployment workflow, meaning that the validation and deployment of your policies becomes another step in your application management lifecycle. Git actions, artifact generation, automated build and deployment pipelines—it all fits!&lt;/p&gt;

&lt;p&gt;However, authorization is more than just code—it’s a representation of how your business functions. Who can access what, where, when, and how, goes beyond deploying your stack. Cerbos Hub is the best way to get everybody involved; from operations, to HR, to accounts payable (and even your CISO), Hub’s collaborative policy-building tools give everybody the opportunity to speak the same language and concentrate on their requirements and business cases.&lt;/p&gt;

&lt;h1&gt;
  
  
  Get started today!
&lt;/h1&gt;

&lt;p&gt;Ready to level up your authorization game? &lt;a href="https://hub.cerbos.cloud?utm_campaign=cerbos_hub_ga&amp;amp;utm_source=dev.to&amp;amp;utm_medium=text&amp;amp;utm_content=&amp;amp;utm_term="&gt;Try Cerbos Hub&lt;/a&gt; and experience the future of authorization management.&lt;/p&gt;

</description>
      <category>authz</category>
      <category>webassembly</category>
      <category>yaml</category>
      <category>accesscontrol</category>
    </item>
    <item>
      <title>Microsoft Entra External ID &amp; Cerbos ✨</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 26 Jun 2024 13:18:37 +0000</pubDate>
      <link>https://forem.com/cerbos/microsoft-entra-external-id-cerbos-ccp</link>
      <guid>https://forem.com/cerbos/microsoft-entra-external-id-cerbos-ccp</guid>
      <description>&lt;p&gt;👋 Looking to level up your authentication (authn) and authorization (authz) game? Here's a great tutorial that dives into integrating Microsoft Entra External ID for seamless external authentication and Cerbos for top-notch, fine-grained authorization. You’ll learn about adding authentication to your external-facing apps, how to write policies, and what a policy decision point is. With clear steps, sample code, and just enough YAML to meet your daily quota, you'll learn to create secure and scalable solutions that are actually usable in the real world. Check out the &lt;a href="https://bit.ly/45FdSGu" rel="noopener noreferrer"&gt;full guide here&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;As an added bonus, this is actually part two of a three-part series. If you’re not entirely sure what authentication and authorization are (or just want a refresher before diving into the tutorial), you should definitely check out the &lt;a href="https://devblogs.microsoft.com/identity/extneral-id-and-cerbos/" rel="noopener noreferrer"&gt;first part&lt;/a&gt;, too. 😄&lt;/p&gt;

&lt;p&gt;Questions? Comments? Hit us up in our &lt;a href="https://go.cerbos.io/slack" rel="noopener noreferrer"&gt;Community Slack&lt;/a&gt;—let's get that conversation going!&lt;/p&gt;

</description>
      <category>authz</category>
      <category>tutorial</category>
      <category>cerbos</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building secure applications: Key insights on authentication and authorization from Cerbos and Microsoft Entra</title>
      <dc:creator>Rohit Ghumare</dc:creator>
      <pubDate>Thu, 04 Apr 2024 13:51:37 +0000</pubDate>
      <link>https://forem.com/cerbos/building-secure-applications-key-insights-on-authentication-and-authorization-from-cerbos-and-microsoft-entra-4oi9</link>
      <guid>https://forem.com/cerbos/building-secure-applications-key-insights-on-authentication-and-authorization-from-cerbos-and-microsoft-entra-4oi9</guid>
      <description>&lt;p&gt;Published by Martin Gjoshevski &amp;amp; Alex Olivier on April 03, 2024&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblk9ugvjvhsk8qx3zc7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblk9ugvjvhsk8qx3zc7i.png" alt="Image description" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Understanding the critical roles of authentication and authorization is essential in safeguarding data and ensuring system security across various software applications. Our latest collaborative effort between &lt;a href="https://www.cerbos.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;Cerbos&lt;/strong&gt;&lt;/a&gt; and Microsoft sheds light on these critical components, focusing on the powerful synergy between Microsoft Entra External ID and Cerbos for securing applications. This blog post, authored by Martin Gjoshevski, Senior Customer Engineer at Microsoft, and Alex Olivier, Chief Product Officer from Cerbos, a Microsoft Partner, serves as a primer to the indispensable roles played by authentication (AuthN) and authorization (AuthZ), offering insights into their distinct functions and the necessity for a comprehensive security strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-&amp;gt;&lt;/strong&gt; &lt;a href="https://devblogs.microsoft.com/identity/extneral-id-and-cerbos/" rel="noopener noreferrer"&gt;&lt;strong&gt;Read full article on Microsoft's blog&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-&amp;gt;&lt;/strong&gt; &lt;a href="https://www.cerbos.dev/product-cerbos-hub" rel="noopener noreferrer"&gt;&lt;strong&gt;Try Cerbos Hub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the heart of this piece is the differentiation between authentication and authorization - two terms often intertwined but fundamentally different in their roles within cybersecurity. Authentication verifies user identity, acting as the first line of defense against unauthorized access. Authorization, on the other hand, determines what an authenticated user is allowed to do, thereby controlling access to resources and data. This blog post, the first in a series of three, delves into the intricacies of choosing the right authorization approach, exploring both coupled and &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/decoupled-authorization" rel="noopener noreferrer"&gt;&lt;strong&gt;decoupled&lt;/strong&gt;&lt;/a&gt; AuthN and AuthZ models. It provides a foundational understanding for developers and IT professionals on structuring their security protocols effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importance of navigating authentication and authorization
&lt;/h2&gt;

&lt;p&gt;Understanding the nuances of authentication and authorization is paramount for anyone involved in software development and cybersecurity. The collaboration between Cerbos and Microsoft illustrates not only the theoretical underpinnings but also practical considerations in selecting and implementing these security measures. The blog offers a comprehensive guide to navigating the complexities of AuthN and AuthZ, making it an essential read for developers looking to bolster their applications' security.&lt;/p&gt;

&lt;p&gt;To dive deeper into the intricacies of authentication and authorization and to understand how Microsoft Entra External ID and Cerbos can be leveraged to secure your applications, we highly encourage reading the full article on Microsoft's blog. This will equip you with a thorough understanding and practical insights into integrating these solutions into your security framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Authentication and authorization, while often used interchangeably, serve distinct and critical roles in cybersecurity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choosing the right authorization approach, whether it's &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/rbac" rel="noopener noreferrer"&gt;&lt;strong&gt;RBAC&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/abac" rel="noopener noreferrer"&gt;&lt;strong&gt;ABAC&lt;/strong&gt;&lt;/a&gt;, or a &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/pbac" rel="noopener noreferrer"&gt;&lt;strong&gt;policy-based model&lt;/strong&gt;&lt;/a&gt;, depends on the specific needs and structure of your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selecting between coupled or decoupled AuthN and AuthZ for your application depends on various factors, such as size, complexity, and nature of the application, security requirements, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The synergy between Microsoft Entra External ID and Cerbos offers a robust framework for implementing both authentication and authorization, providing flexibility, scalability, and enhanced security for applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stay connected
&lt;/h2&gt;

&lt;p&gt;For those eager to explore Cerbos and its capabilities further, we invite you to try out Cerbos Hub and book a meeting for a more detailed discussion by clicking the buttons below. For a comprehensive exploration of the topics discussed and more insights into authentication and authorization, make sure to &lt;a href="https://devblogs.microsoft.com/identity/extneral-id-and-cerbos/" rel="noopener noreferrer"&gt;&lt;strong&gt;read the full article on Microsoft's blog&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-&amp;gt;&lt;/strong&gt; &lt;a href="https://www.cerbos.dev/product-cerbos-hub" rel="noopener noreferrer"&gt;&lt;strong&gt;Try Cerbos Hub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-&amp;gt;&lt;/strong&gt; &lt;a href="https://www.cerbos.dev/workshop" rel="noopener noreferrer"&gt;&lt;strong&gt;Speak to an engineer&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep an eye out for part 2 of our series, where we'll guide you through the process of integrating Microsoft Entra External ID with Cerbos. We'll delve into how External ID empowers SaaS applications to seamlessly federate identities from a multitude of identity providers, and how Cerbos enhances this ecosystem by facilitating the definition and enforcement of fine-grained authorization policies within applications.&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>security</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>What is an authorization API?</title>
      <dc:creator>Rohit Ghumare</dc:creator>
      <pubDate>Wed, 27 Mar 2024 14:27:05 +0000</pubDate>
      <link>https://forem.com/cerbos/what-is-an-authorization-api-39m3</link>
      <guid>https://forem.com/cerbos/what-is-an-authorization-api-39m3</guid>
      <description>&lt;p&gt;Published by Furqan Butt on &lt;a href="https://www.cerbos.dev/blog/what-is-an-authorization-api" rel="noopener noreferrer"&gt;Cerbos Website&lt;/a&gt; March 26, 2024&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0usbyros3vizrk6y0pws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0usbyros3vizrk6y0pws.png" alt="Image description" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Authorization is &lt;strong&gt;not to be confused with&lt;/strong&gt; &lt;a href="https://www.cerbos.dev/blog/the-differences-between-authentication-and-authorization-in-software-development" rel="noopener noreferrer"&gt;&lt;strong&gt;authentication&lt;/strong&gt;&lt;/a&gt;, which involves verifying the identity of the user making a request.&lt;/p&gt;

&lt;p&gt;Authentication is the first step of application security. A user's identity is verified using credentials like a username and password, security questions, or two-factor authentication. Users are aware that authentication is happening, and they can change their credentials as they see fit.&lt;/p&gt;

&lt;p&gt;Authorization, conversely, happens after authentication, &lt;strong&gt;ie&lt;/strong&gt; when a user has already been identified. The organization grants, manages, monitors, and enforces the access a user has to data and services. It usually happens behind the scenes, without a user's knowledge. They also can't change their authorization level but only request it.&lt;/p&gt;

&lt;p&gt;Some common scenarios requiring authorization include the following:&lt;/p&gt;

&lt;p&gt;Any application that has multiple users with different roles accessing the application needs authorization to ensure users can only access the functionality relevant to their role. Think of an ecommerce platform with sellers, purchasers, and system admins, for example.&lt;/p&gt;

&lt;p&gt;Consider this use case, an E-commerce platform has different users that can perform various activities. The authorization API must ensure ensures that each type of user only gets access to the service, functionality, or data relevant to their role and nothing else.&lt;/p&gt;

&lt;p&gt;Another example is an HR system with system admins, HR staff, and employees as users. Employees should only be able to access their own profile and see details regarding their leave, incentives, and other performance feedback. System admins must be able to create new users and grant or revoke their access, but they must not be able to access employees' personal information or approve leave requests. And HR staff might have different levels of access to information based on their role or seniority.&lt;/p&gt;

&lt;p&gt;Similar scenarios apply to social media platforms and well as banking, healthcare, and government systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The role of an authorization API
&lt;/h2&gt;

&lt;p&gt;As mentioned, the best way to implement authorization in modern systems is with the help of an authorization service. An authorization API is an internal system API designed to evaluate and enforce an authenticated user's level of access to system functionalities or application data.&lt;/p&gt;

&lt;p&gt;Using an authorization API allows you to decouple the application code and authorization logic and maintain them independently, which serves as a safeguard against any accidental or malicious unauthorized access to client data. Because the authorization logic can be &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/centralized-management" rel="noopener noreferrer"&gt;&lt;strong&gt;centralized&lt;/strong&gt;&lt;/a&gt;, you are also spared from writing custom logic for each API endpoint. And for organizations serving multiple clients, decoupled authorization architecture makes it easy to achieve data isolation for tenants.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How an authorization API works&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A general authorization flow generally looks as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252F2517c53399d846eea97f6c5ae8804b7f%252F9802cb654f68407f9ada0c61a8e9873f%3Fwidth%3D740%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252F2517c53399d846eea97f6c5ae8804b7f%252F9802cb654f68407f9ada0c61a8e9873f%3Fwidth%3D740%2520align%3D" alt="Authorization flow" width="740" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A user's digital identity is stored and managed by an identity provider (IdP). When a user has been authenticated, the IdP issues ID and access tokens (usually a JWT) for further authorization. The authorization API validates the access token, which serves as proof that the user is verified and the data provided with the access token can be trusted.&lt;/p&gt;

&lt;p&gt;The next step is to perform scope checks, which includes evaluating the different types of access the user has to system resources or functionality. For example, a user may have read access but no write access to resources or data. &lt;/p&gt;

&lt;p&gt;Scope checks are an &lt;em&gt;optional step&lt;/em&gt; in the authorization process as a user with admin role has access to the entire system while a regular user may only have access to certain parts of the system. Depending upon the type of user accessing the system, the Authorization API may or may not carry out this step.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key components of authorization APIs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An authorization API consists of four key components: an access control model, a policy engine, permission management, and audit logging.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252F2517c53399d846eea97f6c5ae8804b7f%252Fe938facc88f54168afc15b1f7c02d878%3Fwidth%3D740%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.builder.io%2Fapi%2Fv1%2Fimage%2Fassets%252F2517c53399d846eea97f6c5ae8804b7f%252Fe938facc88f54168afc15b1f7c02d878%3Fwidth%3D740%2520align%3D" alt="Authorization API architecture" width="740" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Behind the scenes, the authorization API uses an access control model to implement access control for each user. The two most popular access control models widely adopted are role-based access control (RBAC) and attribute-based access control (ABAC).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/rbac" rel="noopener noreferrer"&gt;&lt;strong&gt;RBAC&lt;/strong&gt;&lt;/a&gt; authorizes a user to access services or data based on their role within the organization. It's fairly simple to implement, especially when user functions within the organization are clearly defined and permission to various functions is associated with the role. A finance role, for example, would allow a user to perform all activities related to finance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/abac" rel="noopener noreferrer"&gt;&lt;strong&gt;ABAC&lt;/strong&gt;&lt;/a&gt; authorizes a user to access services or data based on specific attributes. ABAC is more flexible than RBAC because it allows dynamic and more granular authorization decisions. However, it is more complex to implement as it has finer control over what the user can and cannot do. It's best suited to when users in an organization span multiple domains and perform various activities.&lt;/p&gt;

&lt;p&gt;The policy engine—also known as the policy decision point (PDP)—is what allows or denies a user access to data or services. This component evaluates the compliance rules and policies and makes the decision whether to grant or deny access to the user.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/application-permissions" rel="noopener noreferrer"&gt;&lt;strong&gt;permission management&lt;/strong&gt;&lt;/a&gt; component allows administrators to add, modify, configure, and delete policies. The policy engine refers to the permission management component to get the required policies to enforce. When dealing with multiple clients, the permission management component allows centralized policy administration, management, and monitoring of the policies.&lt;/p&gt;

&lt;p&gt;Lastly, the &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/audit-logs" rel="noopener noreferrer"&gt;&lt;strong&gt;audit logging&lt;/strong&gt;&lt;/a&gt; component documents all the activity in the authorization API. Any additions or modifications to policies and access to resources are logged, which can be used for internal and external audits and showing compliance with industry standards. This component is also critical when you need to generate a trail of events for troubleshooting issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use cases for an authorization API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Authorization APIs can help you improve API management, microservices architecture, cloud security, and compliance.&lt;/p&gt;

&lt;p&gt;You can use an authorization API to enable secure access to APIs based on user and role permissions. It can also help implement rate limiting and throttling to prevent the overuse and abuse of APIs.&lt;/p&gt;

&lt;p&gt;Authorization APIs can provide secure access to microservices based on user role and identity. It can also be used to authenticate and authorize other internal and external microservices and enforce policies for service-to-service communication to maintain security.&lt;/p&gt;

&lt;p&gt;Authorization APIs enable secure access to cloud resources based on user role permissions associated with the user. It can be used to enforce multifactor authentication for cloud accounts and for implementing network security policies to protect cloud resources from cyber threats.&lt;/p&gt;

&lt;p&gt;Lastly, authorization APIs can help facilitate compliance with &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/security-standards" rel="noopener noreferrer"&gt;&lt;strong&gt;regulatory standards&lt;/strong&gt;&lt;/a&gt; such as GDPR, HIPAA, and PCI DSS. It helps provide auditing and logging capabilities to track access to sensitive data and enforce data retention policies to ensure data is stored and deleted appropriately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices for using an authorization API
&lt;/h2&gt;

&lt;p&gt;Here are some best practices of how to use an authorization API to prevent security incidents.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Limit access to sensitive resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The less information an authorization API shares with external parties, the less likely it is for exploiters to gain illegitimate access. It is always better to be overly cautious.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Whitelist and blacklist IP addresses to ensure limited access to resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide basic information in error messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hide all sensitive information from all types of interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limit the number of admins and separate access to resources across roles.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use the principle of least privilege&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Overprivileging users or services can increase the potential of breaches. Limiting an entity's access to data, resources, or application functions to only what is required to complete a task helps reduce the attack surface and mitigates the risk of exploitation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Regularly audit access control policies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Having an additional set of eyes checking your access control policies helps improve your resource access strategy. Regular audits from third-party auditing firms will ensure that any vulnerabilities related to designs are maintained at the highest level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;An authorization API lets you implement access control policies and authorization independent of your core solution to improve flexibility, scalability, and maintainability. It forms part of bigger trends towards centralized authorization strategies and zero trust models to prevent security incidents.&lt;/p&gt;

&lt;p&gt;This article explained what an authorization API is, how it works, and how you can use it to protect your software and infrastructure so that you can implement it in your software and infrastructure.&lt;/p&gt;

</description>
      <category>security</category>
      <category>api</category>
      <category>webdev</category>
      <category>authorization</category>
    </item>
    <item>
      <title>The importance of stateless architecture in authorization systems</title>
      <dc:creator>Rohit Ghumare</dc:creator>
      <pubDate>Thu, 14 Mar 2024 15:37:06 +0000</pubDate>
      <link>https://forem.com/cerbos/the-importance-of-stateless-architecture-in-authorization-systems-4f41</link>
      <guid>https://forem.com/cerbos/the-importance-of-stateless-architecture-in-authorization-systems-4f41</guid>
      <description>&lt;p&gt;This Blog was originally published on the &lt;a href="https://www.cerbos.dev/blog/the-importance-of-stateless-architecture-in-authorization-systems" rel="noopener noreferrer"&gt;Cerbos website&lt;/a&gt; by James Walker&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjw5kgtb0cdpi49dx06g4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjw5kgtb0cdpi49dx06g4.png" alt="stateless architecture image" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stateless is a software architecture where the application holds no information about its operating state or the conditions in which it exists. This contrasts with stateful applications, which do maintain a persistent state throughout their lifetime.&lt;/p&gt;

&lt;p&gt;Going stateless might sound complicated, but it can actually simplify system deployment, maintenance, and integration. This article explores what stateless is, how it’s implemented, and why it’s so beneficial to real-world systems such as authorization services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding stateless architecture
&lt;/h2&gt;

&lt;p&gt;The state of a software system refers to the &lt;a href="https://www.cerbos.dev/features-benefits-and-use-cases/stateless-authorization" rel="noopener noreferrer"&gt;&lt;strong&gt;information available when&lt;/strong&gt;&lt;/a&gt; a function is performed, such as the identity of the logged-in user. A stateful service persists this information, while stateless services reestablish the state each time they’re used.&lt;/p&gt;

&lt;p&gt;The paradigm shifts the responsibility for maintaining state onto the client. For example, in a stateless authorization context, the client should provide the authorization layer with the context describing the user issuing the request and the resource they’re trying to access. The service can then use this information to deliver an authorization outcome without having to fetch any further data itself. As a result, each request is completely independent of any other, and the authorization layer has no external dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benefits of stateless architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=-TROtUh5wvk" rel="noopener noreferrer"&gt;&lt;strong&gt;Stateless systems&lt;/strong&gt;&lt;/a&gt; have several advantages over their stateful counterparts such as better scalability, improved fault tolerance, and simplicity in implementation.&lt;/p&gt;

&lt;p&gt;Their characteristics make them easy to understand and reason about. Each session takes the form of a self-contained transaction where the client issues a request and receives a response. The interaction is handled in the same way each time it occurs because the service holds no state that could affect its outputs.&lt;/p&gt;

&lt;p&gt;The following are a few other benefits of going stateless:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Scalability: Stateless services don’t require access to persistent storage, nor do they depend on replicas of a deployment that need to successfully synchronize with each other. This improves scalability — you can launch an unlimited number of instances across a fleet of physical hosts, providing great operating flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fault tolerance: Stateless reduces the number of dependencies in your system. The service is naturally more fault tolerant as there’s fewer places where errors can occur. If an issue is encountered, the client can simply repeat its request without having to wait for a state correction to apply on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simpler debugging and troubleshooting: No server-side state makes it easier to find and fix issues with your services. When a problem occurs in production, you can repeat the client’s request against one of your service’s development instances to observe the sequence of events involved. Errors experienced by stateful services can be difficult to reproduce if they’re caused by the exact server state that prevailed at the time, which isn’t always possible to replicate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stateless Architecture Examples
&lt;/h2&gt;

&lt;p&gt;Stateless architecture has received more attention in recent years due to the rising interest in microservices and serverless computing.&lt;/p&gt;

&lt;p&gt;However, stateless is a well-established strategy that underpins some of the software systems we take for granted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTTP: The ubiquitous HTTP protocol is arguably the best-known example of a stateless system. A new connection between the server and client is created for each request and then destroyed once the response is received. Stateful sessions are only possible when the client identifies itself in each request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RESTful APIs: REST APIs are stateless services provided over HTTP. Each request that the client makes must provide all the information that the server needs to issue a useful response. The server shouldn’t be assumed to understand a request just because the same client has previously connected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serverless computing: Serverless is an increasingly popular model for quickly building and launching apps without having to maintain your own infrastructure. Serverless systems are implemented as stateless functions that run on demand, dynamically creating their operating environment each time they’re called.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The role of stateless in authorization
&lt;/h2&gt;

&lt;p&gt;Stateless architecture is particularly beneficial to authorization layers. Authorization, the act of checking what a user can do within a system — as opposed to authentication, which verifies a user is who they claim to be — is traditionally implemented as a stateful server-side process, requiring complex dependencies to fetch the user’s details and the permissions they hold. This impedes scalability: database performance will reduce with load, and any synchronization problems could cause different instances of the service to return conflicting authorization outcomes.&lt;/p&gt;

&lt;p&gt;By contrast, stateless authorization facilitates straightforward decisions with predictable results. The application can fetch the state it requires upfront then present it to the authorization layer as a signed token. The token provides the service with all the data it needs to produce an authorization decision, eliminating external dependencies.&lt;/p&gt;

&lt;p&gt;The stateless authorization layer is therefore simpler, more scalable, and easier to implement, especially when multiple clients need to interact with the system. It removes the need to persist and synchronize state across the authorization layer’s instances. Although fetching the state within the application can appear to be an overhead, in reality, most systems will already be holding the required information on the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing stateless authorization
&lt;/h2&gt;

&lt;p&gt;Stateless authorization services use the following high-level architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The application calls the authorization layer when it needs to check whether the active user can perform a particular action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The data sent to the authorization layer includes everything that the service needs to produce an authorization outcome, such as the user’s identity, any permissions or special capabilities they hold, and the identity of the resource that’s been requested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The authorization layer evaluates the provided data and delivers an authorization result (either allow or deny) back to the application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an “allow” result was issued, the application permits the user to perform the requested action against the resource. Otherwise, the user is deemed unauthorized and is blocked from continuing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Crucially, all the information required to produce the authorization result is provided by the application. The authorization layer isn’t responsible for fetching any details about the user or the resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices for stateless authorization
&lt;/h2&gt;

&lt;p&gt;As we’ve seen above, implementing a basic stateless authorization system is relatively straightforward. Once you’ve issued a signed token to a client, it should be able to present it to any instance of your service to access protected resources.&lt;/p&gt;

&lt;p&gt;Nonetheless, the difference between a simple and a production-ready authorization layer depends on the details. Here are some best practices to keep in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensure proper token management
&lt;/h3&gt;

&lt;p&gt;The integrity of stateless auth depends on proper token management. Fortunately, standards such as JWT have solved most of the challenges in this space. It’s safest to issue and consume them using established community libraries such as jwt-go for Go or jsonwebtoken for Node.js. Rolling your own code for these functions can make you vulnerable to security issues if your signature verification proves to be incorrect.&lt;/p&gt;

&lt;p&gt;It’s also important to plan how you’ll handle token expiration and revocation. Ensure that each token carries an expiration time that your service checks during its authorization procedure. If you need to immediately expire a set of tokens, you can rotate the private key that the server used to generate their signatures.&lt;/p&gt;

&lt;p&gt;Note that stateless does not mean no persistence at all — stateless in this context refers to not holding the state that’s relevant to a particular client. For more precise expiration controls, you can maintain a central index of issued tokens. When a client presents a token, retrieve the token ID from its payload and check there’s still a match in your index. This allows you to revoke tokens by deleting them from the index.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use HTTPS for Everything
&lt;/h3&gt;

&lt;p&gt;Any authorization data should be communicated over a TLS-protected connection. This helps prevent leaking of sensitive values such as passwords, authorization grants, and access tokens.&lt;/p&gt;

&lt;p&gt;Tokens such as JWTs aren’t encrypted by default — anyone can retrieve a payload by Base64 decoding the token. HTTPS mitigates the risk by preventing bad actors from eavesdropping on authorization activity, but in especially demanding situations, you might also want to encrypt sensitive payload fields for an additional layer of protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Select a centralized authorization server&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use a centralized authorization server to store authorization data such as users, roles, role assignments, and details of issued tokens. This permits you to make changes in one place and then immediately apply them across all your services.&lt;/p&gt;

&lt;p&gt;Choosing a decentralized approach can be attractive at first, but it tends to become less manageable over the life of your service. It forces you to maintain several authorization server instances and ensure stable synchronization between them. Problems can cause errors and discrepancies to occur.&lt;/p&gt;

&lt;p&gt;Centralized authorization eliminates these problems. Although it creates a single point of failure, you can mitigate against this by running multiple replicas of the authorization server to achieve high availability. The overall experience will be more reliable and easier to configure than decentralized systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build upon an established standard
&lt;/h3&gt;

&lt;p&gt;Frameworks such as OAuth and SAML are purposely designed to simplify and standardize authorization procedures. Using them as the basis of your stateless authorization implementation will reduce the risk of security oversights and improve interoperability with other services, such as identity providers.&lt;/p&gt;

&lt;p&gt;When you build your own authorization protocol from scratch, you’re responsible for defining how services and clients interact, the ways in which tokens are used, and how authorization is requested, validated, and granted. OAuth and SAML provide a reference for these high-level characteristics, allowing you to focus on building the app-specific authorization policies relevant to your users and resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Stateless services don’t persist any information between client sessions. They restore their state for each new session, using information provided by the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cerbos.dev/blog/the-future-is-stateless-its-time-to-ensure-your-security-is-as-scalable-as-your-business" rel="noopener noreferrer"&gt;&lt;strong&gt;Stateless architecture is particularly ideal&lt;/strong&gt;&lt;/a&gt; for authorization systems. The ease of scalability and absence of server-side synchronization logic allow you to develop decoupled authorization systems that are both reliable and simple to maintain. The resulting systems can be easily deployed to distributed environments, ready for use by multiple independent microservices.&lt;/p&gt;

&lt;p&gt;The next time you’re implementing authorization in your software projects, consider exploring &lt;a href="https://www.cerbos.dev/blog/the-stack-overflow-podcast-going-stateless-with-authorization-as-a-service" rel="noopener noreferrer"&gt;&lt;strong&gt;stateless authorization&lt;/strong&gt;&lt;/a&gt;. Using established stateless-compatible protocols such as OAuth 2.0 allows you to easily integrate with identity platforms and reduce the complexity in your apps.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>networking</category>
      <category>security</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Cerbos Hub: Simplifying Authorization for Developers</title>
      <dc:creator>Rohit Ghumare</dc:creator>
      <pubDate>Thu, 25 Jan 2024 19:08:13 +0000</pubDate>
      <link>https://forem.com/cerbos/cerbos-hub-simplifying-authorization-for-developers-4mbf</link>
      <guid>https://forem.com/cerbos/cerbos-hub-simplifying-authorization-for-developers-4mbf</guid>
      <description>&lt;h2&gt;
  
  
  Author, test &amp;amp; deploy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extend Policy Decision Point (PDP) with centralized authorization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We are excited to announce our public beta launch for Cerbos Hub as well as two new features to make the life of developers and teams simpler when it comes to managing their authorizations!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hub.cerbos.cloud/?_gl=1*k547e1*_ga*MTk1NjcwNzQ1MC4xNjY2Mjc5NjI2*_ga_8G3G3MS838*MTcwNjA5NzEyNi43NTUuMS4xNzA2MDk3MTI4LjU4LjAuMA.." rel="noopener noreferrer"&gt;Sign up for a free Cerbos Hub account&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💥 New feature #1
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Embeddable authorization policies via WebAssembly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cerbos Hub also provides an embeddable version of the policies that allow for taking authorization decisions on-device, at edge, and in environments where it is not possible to run a service.&lt;/p&gt;

&lt;p&gt;The Cerbos Hub CI/CD pipeline will produce bundles, keeping them in sync with your policies on every change.&lt;/p&gt;

&lt;p&gt;The access to be facilitated in applications will be via the Cerbos SDKs. And they handle auth checks without needing a roundtrip to the backend service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.cerbos.dev/cerbos-hub/decision-points-embedded" rel="noopener noreferrer"&gt;Check out the documentation for more&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💥 New feature #2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Write and test policies in the Cerbos Hub’s IDE Collaborative Playground&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For those who are familiar with Cerbos’ open source product, Cerbos PDP, the &lt;a href="http://cerbos.dev/features-benefits-and-use-cases/cerbos-playground" rel="noopener noreferrer"&gt;Cerbos Playground&lt;/a&gt; is going to be a familiar concept. &lt;/p&gt;

&lt;p&gt;It is the interactive space where users are able to write, test and simulate Cerbos policies in real-time.&lt;/p&gt;

&lt;p&gt;Cerbos Hub now has a full-featured collaborative IDE - Cerbos Hub Playground, to develop, iterate and test policy.&lt;/p&gt;

&lt;p&gt;It comes with instant feedback on changes, It comes with an automated test runner, it integrates into your git-based workflow, Play with the capabilities of Cerbos without any setup or installation with included sample policies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.cerbos.dev/cerbos-hub" rel="noopener noreferrer"&gt;Read the documentation for more&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cerbos Hub - &lt;a href="http://cerbos.dev/product-cerbos-hub" rel="noopener noreferrer"&gt;Start for free&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cerbos.dev/cerbos-hub" rel="noopener noreferrer"&gt;Cerbos Hub documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://community.cerbos.dev/?utm_source=hs_email&amp;amp;utm_medium=email&amp;amp;_hsenc=p2ANqtz--KU3vvp-ZXf1V9PJjln1SE8gjeJilKZScRAz_gD09b7Ez7TOCDjW_wdhgA5O0gxzuXQSkU" rel="noopener noreferrer"&gt;Slack Community &lt;/a&gt;to be in the know of latest developments&lt;/li&gt;
&lt;li&gt;Let us help build or review either your first policy. &lt;a href="https://go.cerbos.io/workshop?utm_source=hs_email&amp;amp;utm_medium=email&amp;amp;_hsenc=p2ANqtz--KU3vvp-ZXf1V9PJjln1SE8gjeJilKZScRAz_gD09b7Ez7TOCDjW_wdhgA5O0gxzuXQSkU" rel="noopener noreferrer"&gt;Book a 30-minute free workshop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cerbos PDP is &lt;a href="https://github.com/cerbos/cerbos?utm_source=hs_email&amp;amp;utm_medium=email&amp;amp;_hsenc=p2ANqtz--KU3vvp-ZXf1V9PJjln1SE8gjeJilKZScRAz_gD09b7Ez7TOCDjW_wdhgA5O0gxzuXQSkU" rel="noopener noreferrer"&gt;open source&lt;/a&gt;, feel free to browse or contribute and don't forget to drop a star ⭐️&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Nuxt authorization: How to implement fine-grained access control</title>
      <dc:creator>aldin</dc:creator>
      <pubDate>Mon, 15 Jan 2024 10:12:26 +0000</pubDate>
      <link>https://forem.com/cerbos/nuxt-authorization-how-to-implement-fine-grained-access-control-2c67</link>
      <guid>https://forem.com/cerbos/nuxt-authorization-how-to-implement-fine-grained-access-control-2c67</guid>
      <description>&lt;p&gt;In this tutorial you will learn how to use &lt;a href="https://cerbos.dev/" rel="noopener noreferrer"&gt;Cerbos&lt;/a&gt; to add fine-grained access control to any &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt; web application, simplifying authorization as a result.&lt;/p&gt;

&lt;p&gt;Check out a working example of a Cerbos integration in a Nuxt application on &lt;a href="https://github.com/cerbos/nuxtjs3-cerbos-iron-session" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A working &lt;a href="https://nuxt.com/docs/getting-started/introduction" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt; web application&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; installed in your working environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;Having met the prerequisites, the steps are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up the Cerbos policy repository&lt;/li&gt;
&lt;li&gt;Set up the Cerbos PDP&lt;/li&gt;
&lt;li&gt;Add the Cerbos client to your Nuxt application&lt;/li&gt;
&lt;li&gt;Create an API route&lt;/li&gt;
&lt;li&gt;Make permission checks across your Nuxt pages and components&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up the Cerbos policy repository
&lt;/h2&gt;

&lt;p&gt;A Cerbos policy repository is a collection of YAML files that define access control rules for your application. It's essential for specifying who can do what within your app. These policies dictate the actions different user roles can perform on various resources. &lt;/p&gt;

&lt;p&gt;A resource is an application-specific concept that applies to anything that requires access rules. For example, a document is a resource that can be altered, viewed, deleted, etc. by different users depending on the access control rules. Read more about the best practices for structuring your policy repository in our &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/best_practices.html#_policy_repository_layout" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your Cerbos policy repository can be stored on your disk, on git, or any S3-compatible storage system. To set up a Cerbos policy repository on the disk, within the Nuxt application, do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your project's root, create a &lt;code&gt;cerbos&lt;/code&gt; folder, then a &lt;code&gt;policies&lt;/code&gt; sub-folder within it.&lt;/li&gt;
&lt;li&gt;Within the &lt;code&gt;policies&lt;/code&gt; folder, create a YAML file which will contain the rules for performing permission checks in your Nuxt application. For example, create a &lt;code&gt;documents.yaml&lt;/code&gt; resource policy file.&lt;/li&gt;
&lt;li&gt;Populate the &lt;code&gt;documents.yaml&lt;/code&gt; file with rules for actions that can be performed on a document, check the example below. Learn more in Cerbos &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/resource_policies" rel="noopener noreferrer"&gt;resource policies documentation&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.cerbos.dev/v1&lt;/span&gt;
&lt;span class="na"&gt;resourcePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;document&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;view'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;change'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destroy'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EFFECT_ALLOW&lt;/span&gt;
      &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;view'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;change'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EFFECT_ALLOW&lt;/span&gt;
      &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
      &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;request.resource.attr.author == request.principal.id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ve defined a simple resource policy file &lt;code&gt;documents.yaml&lt;/code&gt; which allows admin users to &lt;code&gt;view&lt;/code&gt;, &lt;code&gt;change&lt;/code&gt;, and &lt;code&gt;destroy&lt;/code&gt; any &lt;code&gt;document&lt;/code&gt; resource within the system. Non-admin users are allowed to &lt;code&gt;view&lt;/code&gt; and &lt;code&gt;change&lt;/code&gt; the &lt;code&gt;document&lt;/code&gt; resource if the condition is matched that the given user is also the document author.&lt;/p&gt;

&lt;p&gt;Note that a separate policy file is expected for different types of resources and principals we want to create policies about. To showcase this, in the linked demo &lt;a href="https://github.com/cerbos/nuxtjs3-cerbos-iron-session" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;example there is a &lt;code&gt;contacts.yaml&lt;/code&gt; resource policy file alongside the &lt;code&gt;documents.yaml&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;Cerbos policy repository can be further enriched with defining &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/derived_roles" rel="noopener noreferrer"&gt;context-aware roles&lt;/a&gt;, &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/schemas" rel="noopener noreferrer"&gt;schemas&lt;/a&gt;, &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/scoped_policies" rel="noopener noreferrer"&gt;scopes&lt;/a&gt;, &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/compile" rel="noopener noreferrer"&gt;tests&lt;/a&gt;, and various other features explained in comprehensive &lt;a href="https://docs.cerbos.dev/cerbos/latest/policies/" rel="noopener noreferrer"&gt;Cerbos documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the Cerbos PDP
&lt;/h2&gt;

&lt;p&gt;Cerbos PDP is the Policy Decision Point, a component that evaluates application requests against authZ policies to make access decisions; determining whether a user action on a resource is allowed.&lt;/p&gt;

&lt;p&gt;In this demo, we’ll set a Cerbos PDP within your repository, as a separate module, using the previously created &lt;code&gt;cerbos&lt;/code&gt; directory. To run Cerbos PDP locally, do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Cerbos PDP server configuration file within &lt;code&gt;cerbos&lt;/code&gt; directory. You can name it &lt;code&gt;conf.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For simplest configuration, within the &lt;code&gt;conf.yaml&lt;/code&gt; file define the port exposed for listening to HTTP (and/or gRPC) requests and the location of the Cerbos policy repository. The simplest &lt;code&gt;conf.yaml&lt;/code&gt; file would look like the one shown below:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpListenAddr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:3592"&lt;/span&gt;
&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;disk"&lt;/span&gt;
  &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/policies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more robust configuration, make sure to check our &lt;a href="https://docs.cerbos.dev/cerbos/latest/configuration/" rel="noopener noreferrer"&gt;Cerbos PDP configuration documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your file Cerbos-related file structure now might look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── cerbos
│   └── policies
│       ├── documents.yaml
│       └── contacts.yaml
└── conf.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Position your terminal within the &lt;code&gt;cerbos&lt;/code&gt; directory. If you have Docker installed, you can simply run the following command to start Cerbos PDP locally in a Docker container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; cerbos &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/policies:/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 3592:3592 &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/cerbos/cerbos:latest server
  &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;conf.yaml 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cerbos PDP runs as a separate process from your Nuxt application. Here, we ran it as a standalone service within a docker container, but this is not a requirement. Cerbos is designed to be adaptable to your infrastructure. So if you want to run Cerbos PDP as a service, a sidecar, or a lambda function, for instance, check the Cerbos deployment documentation to learn more about Cerbos &lt;a href="https://docs.cerbos.dev/cerbos/latest/deployment/" rel="noopener noreferrer"&gt;deployment patterns&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the Cerbos client to your Nuxt application
&lt;/h2&gt;

&lt;p&gt;Adding a Cerbos client is essential for simplifying the communication between your Nuxt application and the Cerbos PDP. The Client will allow you to make user permission checks from your Nuxt application in an elegant manner.&lt;/p&gt;

&lt;p&gt;To add the Cerbos client to your Nuxt application, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Cerbos client you want to use.

&lt;ul&gt;
&lt;li&gt;Choose between &lt;code&gt;@cerbos/http&lt;/code&gt; for HTTP interactions or &lt;code&gt;@cerbos/grpc&lt;/code&gt; for gRPC in server-side applications.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Install the chosen client package using the &lt;code&gt;npm install&lt;/code&gt; command&lt;/li&gt;

&lt;li&gt;In your Nuxt project, within the &lt;code&gt;utils&lt;/code&gt; folder, create a utility file &lt;code&gt;cerbos.ts&lt;/code&gt; to instantiate the Cerbos client.&lt;/li&gt;

&lt;li&gt;Export the instance for reuse across your Nuxt application.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The above mentioned &lt;code&gt;cerbos.ts&lt;/code&gt; file would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Cerbos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@cerbos/http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Cerbos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost:3592&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create an API route
&lt;/h2&gt;

&lt;p&gt;A Nuxt API route is a feature in Nuxt.js used to define server-side logic and handle HTTP requests within the Nuxt application. These routes allow developers to create various back-end functionalities in the Nuxt project, such as data fetching, form submissions, or in this case authorization.&lt;/p&gt;

&lt;p&gt;To create an API route in Nuxt for Cerbos permission checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an &lt;code&gt;isAllowed.ts&lt;/code&gt; file within the &lt;code&gt;server/api&lt;/code&gt; folder of your Nuxt application.&lt;/li&gt;
&lt;li&gt;Define and export the event handler

&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;isAllowed.ts&lt;/code&gt; file, use &lt;code&gt;defineEventHandler&lt;/code&gt; from &lt;code&gt;nuxt-helpers&lt;/code&gt; to export your API handling function.&lt;/li&gt;
&lt;li&gt;Within this function, call the Cerbos &lt;code&gt;.isAllowed(...)&lt;/code&gt; method to check user permissions based on the request's user and resource details.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../utils/cerbos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Pull the user info from the session in your Nuxt applications&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;000012345&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentId&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Pull the resource info from the data storage in your Nuxt applications. Pass Resource ID within the event as a query param, like we did here.&lt;/span&gt;
          &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;000012347&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;approve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;    

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAllowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cerbos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! You can now universally call this API as &lt;code&gt;/api/isAllowed&lt;/code&gt; across your Nuxt application pages and components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make permission checks across your Nuxt pages and components
&lt;/h2&gt;

&lt;p&gt;Let’s see the usage of Cerbos permission checks across your Nuxt application pages in action. Let’s say we’ve created a page for each of our documents on the path &lt;code&gt;/documents/[id]&lt;/code&gt;. To do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create  a &lt;code&gt;documents&lt;/code&gt; folder under the &lt;code&gt;pages&lt;/code&gt; folder of your application.&lt;/li&gt;
&lt;li&gt;Within the &lt;code&gt;documents&lt;/code&gt; folder, create an &lt;code&gt;[id].vue&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nuxt offers route validation via the &lt;code&gt;validate&lt;/code&gt; property in &lt;code&gt;definePageMeta()&lt;/code&gt; in each page you wish to validate. The &lt;code&gt;validate&lt;/code&gt; property accepts the route as an argument. &lt;/p&gt;

&lt;p&gt;To use the &lt;code&gt;/api/isAllowed&lt;/code&gt; route defined in the previous step you can add the following snippet to the bottom of your recently created &lt;code&gt;[id].vue&lt;/code&gt; (or any other vue) file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;definePageMeta&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isAllowed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/isAllowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;useRequestHeaders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;documentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s that simple!&lt;/p&gt;

&lt;h2&gt;
  
  
  To sum up
&lt;/h2&gt;

&lt;p&gt;All you have to do to use Cerbos authorization in your Nuxt application is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create Cerbos policies you will be using to make decisions over who should be able to do what within your application,&lt;/li&gt;
&lt;li&gt;run a Cerbos PDP which upon being called will be checking those policies,&lt;/li&gt;
&lt;li&gt;install the Cerbos client within your Nuxt application,&lt;/li&gt;
&lt;li&gt;create an API route to enable its usage across your Nuxt application,&lt;/li&gt;
&lt;li&gt;start invoking the exported API route to perform Cerbos &lt;code&gt;.isAllowed(...)&lt;/code&gt; checks and determine whether your application user should be allowed to make a certain action on a certain resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further steps
&lt;/h2&gt;

&lt;p&gt;In this tutorial you saw how to add fine-grained access control with Cerbos to your Nuxt applications. If you liked it make sure to check out &lt;a href="https://hub.cerbos.cloud/" rel="noopener noreferrer"&gt;Cerbos Hub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cerbos Hub saves time managing and synchronizing every Cerbos PDP and policy repository across all your applications and services. It helps connect your Cerbos policy repository and your Cerbos PDP instances and manage them collaboratively and smoothly from a single place.&lt;/p&gt;

&lt;p&gt;We also published a series of articles with step-by-step instructions on how to &lt;a href="https://cerbos.dev/blog/get-started-with-cerbos-hub" rel="noopener noreferrer"&gt;Get started with Cerbos Hub&lt;/a&gt;. Take a look if you’re interested in seeing how it works!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>nuxt</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Managing Access Control Policies and PDPs with Cerbos Hub</title>
      <dc:creator>aldin</dc:creator>
      <pubDate>Thu, 21 Dec 2023 15:58:04 +0000</pubDate>
      <link>https://forem.com/cerbos/managing-access-control-policies-and-pdps-with-cerbos-hub-39o3</link>
      <guid>https://forem.com/cerbos/managing-access-control-policies-and-pdps-with-cerbos-hub-39o3</guid>
      <description>&lt;p&gt;Previously we published the &lt;a href="https://cerbos.dev/blog/get-started-with-cerbos-hub" rel="noopener noreferrer"&gt;Get started with Cerbos Hub&lt;/a&gt; article where we covered the basics of setting up Cerbos Hub with your policy repository and Cerbos PDP. Then we published the article &lt;a href="https://cerbos.dev/blog/authorize-on-the-edge-with-cerbos-hub-and-embedded-pdp-bundles" rel="noopener noreferrer"&gt;Authorize on the edge with Cerbos Hub and Embedded PDP bundles&lt;/a&gt; where we explored how Embedded PDPs can be utilized within Cerbos Hub to streamline and optimize authorization at the edge. Expanding on that, this post focuses on how to manage your access rules efficiently with Cerbos Hub.&lt;/p&gt;

&lt;p&gt;Cerbos Hub streamlines the process of synchronizing access control rules across your apps and services. The tool facilitates collaboration and quick adaptation to changes in app requirements, making the management of access control simpler and more efficient.&lt;/p&gt;

&lt;p&gt;In this piece, we’ll walk through a common use case; a simple SaaS application, CerbFinance, with multiple user roles and permissions. And you’ll see how Cerbos Hub manages the changes in policy definitions, making the changes available in the application in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial Setup
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, make sure to set up the Cerbos Hub and connect the Cerbos PDP to the Hub. Fork the demo repository &lt;a href="https://github.com/cerbos/cerbos-hub-showcase" rel="noopener noreferrer"&gt;https://github.com/cerbos/cerbos-hub-showcase&lt;/a&gt;, check the &lt;code&gt;README&lt;/code&gt;, then follow the instructions in the Introduction to Cerbos Hub, with a &lt;strong&gt;single exception&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Instead of pasting the workspace and client credentials in the configuration yaml file, there is a &lt;code&gt;.env.example&lt;/code&gt; file under the &lt;code&gt;infra/docker/&lt;/code&gt; path of the forked project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhvdck5nsy0fnglii802.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhvdck5nsy0fnglii802.png" alt="Preview of .env.example" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy that file and rename it to &lt;code&gt;.env&lt;/code&gt; on the same path and paste the values of client ID, client secret, and &lt;code&gt;workspace secret&lt;/code&gt; fields.&lt;/p&gt;

&lt;p&gt;To get the WASM bundle URL, go to the &lt;code&gt;Decision points&lt;/code&gt; page in the sidebar, and select the &lt;code&gt;Embedded&lt;/code&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feasqpxvwhmev8fp8vagm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feasqpxvwhmev8fp8vagm.png" alt="Cerbos Hub Decision Points Bundle URL" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the Bundle URL and paste it to your &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswfifzsf5vkt3msgfako.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswfifzsf5vkt3msgfako.png" alt="Preview of .env" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start the application run the &lt;code&gt;make start&lt;/code&gt; command in your terminal.&lt;/p&gt;

&lt;p&gt;For full instructions on how to deal with Embedded PDPs, read the &lt;a href="http://blob.blob/" rel="noopener noreferrer"&gt;Authorize on the edge with Cerbos Hub and Embedded PDP bundles&lt;/a&gt; article.&lt;/p&gt;

&lt;h2&gt;
  
  
  How policies are defined
&lt;/h2&gt;

&lt;p&gt;Our example application is an expense tracking system, in which a user named Frank, a member of the finance team, can view certain sections of the application and perform specific actions, while Finance Managers, and admins have broader access. For this use case, we’ll showcase a dynamic RBAC (role-based-access control) model, where levels of access for users (such as restricting approval rights for expenses) vary depending on the expense status and amount, as well as the user placement in the company hierarchy.&lt;/p&gt;

&lt;p&gt;The given SaaS application example shows how Cerbos Hub manages the policy update orchestration for an "expense" resource. The policy defines that: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finance managers can approve any open expense unless they own the expense.&lt;/li&gt;
&lt;li&gt;Team members have a monetary cap on what they can approve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our CerbFinance demo application, there is a “View as” dropdown in the top right corner where we can switch between users. We’ll go back and forth between the Finance Manager and the team member roles as we go through this tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49wfim4gsnw7wp51nd9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49wfim4gsnw7wp51nd9b.png" alt="Cerb Finance Expenses Preview" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To understand who should be able to do what, we print the roles, departments, and region of the selected user just to the left of the dropdown itself. We have currently selected Derek. Derek is a Finance Manager of the EMEA region, and he is Frank’s supervisor.&lt;/p&gt;

&lt;p&gt;The policies definitions we set for this demo dictate that Finance team members are not allowed to do certain things that Finance Managers can do, such as: approve any expenses with an amount higher than $10,000.&lt;/p&gt;

&lt;p&gt;Here is a snippet extracted from the policy definitions stating exactly that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nwc4fhm7hmgrx1c3kfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nwc4fhm7hmgrx1c3kfo.png" alt="Policy repository expenses preview" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That means that Frank, our finance team member, can only approve expenses less than $10,000. For anything higher than that, a finance manager would need to be involved.&lt;/p&gt;

&lt;p&gt;On the front end, what we see on the screenshot below is a list of expenses, alongside basic information such as who submitted the expense, when, the expense amount, the vendor, and the status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo10tuo1sk55bftuayq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo10tuo1sk55bftuayq0.png" alt="Cerb Finance Expenses Preview" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The far right column shows a &lt;code&gt;Details&lt;/code&gt; button, which when opened shows us a modal with information on the expense. Actions that can be made against the expense appear as buttons at the bottom, which are colored if they are enabled and gray if they are not. This expense report was submitted by Sally, a sales manager at CerbFinance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nqp3fz8870l29i53ynw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nqp3fz8870l29i53ynw.png" alt="Manager checking expense item" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Derek, all the actions except for ‘Edit’ are enabled. The second we switch to Frank, things change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4p4smuuhtxmi62in3as.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4p4smuuhtxmi62in3as.png" alt="Team Member checking expense" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because this expense is higher than $10,000, Frank does not have any of the action buttons enabled for him. Within our demo application, Frank (as anyone else) has specific permissions - he can enter certain areas and do particular tasks. But what if we decide to change these permissions?&lt;/p&gt;

&lt;h2&gt;
  
  
  Making changes to Policies
&lt;/h2&gt;

&lt;p&gt;Take an instance where the company raises the limit for expense approvals by team members from $10,000 to $20,000.  We start by making that change in the policy repository. Go to line 85 of &lt;code&gt;resource_expense.yaml&lt;/code&gt; file located on &lt;code&gt;/cerbos/policies/&lt;/code&gt;path, and replace the amount value 10000 with 20000. Save and push the change to the policy repository.&lt;/p&gt;

&lt;p&gt;The second the update is made, Cerbos Hub starts an automated sequence of actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9c98hfjf9jtg5pc0zkne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9c98hfjf9jtg5pc0zkne.png" alt="Policy repository update amount cap" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It kicks off the CI/CD pipeline to update the policies, runs tests to check for errors, and once it's all clear, sends out the updated policy across the system.&lt;/p&gt;

&lt;p&gt;If any of the tests fail, the build will fail as well, and Cerbos Hub doesn’t send any changes to our Cerbos PDP instances. And we can see the failed tests on the &lt;code&gt;Builds&lt;/code&gt; page of our Cerbos Hub workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9iuonx26dfo2krsgmphq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9iuonx26dfo2krsgmphq.png" alt="Cerbos Hub failed build" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the commit hash in the far left column. A new page will open, showing the exact test that failed and the details of the failure. In this case it failed because even though we made a policy change to enable finance team members to approve expenses up to the amount of $20,000, the test data is unchanged and still expects a failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vpfuihurebjb3hyh7ro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vpfuihurebjb3hyh7ro.png" alt="Cerbos Hub build details" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As it was an intended change, let’s update our tests so they reflect the newly expected behavior, and allow finance team members to approve expenses up to $20,000.&lt;/p&gt;

&lt;p&gt;Cerbos Hub also lets us directly edit either the github commit or the commit file that caused the build to fail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F064j7drnrcjucy4q5e5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F064j7drnrcjucy4q5e5k.png" alt="Cerbos Hub build actions" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The quickest way to go around it is to go to the &lt;code&gt;expenses_test.yaml&lt;/code&gt; file, and find line 240, where it defines the expected results for a finance_team principal approving an expense over $10,000. Replace &lt;code&gt;EFFECT_DENY&lt;/code&gt; with &lt;code&gt;EFFECT_ALLOW&lt;/code&gt; and push the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hkhm5jlwjtyxhdh0otf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hkhm5jlwjtyxhdh0otf.png" alt="Policy test comparison preview" width="800" height="848"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cerbos Hub again starts the CI/CD pipeline to update the policies. And with tests successfully passing this time, it notifies all Cerbos PDP instances of the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pqwqy86np4zpnv6po0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pqwqy86np4zpnv6po0t.png" alt="Cerbos Hub build succeeded" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Decision points page, we can see that the PDP instance is running with the newly built bundle. We confirm this by noting that the latest successfully built commit hash is identical to the bundle hash.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86s9jpifk440mrnmhfqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86s9jpifk440mrnmhfqy.png" alt="Cerbos Hub Decision Points preview" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going back to the front end, you can see that Frank’s view shows the approve/reject actions enabled for Sally’s expense report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqu8nruryzlzcxcw7d3z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqu8nruryzlzcxcw7d3z.png" alt="Team Member expense preview" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;We’ve updated policies in real time. All we had to do is change the policy in our policy repository and make sure that the tests are passing. Cerbos Hub, upon successful build, notifies the Cerbos PDP instances of the change, now allowing Frank to approve the expenses with an amount set to up to $20,000.&lt;/p&gt;

&lt;p&gt;This system-wide update happens smoothly, without stopping services or manual updates, ensuring the CerbFinance application keeps running without a hitch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Beta
&lt;/h2&gt;

&lt;p&gt;Cerbos has launched Cerbos Hub to provide a robust, dynamic, and automated authorization management system. In the provided demo, we witness how effortlessly policies can be updated and enforced in a SaaS application, reflecting changes in real-time without any downtime or deployment hassle.&lt;/p&gt;

&lt;p&gt;The Cerbos PDP ensures that authorization logic is transparent, version-controlled, and easy to manage. Cerbos Hub's managed service extends this power, seamlessly integrating with development workflows, providing real-time updates, and ensuring that authorization decisions are made efficiently everywhere, even at the edge.&lt;/p&gt;

&lt;p&gt;If you haven't already, &lt;a href="https://hub.cerbos.cloud" rel="noopener noreferrer"&gt;join the beta&lt;/a&gt; now and save months of developing access control in-house.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
