<?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>DEV Community: Ege Aytin</title>
    <description>The latest articles on DEV Community by Ege Aytin (@egeaytin).</description>
    <link>https://dev.to/egeaytin</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%2Fuser%2Fprofile_image%2F922857%2F1957dc3e-c85f-4603-9e8a-ae41a7e69961.jpeg</url>
      <title>DEV Community: Ege Aytin</title>
      <link>https://dev.to/egeaytin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/egeaytin"/>
    <language>en</language>
    <item>
      <title>What is SCIM Provisioning: In-Depth Guide [2024]</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Tue, 29 Oct 2024 11:08:50 +0000</pubDate>
      <link>https://dev.to/permify/what-is-scim-provisioning-in-depth-guide-2024-1c0i</link>
      <guid>https://dev.to/permify/what-is-scim-provisioning-in-depth-guide-2024-1c0i</guid>
      <description>&lt;p&gt;The ability to outsource and automate repetitive daily tasks is at the core of why SCIM provisioning exists.&lt;/p&gt;

&lt;p&gt;In the case of large and medium scale enterprises, when an employee joins a new company for example, they usually require access to all of the necessary tools needed to perform their duties. &lt;/p&gt;

&lt;p&gt;This then means that new accounts have to be created with all the right user privileges and packages. &lt;/p&gt;

&lt;p&gt;We could flashback to the pandemic when everyone practically went remote and we had to rely on a bunch of software tools to stay productive at work.&lt;/p&gt;

&lt;p&gt;Even now, employees of large and medium firms still rely on several different cloud based apps to carry out their daily jobs. &lt;/p&gt;

&lt;p&gt;However, we can imagine that when dealing with thousands of users spanning several different cloud based user accounts, this repetitive cycle of handling new cloud identities can easily get complex and untidy if not properly automated. Besides, it could create footprints for security attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is SCIM provisioning?
&lt;/h3&gt;

&lt;p&gt;One effective way to solve this problem of creating many different user accounts per need is through SCIM provisioning. SCIM provisioning involves setting up an automated workflow that caters to the following needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assigning new user accounts or provisioning users&lt;/li&gt;
&lt;li&gt;Updating roles and access levels as needed&lt;/li&gt;
&lt;li&gt;Safely removing user identites when they are no longer in use, also known as de-provisioning users.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The System for Cross-domain Identity Management(SCIM) is an open web standard that serves this purpose of providing a way to easily authenticate users of your app across third party services.&lt;/p&gt;

&lt;h3&gt;
  
  
  How SCIM Works
&lt;/h3&gt;

&lt;p&gt;The SCIM server is a made up of restful API with available endpoints. Information is exchanged over a secure communication protocol. The SCIM client is expected to make a HTTP request call to the server and receive a matching response.&lt;/p&gt;

&lt;p&gt;By providing a standardized API and data model, SCIM makes automated user provisioning, de-provisioning and management possible across various clouds apps.&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%2Fde7i511r7pl0k8xqi60p.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%2Fde7i511r7pl0k8xqi60p.png" alt="how-SCIM" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's throw more light into the illustration above. We usually have &lt;strong&gt;3 key players&lt;/strong&gt; involved in the workflow of creating user accounts (otherwise called provisioning) using SCIM standard: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the SCIM Client which is the Identity Service Provider (IdP)&lt;/li&gt;
&lt;li&gt;the SCIM service provider &lt;/li&gt;
&lt;li&gt;and the cloud apps. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The IdP which has a record of the organizations' user identities initiates requests to the SCIM service provider. Next, the SCIM service provider makes the appropriate changes automatically to &lt;strong&gt;all&lt;/strong&gt; the connected cloud applications.&lt;/p&gt;

&lt;p&gt;SCIM defines resources such as &lt;code&gt;User,&lt;/code&gt; &lt;code&gt;Group,&lt;/code&gt; and &lt;code&gt;ServiceProviderConfig&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each of these resources we just mentioned come with a set of attributes. For example, a &lt;code&gt;User&lt;/code&gt; resource includes attributes like &lt;code&gt;userName,&lt;/code&gt; &lt;code&gt;emails,&lt;/code&gt; &lt;code&gt;displayName,&lt;/code&gt; &lt;code&gt;name.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can also extend the schema contents to include attributes that are specific to our own usecases so it doesn't have to be fixed.&lt;/p&gt;

&lt;p&gt;Now, let's have a look at some of the common API operations that can be performed on the SCIM server: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Create:&lt;/code&gt; This operation provisions new user and makes a record of their identity on the SCIM data store.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Read:&lt;/code&gt; The &lt;code&gt;read&lt;/code&gt; operation fetches user identities from the data store.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Update:&lt;/code&gt; This make changes to the user identities e.g user changing roles when an employee is promoted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Delete:&lt;/code&gt; The &lt;code&gt;delete&lt;/code&gt; operation removes existing resource types from the SCIM data store e.g deleting employee records.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How to implement a custom SCIM Server?
&lt;/h3&gt;

&lt;p&gt;Since SCIM is an open standard, it means we can build our own SCIM server customized to suit specific needs. Once the fundamental ingredients as defined in the specification documents are fulfilled, implementing your customized SCIM server is achievable. &lt;/p&gt;

&lt;p&gt;Here is a general overview of the steps to implement your custom SCIM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand the SCIM standard and RFCs&lt;/li&gt;
&lt;li&gt;Define your organizational specific requirements identifying which user and group management functionalities you need&lt;/li&gt;
&lt;li&gt;Select the technology stack to build your own SCIM variant ensuring it supports Restful API and secure communication protocols&lt;/li&gt;
&lt;li&gt;Design your data model making sure it is in line with SCIM's core resource type which are: &lt;code&gt;Users&lt;/code&gt; and &lt;code&gt;Group&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Next, implement the core SCIM endpoints based on the specifications. &lt;/li&gt;
&lt;li&gt;Implement security. Ensure authentication workflow is secured with OAuth or other means and all exchanges are conducted on HTTPS.&lt;/li&gt;
&lt;li&gt;Develop error handling and logging. &lt;/li&gt;
&lt;li&gt;Test and proper documentation&lt;/li&gt;
&lt;li&gt;Deployment, monitoring and scalability&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A minor slack in this custom implementation might open up a window for security mishaps. Thus, most efficient developer teams usually opt for outsourcing this crucial part of the piece.&lt;/p&gt;

&lt;p&gt;In the following sections, we will talk in more details about using a third party SCIM services and everything you need to know to make the right choice. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to Evaluate SCIM providers?
&lt;/h3&gt;

&lt;p&gt;What truly makes the difference is a SCIM provider that fulfills your organizational needs to a considerably large extent.  Of course, jumping on just about any shiny new product in the market is not advisable. &lt;/p&gt;

&lt;p&gt;Therefore, in this part, we shall talk about the important features you need to look out for when weighing and eventually selecting a SCIM provider to go with.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key features to look for in SCIM providers
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility with existing systems:&lt;/strong&gt; You'll want to look out for a provider that makes it easier to plug into your existing company software without breaking it. This ensures to get SCIM up and running without delays.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of integration and deployment:&lt;/strong&gt; A simplified integration process reduces downtime. This is especially important in a business environment where swift deployment provides a competitive advantage. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security features and compliance&lt;/strong&gt; : When selecting a SCIM provider, it is essential to ensure they offer robust security features and are compliant with relevant industry standards and regulations such as GDPR and HIPAA  Compliance to name a few. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability and performance&lt;/strong&gt;: Consider a SCIM provider that can meet the growing needs of your organization or user base. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customer support and documentation:&lt;/strong&gt; Timely customer support and well crafted documentation is an indication that the SCIM provider is reliable and ready to assist. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Factors influencing the choice of a SCIM provider
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Company size and requirements:&lt;/strong&gt; A small startup would need to provision less user accounts compared to a medium or large enterprise. So, it's important to pick a SCIM provider with a cost effective package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Budget and pricing considerations:&lt;/strong&gt; The allocated amount a company plans to spend on SCIM resources needs to work with the pricing of the chosen SCIM provider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specific use cases and industry needs&lt;/strong&gt;: It's essential to align the features offered by the SCIM provider with your specific industry to know if it can effectively support your organization's identity management requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What are the Top SCIM Providers?
&lt;/h3&gt;

&lt;p&gt;In this section will expand even more into what options exists. &lt;/p&gt;

&lt;p&gt;As we take a closer look at the &lt;strong&gt;&lt;em&gt;top 5 SCIM providers in the market for 2024,&lt;/em&gt;&lt;/strong&gt; it will help to bear in mind your pressing organizational needs with matching how each provider might possibly fit.  &lt;/p&gt;

&lt;p&gt;Provider 1.  &lt;strong&gt;Okta&lt;/strong&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%2Fxuegu3l230jfdwqn1yso.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%2Fxuegu3l230jfdwqn1yso.png" alt="okta" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.okta.com/" rel="noopener noreferrer"&gt;Okta&lt;/a&gt; can be described as an all-in-one identity solution. Users are provisioned using SCIM through the Okta Lifecycle Management (LCM). This ensures that &lt;a href="https://help.okta.com/oie/en-us/content/topics/provisioning/lcm/lcm-provisioning-workflow.htm" rel="noopener noreferrer"&gt;events are triggered at each point&lt;/a&gt; whenever any user changes occurs, such as joining or leaving your organization.   &lt;/p&gt;

&lt;p&gt;Key Features of Okta&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Comprehensive identity and access management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrates with a wide range of applications and services allowing for seamless connectivity across different IT environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advanced security features like adaptive multi-factor authentication (MFA) and threat insights.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lifecycle management to facilitate automatic user provisioning and ensures that data is quickly synchronized as users' come in or leave the organization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A centralized directory for managing all your user profiles in one place.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong emphasis on security and compliance.&lt;/li&gt;
&lt;li&gt;Scalable solution suitable for enterprises of all sizes.&lt;/li&gt;
&lt;li&gt;User-friendly interface and extensive support resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher cost compared to some competitors.&lt;/li&gt;
&lt;li&gt;Complex setup which might require some technical know-how.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pricing&lt;br&gt;
Okta’s pricing varies based on the specific modules and services used. Basic plans for single sign-on (SSO) start around $2 per user per month, with advanced features and enterprise packages costing significantly more.&lt;/p&gt;

&lt;p&gt;Provider 2.  &lt;strong&gt;WorkOS&lt;/strong&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%2F8gxromr83uxxmrjuwmpz.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%2F8gxromr83uxxmrjuwmpz.png" alt="workos" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://workos.com/" rel="noopener noreferrer"&gt;WorkOS&lt;/a&gt; aims to provide enterprise-grade identity management solutions for your app to help you ship without needing extensive resources or time. It includes a &lt;a href="https://workos.com/docs/directory-sync" rel="noopener noreferrer"&gt;Directory Sync&lt;/a&gt; to help you &lt;em&gt;'build a frictionless user provisioning and deprovisioning workflow for your organization.'&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Key Features of WorkOS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Developer-centric with robust APIs and SDKs for backend technologies such as PHP, Python, NodeJS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time event streaming for provisioning events which gives a better way to update data compared to using webhooks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A customizable user interface for authentication that supports various authentication types, making it easier for developers to implement secure login flows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Directory Sync for user lifecycle management by syncing with corporate directories like Google Workspace, Azure AD, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Audit logs to maintain regulatory requirements and security standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy integration with major identity providers (IdPs) and Human Resources Information System (HRIs).&lt;/li&gt;
&lt;li&gt;Flat-rate pricing simplifies budgeting.&lt;/li&gt;
&lt;li&gt;Excellent documentation and developer support via Slack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flat-rate pricing may not be cost-effective for smaller organizations.&lt;/li&gt;
&lt;li&gt;Limited to the features included in their predefined plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pricing&lt;br&gt;
WorkOS charges $125 per company per month for its SCIM Directory Sync, with discounts for bulk purchases. Custom enterprise plans are also available with additional support and SLAs.&lt;/p&gt;

&lt;p&gt;Provider 3.  &lt;strong&gt;Frontegg&lt;/strong&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%2Feu17gpgeoydptyc53qzr.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%2Feu17gpgeoydptyc53qzr.png" alt="frontegg" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image credit: Frontegg&lt;/p&gt;

&lt;p&gt;&lt;a href="https://frontegg.com/" rel="noopener noreferrer"&gt;Frontegg&lt;/a&gt; is built with the goal of modernizing user management for B2B Saas organizations. As shown in the screenshot above, via the admin portal in the dashboard, you can easily set up SCIM provisioning, connect your identity provider and sync data.  &lt;/p&gt;

&lt;p&gt;Key Features of Frontegg&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Full suite of authentication services, including SCIM provisioning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advanced security features like behavioral analytics, bot detection, robust encryption and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customizable admin portal where users can manage their profiles, team memberships, roles, and permissions. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports a variety of front-end frameworks (React, Angular, Vue, etc.) and provides robust SDKs and APIs for easy integration and customization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offers tenant settings, entitlements, fine-grained authorization, and multi-tenancy management, making it suitable for complex organizational structures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong security features tailored for large tech companies.&lt;/li&gt;
&lt;li&gt;Supports a wide range of IdPs.&lt;/li&gt;
&lt;li&gt;Self-service configuration through an admin portal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;May require significant setup knowledge for full utilization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pricing&lt;br&gt;
Frontegg’s pricing is primarily based on Monthly Active Users (&lt;strong&gt;MAU&lt;/strong&gt;). Specific pricing details are available upon contacting their sales team, making it less transparent compared to competitors like WorkOS.&lt;/p&gt;

&lt;p&gt;Provider 4.  &lt;strong&gt;Stytch&lt;/strong&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%2Fs06zk52xxv3uu4zijt17.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%2Fs06zk52xxv3uu4zijt17.png" alt="stytch" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stytch.com" rel="noopener noreferrer"&gt;Stytch&lt;/a&gt; offers SCIM provisioning as part of its B2B authentication suite. It facilitates user identity management by providing the relevant SCIM APIs, integrating with the IdP and effecting user changes using webhooks.&lt;/p&gt;

&lt;p&gt;Key Features of Stytch&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Focus on modern authentication methods like passkeys and biometric auth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stytch supports SCIM integration with popular IdPs such as Okta. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users can enable SCIM provisioning for their existing SAML applications by configuring SCIM connections through the Stytch dashboard or API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lightweight and easy-to-integrate solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implements fine-grained access controls, allowing organizations to define roles and permissions at an organizational level.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost-effective for basic SCIM provisioning needs.&lt;/li&gt;
&lt;li&gt;Quick and straightforward integration.&lt;/li&gt;
&lt;li&gt;A good fit for startups and smaller businesses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less feature-rich compared to other providers.&lt;/li&gt;
&lt;li&gt;Limited support for large-scale enterprise needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pricing&lt;br&gt;
Stytch offers competitive pricing based on MAU, with plans starting at $0.05 per active user per month. They provide a transparent pricing model with additional features available at higher tiers.&lt;/p&gt;

&lt;p&gt;Provider 5.  &lt;strong&gt;OneLogin&lt;/strong&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%2Fhdb19v9wiawp7npeet4s.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%2Fhdb19v9wiawp7npeet4s.png" alt="onelogin" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.onelogin.com/" rel="noopener noreferrer"&gt;OneLogin&lt;/a&gt; aims to provide a trusted experience platform with secure, scalable and intelligent experiences. &lt;/p&gt;

&lt;p&gt;By integrating SCIM, OneLogin ensures that user data is synchronized and updated in real-time across all connected applications, reducing administrative overhead and enhancing security.&lt;/p&gt;

&lt;p&gt;Key Features of OneLogin&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete access management tools designed to monitor user access within an enterprise IT ecosystem.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Strong integration capabilities with various applications and services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advanced and adaptive authentication methods to safeguard user credentials and increase security defenses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time cloud directory which synchronizes users in your directory to thousands of apps in real-time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compliance analysis and reporting to provide audit logs which can be used to generate useful statistics.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ease of use and simple integration.&lt;/li&gt;
&lt;li&gt;Robust security features, including adaptive authentication.&lt;/li&gt;
&lt;li&gt;Scalable for enterprises of various sizes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be expensive for smaller businesses.&lt;/li&gt;
&lt;li&gt;Some users report a steep learning curve for advanced features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pricing&lt;br&gt;
OneLogin’s pricing starts at around $2 per user per month for basic SSO and increases with additional features and enterprise requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison table of the top SCIM providers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Factor&lt;/th&gt;
      &lt;th&gt;Okta&lt;/th&gt;
      &lt;th&gt;WorkOS&lt;/th&gt;
      &lt;th&gt;Frontegg&lt;/th&gt;
      &lt;th&gt;Stytch&lt;/th&gt;
      &lt;th&gt;OneLogin&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Compatibility&lt;/td&gt;
      &lt;td&gt;Supports a wide range of apps and services&lt;/td&gt;
      &lt;td&gt;Integrates with major IdPs and HRIS&lt;/td&gt;
      &lt;td&gt;Broad IdP support and custom integrations&lt;/td&gt;
      &lt;td&gt;Focused on modern auth methods&lt;/td&gt;
      &lt;td&gt;Extensive app and service compatibility&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ease of Integration&lt;/td&gt;
      &lt;td&gt;User-friendly with extensive resources&lt;/td&gt;
      &lt;td&gt;Developer-centric with robust APIs/SDKs&lt;/td&gt;
      &lt;td&gt;Self-service admin portal for easy setup&lt;/td&gt;
      &lt;td&gt;Lightweight and easy to integrate&lt;/td&gt;
      &lt;td&gt;Easy to integrate&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Security Features&lt;/td&gt;
      &lt;td&gt;Advanced security, adaptive MFA, threat insights&lt;/td&gt;
      &lt;td&gt;Real-time event streaming, SOC 2 certified&lt;/td&gt;
      &lt;td&gt;Behavioral analytics, advanced security suite&lt;/td&gt;
      &lt;td&gt;Basic security features, passkey auth&lt;/td&gt;
      &lt;td&gt;Adaptive authentication, robust security&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pricing&lt;/td&gt;
      &lt;td&gt;From $2/user/month, higher for advanced features&lt;/td&gt;
      &lt;td&gt;$125/company/month, discounts for bulk packages&lt;/td&gt;
      &lt;td&gt;$0.05/MAU, higher tiers available&lt;/td&gt;
      &lt;td&gt;Starts at $2/user/month, increases with features&lt;/td&gt;
      &lt;td&gt;Starts at $4/user/month&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Customer Support&lt;/td&gt;
      &lt;td&gt;Excellent support, including 24/7 availability&lt;/td&gt;
      &lt;td&gt;Excellent and dedicated support&lt;/td&gt;
      &lt;td&gt;Excellent support&lt;/td&gt;
      &lt;td&gt;Great customer support&lt;/td&gt;
      &lt;td&gt;Good and quick support&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Documentation&lt;/td&gt;
      &lt;td&gt;Excellent, user-friendly documentation&lt;/td&gt;
      &lt;td&gt;Best-in-class documentation and API references&lt;/td&gt;
      &lt;td&gt;Good documentation for developers&lt;/td&gt;
      &lt;td&gt;Extensive and clear documentation&lt;/td&gt;
      &lt;td&gt;Good documentation for developers&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Testimonials from organizations that have benefited from using SCIM
&lt;/h4&gt;

&lt;p&gt;SCIM is rapidly gaining adoption by high tech companies as an effective way of identity management.&lt;/p&gt;

&lt;p&gt;For instance, here's what the Director of Product for Indeed, a leading employment website noted : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Instead of having to jump on a call with the customer, stand by for 30 minutes to redeploy the login app to activate the SSO connection, the Admin Portal allowed the team to consolidate onboarding into just a few, self-serve steps." - Abishek Chhibber, Director of Product, Indeed &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How to make the right choice?
&lt;/h3&gt;

&lt;p&gt;In conclusion, we have talked about how SCIM simplifies identity management and ensures productivity as well as how SCIM works.&lt;/p&gt;

&lt;p&gt;Most importantly, we have discussed things to consider in choosing a SCIM provider along with recommendations based on specific use cases.&lt;/p&gt;

&lt;h4&gt;
  
  
  Common pitfalls to avoid during selection process
&lt;/h4&gt;

&lt;p&gt;Choosing a SCIM provider can be a weighty decision. Let's look at some common pitalls engineering teams face. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overlooking compliance of SCIM providers:&lt;/strong&gt; The SCIM protocol is an open standard. This means it states some guidelines and rules for implementing it. Meanwhile, different SCIM providers might translate the guidelines in their own way. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Engineering teams wouldn't want to be in a rush rather should make sure to check that the SCIM provider actually follows the standard. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Failure to evaluate compatibility:&lt;/strong&gt; One common mistake developer teams make is not doing a proper analysis on their existing legacy software to determine if it can easily support SCIM integration. This leads to delay in the overall implementation timeline, risk of server errors and cost implications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setting wrong expectations:&lt;/strong&gt; The SCIM standard is not a one-size-fits-all. Thus, expecting that it will instantly solve all your identity management problems is not the most realistic thing to do. For instance, your IdP (Identity Provider) or SCIM client might not work out of the box with every SCIM service without adding extra customizations here and there. So it's to important to manage expectations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  SCIM Provider recommendations based on specific needs and scenarios
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Education
&lt;strong&gt;Use Case:&lt;/strong&gt; Managing student, faculty, and staff identities across various systems.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Industry Needs:&lt;/strong&gt; Scalability, ease of integration, and user-friendly interfaces&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features to Look For:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Ability to handle a large number of users and fluctuations in user numbers throughout the academic year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Integration:&lt;/strong&gt; Compatibility with existing educational systems and platforms like LMS (Learning Management Systems).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-Service Portals:&lt;/strong&gt; Enabling students and staff to manage their accounts independently, reducing the administrative burden &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SCIM Provider Recommendations&lt;/strong&gt;&lt;br&gt;
Okta, Frontegg, OneLogin&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Healthcare
&lt;strong&gt;Use Case:&lt;/strong&gt; Managing access to sensitive patient data and complying with regulations like HIPAA&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Industry Needs:&lt;/strong&gt; High security, stringent compliance, and detailed auditing.&lt;/p&gt;

&lt;p&gt;Features to Look For:&lt;br&gt;
&lt;strong&gt;HIPAA Compliance:&lt;/strong&gt; Ensures the SCIM provider follows strict guidelines for protecting health information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced Security Features:&lt;/strong&gt; Including encryption, multi-factor authentication (MFA), and automated provisioning/de-provisioning to maintain secure access controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit Trails:&lt;/strong&gt; Detailed logging and monitoring to track access and changes to patient data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SCIM Provider Recommendations&lt;/strong&gt;&lt;br&gt;
Okta, WorkOS, OneLogin&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcommunity.microsoft.com/t5/security-compliance-and-identity/provisioning-with-scim-getting-started/ba-p/880010" rel="noopener noreferrer"&gt;Provisioning with SCIM – getting started &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://permify.co/#usecases" rel="noopener noreferrer"&gt;Build Scalable Authorization systems with Permify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.traxion.com/blog/the-10-most-common-pitfalls-for-scim-2-0-compliant-api-implementations/" rel="noopener noreferrer"&gt;The 10 most common pitfalls for SCIM 2.0 compliant API implementations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/articles/scim-data-model-limitations/" rel="noopener noreferrer"&gt; Don't SCIM over your Data Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workos.com/blog/deciphering-scim-complexity-navigating-group-fragmentation" rel="noopener noreferrer"&gt;Deciphering SCIM Complexity: Navigating Group Fragmentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>tutorial</category>
      <category>authentication</category>
    </item>
    <item>
      <title>OAuth vs. JWT: Ultimate Comparison</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Thu, 25 Jul 2024 13:31:49 +0000</pubDate>
      <link>https://dev.to/permify/oauth-vs-jwt-ultimate-comparison-3nd2</link>
      <guid>https://dev.to/permify/oauth-vs-jwt-ultimate-comparison-3nd2</guid>
      <description>&lt;p&gt;One of the most critical decisions in a software development project is selecting security standards. This decisions affects not only the security and performance of your app but also the user experience. &lt;/p&gt;

&lt;p&gt;When it comes to web application security, OAuth and JSON Web Tokens (JWT) are the most widely adopted standards.&lt;/p&gt;

&lt;p&gt;OAuth and JWT each have different characteristics and purposes, which determine how you use them in your apps.&lt;/p&gt;

&lt;p&gt;In this article, we will break down OAuth and JWT and compare their functionalities and use cases. &lt;/p&gt;

&lt;p&gt;You will also learn how to use them together to secure web applications. By the end of this article, you will have a clear understanding of when to use each one and how to implement them effectively in your apps.&lt;/p&gt;

&lt;h2 id="understanding-oauth"&gt;Understanding OAuth&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is OAuth?
&lt;/h3&gt;

&lt;p&gt;OAuth stands for Open Authorization. It is an authentication protocol that authorizes one application to interact with another on your behalf.&lt;/p&gt;

&lt;p&gt;The main goal of OAuth is to allow websites and apps to access a user's information without having the user disclose their passwords. This kind of access is important for making secure apps that work on different platforms.&lt;/p&gt;

&lt;p&gt;To further understand OAuth, it's important to grasp the key components involved in the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource Owner&lt;/strong&gt;: This is the user that owns the data or resource.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;: The application requesting access to the user's resource. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Server&lt;/strong&gt;: The authorization server sends access tokens to the client after authenticating the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Server&lt;/strong&gt;: This server hosts the resource or data that the client wants to access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How OAuth Works?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F68024640%2F7e7f5b1d-737c-4b26-a594-cb431399e28a%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F68024640%2F7e7f5b1d-737c-4b26-a594-cb431399e28a%3Falign%3D" alt="OAuth flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a detailed breakdown of the OAuth flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Request Resource&lt;/strong&gt;: The client asks to access a resource controlled by the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirect User for Authorization&lt;/strong&gt;: The client sends the user to the authorization server to begin authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Consent&lt;/strong&gt;: The authorization server asks the user to approve the client's request to access their resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide Consent&lt;/strong&gt;: The user reviews the request and agrees to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return Authorization Code&lt;/strong&gt;: After consent, the authorization server redirects the user back to the client with an authorization code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exchange Authorization Code for Access Token&lt;/strong&gt;: The client sends a request to the authorization server to exchange the authorization code for an access token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Receive Access Token&lt;/strong&gt;: The authorization server provides the client with an access token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request Resource with Access Token&lt;/strong&gt;: The client uses the access token to request the desired resource from the resource server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate Access Token&lt;/strong&gt;: The resource server checks the access token to ensure it's valid and has the required permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide Resource&lt;/strong&gt;: If the access token is valid, the resource server gives the requested resource to the client.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  OAuth Versions
&lt;/h3&gt;

&lt;p&gt;OAuth has evolved over the years and has two major versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth 1.0a&lt;/strong&gt;: This is the original version. It was secure but hard to use because it needed cryptographic signatures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth 2.0&lt;/strong&gt;: This is the more popular version. It's easier to use and more flexible, but it must be implemented carefully to stay secure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases of OAuth
&lt;/h3&gt;

&lt;p&gt;OAuth is widely used across various industries and scenarios, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Social Media Integration&lt;/strong&gt;: Letting users login to different services using their social media accounts (e.g., "Log in with Facebook").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Authorization&lt;/strong&gt;: Allowing third-party developers to access user data through APIs without needing the user's login details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Applications&lt;/strong&gt;: Providing secure access to company resources and services from third-party apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples in the real world include apps like Slack working with Google Drive or fitness trackers connecting with health data platforms.&lt;/p&gt;

&lt;h2 id="understanding-jwt-json-web-tokens"&gt;Understanding JWT (JSON Web Tokens)&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is JWT?
&lt;/h3&gt;

&lt;p&gt;JWT, or JSON Web Token, is a widely used standard for securely transmitting information between parties as a JSON object. This information is secure and can be trusted because it is digitally signed.&lt;/p&gt;

&lt;p&gt;The primary goal of JWT is to ensure the integrity and authenticity of the transmitted information. Developers commonly use JWTs to create authentication systems that do not require storing session details, which is known as stateless authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure of a JWT
&lt;/h3&gt;

&lt;p&gt;A JWT consists of three parts, which together form the structure of a JWT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Header&lt;/li&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;Signature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's break down each structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {
    "alg": "HS256",
    "typ": "JWT"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Header&lt;/strong&gt;: The header has two parts: the type of token (JWT) and the signing algorithm used, for example, HMAC SHA256 or RSA.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payload&lt;/strong&gt;: The payload consists of claims. Claims are statements about an entity, typically the user, along with additional data. There are three types of claims:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* **Registered claims**: These are predefined claims that are not mandatory but recommended, such as `iss` (issuer), `exp` (expiration time), `sub` (subject), and `aud` (audience).
* **Public claims**: Claims that any user can define but should be unique to avoid conflicts.
* **Private claims**: Private claims are custom claims designed to share information between parties who agree to use them.

An example payload might look like this:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This JSON is then encoded using Base64URL to create the second part of the JWT.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Signature&lt;/strong&gt;: To create the signature, you combine the encoded header and payload with a secret using the specified algorithm from the header and then sign it.&lt;/p&gt;

&lt;p&gt;For instance, if you choose to use the HMAC SHA256 algorithm, the signature is created in this manner:&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret)  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a JWT as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  header.payload.signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Scenario: User Authentication
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F68024640%2Ffc00caba-127b-4b87-bd2b-02e353256945%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F68024640%2Ffc00caba-127b-4b87-bd2b-02e353256945%3Falign%3D" alt="JWT authentication flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider a user logging into an application. Here's how JWT can be used to manage the authentication process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Login&lt;/strong&gt;: The user logs in with their credentials (e.g., username and password).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT Issuance&lt;/strong&gt;: After a successful login, the server creates a JWT containing the user's details (claims) and sends it to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Storage&lt;/strong&gt;: The client stores the JWT, typically in local storage or a cookie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticated Requests&lt;/strong&gt;: For subsequent requests, the client sends the JWT in the HTTP authorization header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Verification&lt;/strong&gt;: The server verifies the JWT's signature and checks the claims (e.g., expiration time) to ensure the token is valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Granted&lt;/strong&gt;: If the JWT is valid, the server processes the request. Otherwise, it responds with an unauthorized error.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Use Cases of JWT
&lt;/h3&gt;

&lt;p&gt;JWTs have many uses across different scenarios. Some common use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: JWTs are often used for user authentication, replacing traditional session management. They offer a way to handle user sessions without storing them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Information Exchange&lt;/strong&gt;: JWTs can securely transmit information between parties. Their compact size and URL-safe nature make them well-suited for embedding in URLs, HTTP headers, and other transport methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Control&lt;/strong&gt;: JWTs can be used to control access to resources by encoding user roles and permissions in the token, ensuring that only authorized users can access specific resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-world examples include implementations of single sign-on (SSO), API authentication, and mobile app authentication.&lt;/p&gt;

&lt;h2 id="comparing-oauth-and-jwt"&gt;Comparing OAuth and JWT&lt;/h2&gt;

&lt;h3&gt;
  
  
  Key Differences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose and Primary Use Cases&lt;/strong&gt;: OAuth is used for authorization by allowing third-party apps to access resources securely without sharing sensitive credentials. On the other hand, JWT is used for authentication and for securely exchanging information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Types&lt;/strong&gt;: OAuth access tokens are opaque and aren't designed for the client to understand; they need validation by the resource server. In contrast, JWTs pack all necessary information within the token itself so they can be verified locally without involving the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity and Implementation&lt;/strong&gt;: OAuth involves multiple steps and interactions between clients, authorization servers, and resource servers. This makes it more complex to implement when compared to JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros and Cons
&lt;/h3&gt;

&lt;h4&gt;
  
  
  OAuth Advantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delegated Access&lt;/strong&gt;: OAuth's main advantage is that it allows delegated access. This means users can give third-party apps specific permissions without sharing their passwords. OAuth also enhances security by minimizing the risk of exposing user credentials and gives users control over who can access their data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Granular Permissions&lt;/strong&gt;: OAuth uses scopes to define what actions an access token can perform. This lets users control the permissions that third-party apps get, ensuring they only have access to what they need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refresh Tokens&lt;/strong&gt;: OAuth can issue refresh tokens, which let apps get new access tokens without needing users to log in again. This improves the user experience by providing continuous access to resources. It also keeps access tokens short-lived, making them less risky if they get compromised.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  OAuth Disadvantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: The OAuth process has many steps and interactions, which can be tough to implement correctly. Developers need to handle various issues like token expiration and revocation to ensure everything works securely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Management&lt;/strong&gt;: Managing access and refresh tokens can be complicated, especially with multiple clients and resource servers. Issuing, storing, validating, and revoking tokens requires careful planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Load&lt;/strong&gt;: Frequently checking access tokens with the authorization server can slow things down and increase server load. This can affect performance, especially in busy applications where tokens need to be validated often.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  JWT Advantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateless Authentication&lt;/strong&gt;: JWTs enable stateless authentication by including all necessary information within the token. This means servers can check tokens without needing to keep a session state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Since JWTs can be checked locally without contacting the server, they can improve performance and reduce delay for client requests. This is helpful in high-traffic environments where reducing server load is important.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compact and URL-Safe&lt;/strong&gt;: JWTs are small and can be easily included in URLs, headers, and other transport methods. Their small size and safe encoding make them great for various uses, like API authentication and mobile app sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  JWT Disadvantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Token Size&lt;/strong&gt;: JWTs can be large because they include claims and a signature, which can increase network usage. This can be a problem in situations with limited bandwidth or when sending tokens often.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Risks&lt;/strong&gt;: Using JWTs securely means following cryptographic principles and best practices carefully. Risks like token leakage, replay attacks, and exposing sensitive data need to be managed with proper token design, encryption, and validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Built-in Revocation&lt;/strong&gt;: Unlike OAuth, JWTs don't have a built-in way to revoke tokens. Once a JWT is issued, it's valid until it expires, which makes it hard to invalidate tokens immediately if they are compromised or need to be revoked.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="how-oauth-and-jwt-work-together"&gt;How OAuth and JWT Work Together&lt;/h2&gt;

&lt;h3&gt;
  
  
  Integration Scenarios
&lt;/h3&gt;

&lt;p&gt;In many modern applications, OAuth and JWT can be used together. One common setup is using JWTs as OAuth access tokens. In this setup, the authorization server issues a JWT as an access token, which the client then uses to access the resource server.&lt;/p&gt;

&lt;p&gt;Here's a detailed example of how this integration works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Request&lt;/strong&gt;: The client application requests authorization from the user to access their resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Grant&lt;/strong&gt;: The user grants permission, and the client receives an authorization code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Token Request&lt;/strong&gt;: The client sends the authorization code to the OAuth authorization server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT Issuance&lt;/strong&gt;: The authorization server generates a JWT as the access token and sends it back to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Request&lt;/strong&gt;: The client uses the JWT access token to request resources from the resource server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Validation&lt;/strong&gt;: The resource server validates the JWT by checking its signature and claims, ensuring it is valid and has the necessary permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Response&lt;/strong&gt;: If the JWT is valid, the resource server processes the request and returns the requested resources to the client.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefits of Combining OAuth and JWT
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: Using JWTs as access tokens in OAuth combines their strengths. OAuth provides strong authorization, while JWTs offer a secure and efficient way to send and validate tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Performance&lt;/strong&gt;: The resource server can check JWTs locally without needing to contact the authorization server, reducing delay and server load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperability&lt;/strong&gt;: Using both OAuth and JWT helps different services and apps work together more easily. Many modern APIs and services support both, making it simpler to integrate and secure multiple systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Examples
&lt;/h3&gt;

&lt;p&gt;Several real-world applications use OAuth and JWT together to secure their services. Here are a few examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single Sign-On (SSO)&lt;/strong&gt;: Many enterprise systems use OAuth for SSO, where the authorization server gives out JWTs as access tokens. This lets users log in once and access multiple services without having to log in again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Gateway&lt;/strong&gt;: In microservices setups, an API gateway can use OAuth to authorize clients and issue JWTs as access tokens. The microservices then validate these JWTs locally, leading to a secure and efficient access control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile and Web Applications&lt;/strong&gt;: Applications like Google and Facebook use OAuth to authorize third-party apps to access user data. These access tokens, often JWTs, provide an efficient way to manage user sessions and permissions across different platforms.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="choosing-the-right-solution"&gt;Choosing the Right Solution&lt;/h2&gt;

&lt;p&gt;When deciding between OAuth, JWT, or a combination of both for your application, several factors need to be considered. Each technology has its strengths and is suited to different scenarios. Here's a guide to help you choose the right solution based on your requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factors to Consider
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security Requirements&lt;/strong&gt;: Think about the security your application needs. If you need detailed access control and want to allow third-party apps to access data, OAuth might be better. If you need a secure way to send user info without keeping session data, JWT is a good choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Architecture&lt;/strong&gt;: Consider your app's architecture. For microservices and distributed systems, JWTs are great because they're stateless. OAuth is useful in a centralized setup for handling authorization across different services and platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience and Performance&lt;/strong&gt;: Consider how your choice affects user experience and performance. JWTs can boost performance by cutting down on server-side checks. However, OAuth offers features like refresh tokens, which can improve user experience by keeping users logged in longer without needing to re-authenticate often.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="recommendations-for-different-scenarios"&gt;Recommendations for Different Scenarios&lt;/h2&gt;

&lt;h3&gt;
  
  
  When to Use OAuth
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Third-Party Access&lt;/strong&gt;: If your app needs to let third-party apps access user resources without sharing user credentials, OAuth is the way to go. Examples include logging in with Google, Facebook, or other social media accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Granular Permissions&lt;/strong&gt;: If your app needs detailed control over permissions with different levels of access, OAuth's scope feature is helpful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Authorization Workflows&lt;/strong&gt;: For apps with complex authorization needs, like enterprise systems with multiple roles and permissions, OAuth offers the right framework to manage these securely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to Use JWT
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateless Authentication&lt;/strong&gt;: If your app needs stateless authentication, where the server can check tokens without keeping session data, JWT is very effective. This approach is common in API authentication and mobile apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Sign-On (SSO)&lt;/strong&gt;: For SSO, where one login gives access to multiple services, JWTs are useful because they can carry information and be easily validated by different services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Information Exchange&lt;/strong&gt;: When you need a compact, URL-safe way to securely send information between parties, JWTs are a great choice. Their self-contained nature makes sharing and validating info simpler.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to Combine Both
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth with JWT Access Tokens&lt;/strong&gt;: Combining OAuth with JWT access tokens is a powerful approach for apps needing delegated access and stateless authentication. It blends OAuth's strong authorization with JWT's efficiency and speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices Architectures&lt;/strong&gt;: In microservices setups, using OAuth for initial authorization and issuing JWTs as access tokens lets each microservice check tokens locally. This cuts down on interactions with the authorization server and boosts the overall system performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security and Scalability&lt;/strong&gt;: Using OAuth alongside JWTs enhances security by managing token lifetimes with OAuth's refresh tokens. JWTs also offer a scalable, stateless token validation for each request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="conclusion"&gt;Wrapping Up&lt;/h2&gt;

&lt;p&gt;In this article, we have explored the differences between OAuth and JWT. Understanding their strengths and use cases is crucial for implementing efficient authentication and authorization mechanisms.&lt;/p&gt;

&lt;p&gt;When choosing between OAuth, JWT, or a combination of both, consider your application's specific needs, including security requirements, architecture, user experience, and performance. &lt;/p&gt;

&lt;p&gt;By carefully evaluating these factors, you can implement the most appropriate solution to ensure your web apps are both efficient and secure.&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>oauth</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How To Build Centralized Authorization System</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Wed, 24 Jul 2024 15:14:00 +0000</pubDate>
      <link>https://dev.to/permify/how-to-build-centralized-authorization-system-5e7p</link>
      <guid>https://dev.to/permify/how-to-build-centralized-authorization-system-5e7p</guid>
      <description>&lt;p&gt;In a centralized authorization, control decisions are managed from one single location and serve the entire application. &lt;/p&gt;

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

&lt;h3&gt;
  
  
  What you'll learn:
&lt;/h3&gt;

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

&lt;p&gt;Therefore, in the course of this article, we will cover the following and more;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What a centralized control system entails&lt;/strong&gt;; how it works, real-world organizations using it, the benefits and tradeoffs of having a central access system in your application and the workflow from an architectural level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralized vs Distributed Authorization Systems&lt;/strong&gt; and how to effectively decide the most optimal solution with practical use cases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A step by step guide&lt;/strong&gt; to get started implementing your centralized system using Permify&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are looking to understand the nooks and cranies of access management systems, then this is for you. &lt;/p&gt;

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

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2 id="the-decoupling-authorization-concept"&gt;The Decoupling Authorization Concept&lt;/h2&gt;

&lt;p&gt;Similar to the idea and essence of separation of concerns when writing code, the decoupling authorization concept falls along that path. &lt;/p&gt;

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

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

&lt;h2 id="what-is-a-centralized-access-control-system"&gt;What is a Centralized Authorization System?&lt;/h2&gt;

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

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

&lt;p&gt;Real world examples where centralized systems are used include companies that provide software infrastructure as a service (IaaS). &lt;/p&gt;

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

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

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

&lt;p&gt;Next, we’ll highlight some of the benefits.&lt;/p&gt;

&lt;h3 id="what-is-distributed-access-control"&gt;What is Distributed Authorization?&lt;/h3&gt;

&lt;p&gt;Decentralized or distributed access management involves a structure where control is handled by a number of servers spread across nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F9294b94a-d9a6-4084-b3e5-5e47b3406855" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F9294b94a-d9a6-4084-b3e5-5e47b3406855" alt="decentralized"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;h3 id="strengths-and-weaknesses"&gt;Strengths and Weaknesses&lt;/h3&gt;

&lt;p&gt;According to the &lt;a href="https://en.wikipedia.org/wiki/CAP_theorem" rel="noopener noreferrer"&gt;CAP theorem&lt;/a&gt;, a distributed system can only deliver at most two of these: &lt;strong&gt;C&lt;/strong&gt;onsistency, &lt;strong&gt;A&lt;/strong&gt;vailability and &lt;strong&gt;P&lt;/strong&gt;artition tolerance.  &lt;/p&gt;

&lt;p&gt;So, this calls for careful consideration of what your application can let go of without any negative consequences to business operations. &lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;strong&gt;Use case 1:&lt;/strong&gt; A banking application
&lt;/h4&gt;

&lt;p&gt;For this use case, we may describe the main business requirement as thus:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Availability, reliability:&lt;/strong&gt; Providing reliable information on financial transactions is necessary to maintain trust and satisfaction. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Safeguarding user accounts and transactions by ensuring the highest level of security possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; As the customer base grows, the application is expected to adapt to this change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, let's see how both authorization systems might compare in meeting these needs in relation to CAP mentioned earlier. &lt;/p&gt;

&lt;h4&gt;
  
  
  Centralized Authorization Systems
&lt;/h4&gt;

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

&lt;p&gt;The central server is often able to achieve &lt;strong&gt;high availability&lt;/strong&gt; of service if it is well designed in a way that authorization requests and responses flow smoothly. &lt;/p&gt;

&lt;p&gt;It’s also feasible to implement comprehensive security measures and policies to protect financial transactions and data. &lt;/p&gt;
&lt;h4&gt;
  
  
  Weaknesses:
&lt;/h4&gt;

&lt;p&gt;When there's a break in transmission, being a &lt;em&gt;single point of failure,&lt;/em&gt; the central server is affected leading to a disruption. &lt;/p&gt;

&lt;p&gt;A centralized system may struggle or require extra effort to scale as the user base grows. &lt;/p&gt;
&lt;h4&gt;
  
  
  Decentralized  Authorization Systems
&lt;/h4&gt;
&lt;h4&gt;
  
  
  Strengths:
&lt;/h4&gt;

&lt;p&gt;Decentralized systems are designed to thrive even when there is a partition because the nodes function independently of one another. &lt;/p&gt;

&lt;p&gt;A decentralized system will have higher availability because of the ability to &lt;em&gt;balance the load&lt;/em&gt; effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Achieving consistency and high security standards across each and every node can be challenging in a decentralized system&lt;/p&gt;
&lt;h4&gt;
  
  
  Use case 2: A real-time messaging application
&lt;/h4&gt;

&lt;p&gt;For this use case, we can identify our important  business needs as: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High availability:&lt;/strong&gt; Users expect to send and receive messages at any time even during peak periods without downtimes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; They expect their information to be safe and secure even in transmission&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; Users typically expect no delay or lagging. &lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Centralized Authorization Systems
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s easy to achieve consistency with a centralized server managing all data and operations&lt;/p&gt;

&lt;p&gt;For a small application with sizable requirements, a centralized system will be easier to design, implement and manage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;There is a single point of failure, which means that when the central server is down, the entire application will be inaccessible.&lt;/p&gt;

&lt;p&gt;A centralized system will require more effort to scale as the user base grows.&lt;/p&gt;
&lt;h4&gt;
  
  
  Decentralized Authorization Systems
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;There is more room to scale if the user base increases because the workload is shared across different nodes. &lt;/p&gt;

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

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

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;h2 id="how-centralized-authorization-systems-work"&gt;How Centralized Authorization Systems Work?&lt;/h2&gt;

&lt;p&gt;For this section, let’s talk about the nitty gritty of how a centralized system works. &lt;/p&gt;

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

&lt;p&gt;To implement this, we need to follow these key steps before anything;&lt;/p&gt;

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

&lt;p&gt;Step II.  &lt;strong&gt;Design architecture:&lt;/strong&gt; Based on the needs of the application, map out the architectural plan of your application showing the major components, their interactions, and the flow of data and control.&lt;/p&gt;

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

&lt;p&gt;Step IV.  &lt;strong&gt;Build microservices:&lt;/strong&gt; Implement the other core services and business logic of your application.&lt;/p&gt;

&lt;p&gt;Step V.  &lt;strong&gt;Deploy, test and maintain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Great, let’s now take a look at an demo workflow of a centralized architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F50bd5871-a6bf-45ea-bbeb-01d1625ae076" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F50bd5871-a6bf-45ea-bbeb-01d1625ae076" alt="centralized-architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the illustration above, our use case is a banking application system. &lt;/p&gt;

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

&lt;p&gt;So within a centralized system, all of these outlets will be connected to a single server behind the scenes.&lt;/p&gt;

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

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

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

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

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

&lt;h2 id="centralized-vs-distributed-access-control"&gt;Centralized vs. Distributed Authorization&lt;/h2&gt;

&lt;p&gt;In this section, we'll talk about a distributed system and discuss more on how it differs from a centralized authorization system. &lt;/p&gt;

&lt;p&gt;Weighing these would help you decide which approach suits your application needs making you better prepared to navigate any trade-offs.&lt;/p&gt;

&lt;h2 id="implementing-centralized-authorization-systems-with-permify"&gt;Implementing Centralized Authorization Systems with Permify&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://permify.co/" rel="noopener noreferrer"&gt;Permify&lt;/a&gt; is an open source service that provides all your authorization needs in one place, a popular choice loved by developers for many reasons.&lt;/p&gt;

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

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

&lt;p&gt;To get started, ensure Docker is running and connect to Permify:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step I.&lt;/strong&gt; Connect&lt;/p&gt;

&lt;p&gt;In your terminal, type the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 3476:3476 -p 3478:3478  ghcr.io/permify/permify serve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should get a screen showing that Permify service is running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F654ae51d-1f85-47a8-8a64-4710a3ac0ad6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F654ae51d-1f85-47a8-8a64-4710a3ac0ad6" alt="connect2Perm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step II.&lt;/strong&gt; Define Authorization Schema&lt;/p&gt;

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

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

&lt;p&gt;We will be using the &lt;a href="https://play.permify.co/?s=organizations-hierarchies" rel="noopener noreferrer"&gt;Permify playground&lt;/a&gt; to model our schema. &lt;br&gt;
The complete schema file can be found &lt;a href="https://gist.github.com/cannarron/47ca9a03d3d9ce1915a5b426e75e2bc8" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's dig in!&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;user&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;roles&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;message&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chatroom&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;Here, we create 4 entities; user, roles, message, chatroom.&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;roles&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="err"&gt;relation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@user&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;For the roles entity which would contain privileges, we add a new role to define an admin user.&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;message&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="err"&gt;relation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;owner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@user&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;permission&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;create&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;owner&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;Next is the message entity. It defines the owner as user and the permission to create a message.&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="err"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chatroom&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="err"&gt;relation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@roles&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;represents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;owner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;repository&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;relation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;owner&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;@user&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;permissions&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;permission&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;parent.admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;owner&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;The chatroom entity links the roles entity as its parent, stating that the user is the owner of the chatroom. Owner and any other admin can delete chatroom.&lt;/p&gt;

&lt;p&gt;That's it for our schema.&lt;/p&gt;

&lt;p&gt;The Permify playground contains a helpful visualizer tool that shows the schema relationships.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step III.&lt;/strong&gt; Connect your schema with Permify authorization service&lt;/p&gt;

&lt;p&gt;We have an authorization schema ready. The next thing we'll do is notify Permify server of this schema. &lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;localhost:3476/v1/tenants/t1/schemas/write&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure to click "&lt;strong&gt;Copy&lt;/strong&gt;" on the Permify Playground to get the string version of your schema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fcc8bba07-8042-4967-9c77-6f1c93e2f74c" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fcc8bba07-8042-4967-9c77-6f1c93e2f74c" alt="write2schema_n"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great. The above screenshot shows that we have successfully queried the Permify API and received a schema ID back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step IV.&lt;/strong&gt; Store Authorization Data&lt;/p&gt;

&lt;p&gt;Permify gives you the ability to store your authorization data in any database of choice and work with it using the Permify DataService.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;localhost:3476/v1/tenants/t1/data/write&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"schema_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"tuples"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"entity"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatroom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&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;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="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="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://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fee20a722-d3fb-4152-b265-6bf76bb98110" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fee20a722-d3fb-4152-b265-6bf76bb98110" alt="step-iv"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we are assigning a chatroom with id &lt;code&gt;1&lt;/code&gt; to belong to user with id 4. In other words, the relationship between the user and chatroom is &lt;em&gt;"owner"&lt;/em&gt;, as defined in our schema.&lt;/p&gt;

&lt;p&gt;From our Postman API* screen above, you will notice that Permify returns us a &lt;strong&gt;&lt;a href="https://docs.permify.co/operations/snap-tokens" rel="noopener noreferrer"&gt;snap token&lt;/a&gt;&lt;/strong&gt;. This feature makes it possible for you to get an up to date results at all times even if your schema later changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step V.&lt;/strong&gt; Perform authorization checks in your self hosted microservices and receive responses &lt;/p&gt;

&lt;p&gt;Now that we have authorization data in place, we are ready to perform checks to and fro.&lt;/p&gt;

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

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

&lt;p&gt;Make a POST request to the &lt;em&gt;CheckAPI&lt;/em&gt; service, include the following JSON in the body section of your request:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;localhost:3476/v1/tenants/t1/permissions/check&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"schema_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"snap_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;"entity"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatroom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&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;"permission"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subject"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&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;"context"&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;"tuples"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"entity"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatroom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&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;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subject"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&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="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="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://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Frk67maHkR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Frk67maHkR.png" alt="check_allowed"&gt;&lt;/a&gt;&lt;br&gt;
The screen above shows a successful check. With this your microservice receives the response &lt;code&gt;CHECK_RESULT_ALLOWED&lt;/code&gt; and user can therefore proceed with the required action.&lt;/p&gt;

&lt;p&gt;This completes the authorization cycle from our authorization service. &lt;/p&gt;

&lt;h2 id="summary-and-conclusion"&gt;Summary and Conclusion&lt;/h2&gt;

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

&lt;p&gt;To solidify our understanding, we have implemented a centralized system in our application using Permify authorization services. &lt;/p&gt;

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

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

</description>
      <category>tutorial</category>
      <category>authorization</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Opa Gatekeeper: How To Write Policies For Kubernetes Clusters</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Thu, 04 Jul 2024 13:37:37 +0000</pubDate>
      <link>https://dev.to/permify/opa-gatekeeper-how-to-write-policies-for-kubernetes-clusters-4o3</link>
      <guid>https://dev.to/permify/opa-gatekeeper-how-to-write-policies-for-kubernetes-clusters-4o3</guid>
      <description>&lt;p&gt;Due to the presence of tools like kubernetes, it is easier to manage and automate the daily working processes of a microservices environment.&lt;/p&gt;

&lt;p&gt;Using policies in your kubernetes will give you maximum control and flexibility especially in areas such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improving the security of your microservices&lt;/li&gt;
&lt;li&gt;Active management of limited resources in your cloud infrastructure&lt;/li&gt;
&lt;li&gt;Compliance and governance with regulatory laws&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By reading this article you will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The benefits of using policies in securing kubernetes environment.&lt;/li&gt;
&lt;li&gt;How to set up a system for dispensing policies; how kubernetes and OPA work behind the scenes.&lt;/li&gt;
&lt;li&gt;Everything you need to get started writing and running policies within your cluster.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="what-is-open-policy-agent-opa"&gt;What is Open Policy Agent (OPA)?&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.openpolicyagent.org/" rel="noopener noreferrer"&gt;Open Policy Agent (OPA)&lt;/a&gt; helps us write policy as code using Rego, a declarative language designed specifically for this reason.&lt;/p&gt;

&lt;p&gt;With OPA, we can define and enforce policies across various layers of the stack, from kubernetes to microservices. &lt;/p&gt;

&lt;p&gt;This approach contributes to consistency, scalability, and agility in managing policies within your kubernetes clusters. &lt;/p&gt;

&lt;p&gt;In addition, by using an expressive syntax you can efficiently represent access control rules and complex policy decisions that your organization reaches. &lt;/p&gt;

&lt;p&gt;Altogether, this goes a long way to make sure that your kubernetes environment is compliant and secure.&lt;/p&gt;

&lt;p&gt;The focus of this article is on writing policies in kubernetes setup.&lt;/p&gt;

&lt;p&gt;If you are not familiar with OPA, you can quickly learn more about how it works and implementation details in &lt;a href="https://permify.co/post/implementing-opa/" rel="noopener noreferrer"&gt;this article &lt;/a&gt;&lt;/p&gt;

&lt;h2 id="how-opa-and-kubernetes-work-together"&gt;How OPA And Kubernetes Work Together?&lt;/h2&gt;

&lt;p&gt;In this section, let us dive a bit more into how you can get Open Policy Agent (OPA) up and running. &lt;/p&gt;

&lt;p&gt;Good enough, OPA provides good support for kubernetes as reflected in its documentation so we shall look into how you can integrate it into your kubernetes environment.&lt;/p&gt;

&lt;p&gt;But first things first, let's talk about some important components and understand how it works ‘behind the scenes’. &lt;/p&gt;

&lt;p&gt;Kubernetes ships with what is called an admission controller. It's a piece of code that acts like a middleman between the kubernetes API itself and any request sent. &lt;/p&gt;

&lt;p&gt;Admission controllers can also be used to enforce policies and security measures, making sure that only authorized and properly configured workloads are allowed into the cluster. &lt;/p&gt;

&lt;p&gt;They may alter requests to ensure that it is of valid and acceptable form before processing takes place. &lt;/p&gt;

&lt;p&gt;So, admission controllers can be of two types: mutating or validating. It's important to understand this aspect as this is where Open Policy Agent (OPA) plugs in. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F94429606-c884-40af-893b-6a24903967a2" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F94429606-c884-40af-893b-6a24903967a2" alt="admission controllers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As to why we need admission controllers in our cluster, &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/" rel="noopener noreferrer"&gt;the official kubernetes documentation&lt;/a&gt; has this to say: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...a Kubernetes API server that is not properly configured with the right set of admission controllers is an incomplete server and will not support all the features you expect..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In essence, you may choose to use Open Policy Agent (OPA) or write your own custom admission controller, depending on the scope of customizations you are planning to achieve in your kubernetes environment.&lt;/p&gt;

&lt;h2 id="what-is-opa-gatekeeper"&gt;What is OPA Gatekeeper?&lt;/h2&gt;

&lt;p&gt;A kubernetes setup is barely complete without an admission controller. &lt;a href="https://github.com/open-policy-agent/gatekeeper" rel="noopener noreferrer"&gt;OPA Gatekeeper&lt;/a&gt; is one such controller that checks any request coming into the kubernetes API. &lt;/p&gt;

&lt;p&gt;Gatekeeper intercepts the request and checks with predefined policies. Based on this check, a request can be denied or granted. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F7a36c62b-c5f0-4d85-9337-8856edc8f8c6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F7a36c62b-c5f0-4d85-9337-8856edc8f8c6" alt="opa-gatekeeper"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the illustration above, we see the workflow of how OPA gatekeeper &lt;strong&gt;reviews&lt;/strong&gt; any request that comes into the kubernetes API server. &lt;/p&gt;

&lt;p&gt;It also constantly &lt;strong&gt;watches&lt;/strong&gt; for any changes in the elements of the API server such as the pods and services. &lt;/p&gt;

&lt;p&gt;So in essence, when you install gatekeeper on kubernetes environment, you can write policies and have them take effect in the cluster. &lt;br&gt;
We will see more of this in a bit.&lt;/p&gt;

&lt;h2 id="tutorial-guide-writing"&gt;Writing Policies In Kubernetes Clusters With OPA Gateway&lt;/h2&gt;

&lt;p&gt;To further understand the benefits and integration scope of OPA gatekeeper in kubernetes, we will cover the following use cases throughout this piece:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/ot-49MTSQNyOws_oFwt4sw#1-Namespace-policy" rel="noopener noreferrer"&gt;Defining namespaces policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hackmd.io/ot-49MTSQNyOws_oFwt4sw#2-Resource-quota-allocation" rel="noopener noreferrer"&gt;Allocating resources quotas&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/ot-49MTSQNyOws_oFwt4sw#3-Custom-validation-webhook" rel="noopener noreferrer"&gt;Writing a custom controller&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This 2-part tutorial will take you step by step through the entire process of how to write and test policies using Open Policy Agent (OPA) in your kubernetes cluster. &lt;/p&gt;

&lt;p&gt;In the first part, we'll make use of OPA gatekeeper admission controller to enforce the policies we write, and then, in the second part we shall write our own custom validating controller. &lt;/p&gt;

&lt;p&gt;Thus, by the end of this guide you'll have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gained knowledge of how OPA policies work within a kubernetes set up&lt;/li&gt;
&lt;li&gt;How to write and apply your own policies &lt;/li&gt;
&lt;li&gt;A better understanding of the admission controller webhook in Kubernetes; the workflow and how to implement your own validating controller.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To benefit fully from this practical guide, you need to have the following set up in your local machine: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure you have &lt;a href="https://www.openpolicyagent.org/docs/latest/#1-download-opa" rel="noopener noreferrer"&gt;OPA &lt;/a&gt;installed &lt;/li&gt;
&lt;li&gt;Minikube : Ensure you have &lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt; and a running Kubernates cluster&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/tasks/tools/#kubectl" rel="noopener noreferrer"&gt;kubectl:&lt;/a&gt; Ensure you have &lt;code&gt;kubectl&lt;/code&gt; configured to interact with your cluster.&lt;/li&gt;
&lt;li&gt;OPA gatekeeper : Ensure &lt;a href="https://open-policy-agent.github.io/gatekeeper/website/docs/install#installation" rel="noopener noreferrer"&gt;OPA Gatekeeper is installed in your cluster.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker and &lt;a href="https://hub.docker.com/signup" rel="noopener noreferrer"&gt;DockerHub&lt;/a&gt; account&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's get right into it.&lt;/p&gt;

&lt;h3 id="defining-namespaces-policies"&gt;1. Defining namespaces policies&lt;/h3&gt;

&lt;p&gt;For this usecase, let's write an OPA policy that states that every namespace create request should have an annotation added to it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step I:&lt;/strong&gt; Create a constraint template file&lt;br&gt;
A ConstraintTemplate defines the structure and logic of the policy. This template will enforce that every namespace must have the &lt;code&gt;team&lt;/code&gt; annotation.&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;templates.gatekeeper.sh/v1beta1&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;ConstraintTemplate&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;k8srequiredannotations&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;crd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;names&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;K8sRequiredAnnotations&lt;/span&gt;
  &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admission.k8s.gatekeeper.sh&lt;/span&gt;
      &lt;span class="na"&gt;rego&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;package k8srequiredannotations&lt;/span&gt;

        &lt;span class="s"&gt;violation[{"msg": msg}] {&lt;/span&gt;
          &lt;span class="s"&gt;input.review.kind.kind == "Namespace"&lt;/span&gt;
          &lt;span class="s"&gt;not input.review.object.metadata.annotations["team"]&lt;/span&gt;
          &lt;span class="s"&gt;msg := "Namespace must have an annotation 'team'"&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;constrainttemplate.yaml&lt;/code&gt; then apply it to your cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f constrainttemplate.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step II:&lt;/strong&gt; Create a constraint file&lt;/p&gt;

&lt;p&gt;A Constraint uses the ConstraintTemplate to enforce the policy on specific resources—in this case, namespaces.&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;constraints.gatekeeper.sh/v1beta1&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;K8sRequiredAnnotations&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;require-team-annotation&lt;/span&gt;
&lt;span class="na"&gt;spec&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;kinds&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="na"&gt;kinds&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;Namespace"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;constraint.yaml&lt;/code&gt; and also apply it to your cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f constraint.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step III:&lt;/strong&gt; Verify the policy &lt;/p&gt;

&lt;p&gt;To verify that the policy is working, try creating a namespace without the team annotation. It should be denied.&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;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;Namespace&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;demo-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;demo-namespace.yaml&lt;/code&gt; and apply it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f demo-namespace.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As expected, we get an error response: &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F6c6fb7e9-5154-45ac-86fc-bbb8cfd94b05" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F6c6fb7e9-5154-45ac-86fc-bbb8cfd94b05" alt="team_annot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's comply with the policy by creating a namespace with the &lt;code&gt;team&lt;/code&gt; annotation.&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;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;Namespace&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;test-namespace&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;devops"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the above YAML file as &lt;code&gt;test-namespace-with-annotation.yaml&lt;/code&gt; and apply it to the cluster.&lt;/p&gt;

&lt;p&gt;This time, it creates the namespace successfully.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F0375c733-a4c0-4e47-b5a8-9acba6f6a338" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F0375c733-a4c0-4e47-b5a8-9acba6f6a338" alt="test_np_with_anot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="allocating-resources-quotas"&gt;2. Allocating resources quotas&lt;/h3&gt;

&lt;p&gt;Next, we want to write a bit more advanced policy that states that namespaces labelled with &lt;code&gt;env:production&lt;/code&gt; must have a resource quota applied to them.&lt;/p&gt;

&lt;p&gt;Such a policy can be helpful when you want to control or monitor usage of resources and make things more efficient. Let's get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step I:&lt;/strong&gt; Create the constraint template file&lt;/p&gt;

&lt;p&gt;This template will check if namespaces labeled with &lt;code&gt;env: production&lt;/code&gt; have a resource quota.&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;templates.gatekeeper.sh/v1beta1&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;ConstraintTemplate&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;k8srequiredresourcequotas&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;crd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;names&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;K8sRequiredResourceQuotas&lt;/span&gt;
  &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admission.k8s.gatekeeper.sh&lt;/span&gt;
      &lt;span class="na"&gt;rego&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;package k8srequiredresourcequotas&lt;/span&gt;

        &lt;span class="s"&gt;violation[{"msg": msg}] {&lt;/span&gt;
          &lt;span class="s"&gt;input.review.kind.kind == "Namespace"&lt;/span&gt;
          &lt;span class="s"&gt;namespace := input.review.object&lt;/span&gt;

          &lt;span class="s"&gt;some label_key&lt;/span&gt;
          &lt;span class="s"&gt;namespace.metadata.labels[label_key] == "production"&lt;/span&gt;
          &lt;span class="s"&gt;not has_resource_quota(namespace.metadata.name)&lt;/span&gt;

          &lt;span class="s"&gt;msg := sprintf("Namespace labeled 'env: production' must have a resource quota", [])&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;

        &lt;span class="s"&gt;has_resource_quota(namespace_name) {&lt;/span&gt;
          &lt;span class="s"&gt;some i&lt;/span&gt;
          &lt;span class="s"&gt;input.review.context.related[i].kind == "ResourceQuota"&lt;/span&gt;
          &lt;span class="s"&gt;input.review.context.related[i].metadata.namespace == namespace_name&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;constrainttemplate.yaml&lt;/code&gt; and apply it to your cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f constrainttemplate.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step II:&lt;/strong&gt; Create a constraint file&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;constraints.gatekeeper.sh/v1beta1&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;K8sRequiredResourceQuotas&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;require-resource-quota-for-production&lt;/span&gt;
&lt;span class="na"&gt;spec&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;kinds&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="na"&gt;kinds&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;Namespace"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;constraint.yaml&lt;/code&gt; and apply it to your cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f constraint.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step III:&lt;/strong&gt; Verify the policy &lt;br&gt;
To verify that the policy works, let's create a simple test namespace with the production label but without specifying any resource quotas. It should be rejected.&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;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;Namespace&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;test-namespace-production-no-quota&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file &lt;code&gt;test-namespace-production-no-quota.yaml&lt;/code&gt; and apply it:&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="s"&gt;kubectl apply -f test-namespace-production-no-quota.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As expected, we get an error response when we try to create a namespace, saying that we must assign a quota just like it is stated in our policy file: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fc52c8685-3925-47d8-80cc-9f12cddd00bf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fc52c8685-3925-47d8-80cc-9f12cddd00bf" alt="namespace_error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome. Let's go ahead and assign a quota for our namespace.&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;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;ResourceQuota&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;resource-quota&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests.cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
    &lt;span class="na"&gt;requests.memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
    &lt;span class="na"&gt;limits.cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
    &lt;span class="na"&gt;limits.memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this YAML to a file named &lt;code&gt;resource-quota.yaml&lt;/code&gt; and apply it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f resource-quota.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fcd075440-698a-42f6-bc95-dbd5df76dd5a" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fcd075440-698a-42f6-bc95-dbd5df76dd5a" alt="resource_quota_created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After applying as shown above, the namespace creation and quota application is successful.&lt;/p&gt;

&lt;p&gt;You can also go further to actually check the assigned quota for the namespace with the command: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get resourcequotas -n default&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Thus far, we have seen how OPA gatekeeper acts as middleman or interceptor whenever we want to perform specific actions in kubernetes.  &lt;/p&gt;

&lt;p&gt;Let's now move to the final part, which is creating our own custom validation webhook.&lt;/p&gt;

&lt;h3 id="writing-a-custom-controller"&gt;3. Writing a custom controller&lt;/h3&gt;

&lt;p&gt;To begin, create and switch to a seperate folder specifically for this entire drill, you can call it &lt;code&gt;webhook_server.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;. Start the Minikube cluster.&lt;br&gt;
&lt;code&gt;minikube start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;. Write the validating logic for the webhook. We'll write this in Python but it can also be written  in any other language of choice. &lt;br&gt;
Create a file &lt;code&gt;app.py&lt;/code&gt; and copy the following contents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/validate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_pod&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;admission_review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;pod_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admission_review&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;request&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;spec&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Add your validation logic here
&lt;/span&gt;        &lt;span class="c1"&gt;# Example: Check if the pod has a specific label
&lt;/span&gt;        &lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pod_spec&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;labels&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod validation failed: Missing &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MissingAppLabel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

        &lt;span class="c1"&gt;# If all validation checks pass
&lt;/span&gt;        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod validation succeeded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred during pod validation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;InternalServerError&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}}),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Configure logging
&lt;/span&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Start the Flask app
&lt;/span&gt;    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; We need to containerize this webhook server, build and push it to a DockerHub repository. &lt;br&gt;
 I. Create a repository on your Dockerhub account.&lt;br&gt;
 II. Create a Dockerfile in the folder with the following contents: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Dockerfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;

&lt;span class="n"&gt;WORKDIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;

&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;III. Build the image&lt;br&gt;
 &lt;code&gt;docker build -t your-username/repository-name:latest .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;IV. Push it to DockerHub&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag &amp;lt;repository-name&amp;gt;:latest your-username/repository-name:latest
docker push your-username/repository-name:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the image should be live on Dockerhub. This means we can now use it in our deployment yaml file. &lt;/p&gt;

&lt;p&gt;💡&lt;strong&gt;Troubleshooting tip:&lt;/strong&gt; if you experience request denied errors while pushing your docker image to DockerHub, ensure to login to docker on terminal, double check for any typos or mismatch in the image name, repository name and tagname.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;. Generate TLS Certificates. This helps to secure communication between our webhook server and kubernetes. It is a crucial step to pay attention to. If not properly configured, you might end up getting TLS errors down the line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-newkey&lt;/span&gt; rsa:4096 &lt;span class="nt"&gt;-keyout&lt;/span&gt; server.key &lt;span class="nt"&gt;-out&lt;/span&gt; server.crt &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s2"&gt;"/CN=pod-validation-webhook.default.svc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret tls pod-validation-webhook-tls &lt;span class="nt"&gt;--cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;server.crt &lt;span class="nt"&gt;--key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;server.key &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; Create the deployment YAML file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch webhook-deployment.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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/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;Deployment&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;pod-validation-webhook&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-validation-webhook&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-validation-webhook&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;cweb&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cannarron/cweb:latest&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&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;tls-certs&lt;/span&gt;
          &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/webhook/certs&lt;/span&gt;
          &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&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;tls-certs&lt;/span&gt;
        &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-validation-webhook-tls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6.&lt;/strong&gt; Create a service&lt;br&gt;
We need to create a kubectl service resource to point back to our Python webhook server&lt;br&gt;
&lt;code&gt;touch webhook-service.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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;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;Service&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;pod-validation-webhook&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-validation-webhook&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7.&lt;/strong&gt; Create the validation configuration file. &lt;br&gt;
The validation configuration file is what officially registers our webhook as part of the kubernetes API. In other words, kubernetes will be aware that there's a new middleman that should be called whenever a pod creation request is sent.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch validating-webhook-config.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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admissionregistration.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;ValidatingWebhookConfiguration&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;pod-validation-webhook&lt;/span&gt;
&lt;span class="na"&gt;webhooks&lt;/span&gt;&lt;span class="pi"&gt;:&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;pod.validation.example.com&lt;/span&gt;
    &lt;span class="na"&gt;clientConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;service&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;pod-validation-webhook&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;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/validate"&lt;/span&gt;
      &lt;span class="na"&gt;caBundle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;base64 encoded ca.crt&amp;gt;&lt;/span&gt;
    &lt;span class="na"&gt;admissionReviewVersions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
    &lt;span class="na"&gt;sideEffects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;None&lt;/span&gt;
    &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="na"&gt;failurePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fail&lt;/span&gt;
    &lt;span class="na"&gt;matchPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Equivalent&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="na"&gt;apiVersions&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;v1"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;operations&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="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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8.&lt;/strong&gt; Apply manifest files; Let's apply the deployment, service and validation configuration files YAML we have created in the earlier steps.&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="s"&gt;kubectl apply -f webhook-deployment.yaml&lt;/span&gt;
&lt;span class="s"&gt;kubectl apply -f webhook-service.yaml&lt;/span&gt;
&lt;span class="s"&gt;kubectl apply -f validating-webhook-config.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;9.&lt;/strong&gt; Verify. &lt;br&gt;
Finally if the deployment goes well, then you should see the pod running successfully. And the validation webhook should be active as well&lt;br&gt;
To verify that our validation hook is now active, based on the validation rules set in the webhook, we simply create a test pod without a label which request should be denied.&lt;/p&gt;

&lt;h2 id="summary-and-conclusion"&gt;Summary and Conclusion&lt;/h2&gt;

&lt;p&gt;In this comprehensive guide, we have talked about using policies in kubernetes to extend its features and add custom enhancements or team preferences. We have also gone through step by step on implementing kubernetes policies with practical usecases.&lt;/p&gt;

&lt;p&gt;Using policies in your kubernetes setup is a creative way to fully explore the capabilities within your containerized deployments and make it more secure.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>opa</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Implement Two-Factor Authentication (2FA) in Golang</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Mon, 01 Jul 2024 13:47:22 +0000</pubDate>
      <link>https://dev.to/permify/how-to-implement-two-factor-authentication-2fa-in-golang-2jg3</link>
      <guid>https://dev.to/permify/how-to-implement-two-factor-authentication-2fa-in-golang-2jg3</guid>
      <description>&lt;p&gt;Authentication is crucial for ensuring security and passwords alone are no longer sufficient to protect against unauthorized access. That's where Two-Factor Authentication comes in. By requiring users to provide two forms of identification, such as a password and a temporary code, 2FA significantly reduces the risk of unauthorized access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Permify/permify/" rel="noopener noreferrer"&gt;&lt;br&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2Fc3933934-c3a4-44fb-a3fc-dbdf5aff4e95" alt="Local Image"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore how to implement Two-Factor Authentication (2FA) in Golang.&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you begin implementing Two-Factor Authentication (2FA) in your Golang web application, ensure you have the following prerequisites in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of Golang programming language.&lt;/li&gt;
&lt;li&gt;Go development environment set up on your machine.&lt;/li&gt;
&lt;li&gt;Familiarity with web development concepts such as HTTP requests and HTML templates.&lt;/li&gt;
&lt;li&gt;A text editor or integrated development environment (IDE) for writing and editing Go code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with understanding the basics of Two-Factor Authentication and how it works.&lt;/p&gt;

&lt;h2 id="understanding-two-factor-authentication-2fa"&gt;Understanding Two-Factor Authentication (2FA)&lt;/h2&gt;
&lt;h3&gt;
  
  
  How 2FA Works
&lt;/h3&gt;

&lt;p&gt;Two-Factor Authentication (2FA) adds an additional layer of security to the traditional username and password login process. It requires users to provide two forms of identification before granting access to their accounts. Let's understand how it works with a real-life scenario:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Online Banking&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single-Factor Authentication&lt;/strong&gt;: Imagine logging into your online banking account with just your username and password. While this provides some level of security, it's vulnerable to password theft or hacking.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Two-Factor Authentication (2FA)&lt;/strong&gt;: Now, let's add an additional step. After entering your username and password, instead of immediately gaining access, you receive a one-time code on your smartphone via a text message or a dedicated authentication app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Something You Know (Password)&lt;/strong&gt;: Your regular username and password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Something You Have (One-Time Code)&lt;/strong&gt;: The one-time code sent to your smartphone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, to access your account, you not only need to know your password but also have access to your smartphone to retrieve the one-time code. Even if someone knows your password, they can't log in without also having your smartphone.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="what-is-totp"&gt;What is Time-Based One-Time Passwords (TOTP) ?&lt;/h2&gt;

&lt;p&gt;Time-Based One-Time Passwords (TOTP) is a common method used for implementing 2FA. TOTP generates a temporary six-digit code that changes every 30 seconds, providing an additional layer of security.&lt;/p&gt;

&lt;p&gt;Here's how TOTP works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shared Secret&lt;/strong&gt;: A unique secret key is shared between the user's device and the authentication server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Synchronization&lt;/strong&gt;: Both the user's device and the server use the current time to generate the one-time password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algorithm&lt;/strong&gt;: TOTP uses a cryptographic algorithm, typically HMAC-SHA1, to generate the one-time password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validity Period&lt;/strong&gt;: Each one-time password is valid for a short period, typically 30 seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, when setting up TOTP for a user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server generates a secret key and shares it with the user's device.&lt;/li&gt;
&lt;li&gt;The user's device uses this secret key along with the current time to generate the six-digit code.&lt;/li&gt;
&lt;li&gt;When logging in, the user provides both their regular password and the current six-digit code generated by their device.&lt;/li&gt;
&lt;li&gt;The server verifies the code by using the shared secret key and checking its validity within the time window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, that you have basic understanding of 2FA and TOTP. Let's start implementing it in a Golang Web App.&lt;/p&gt;

&lt;h2 id="setting-up-your-golang-environment"&gt;Setting Up Your Golang Environment&lt;/h2&gt;

&lt;p&gt;To set up your Golang environment for implementing 2FA, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Golang&lt;/strong&gt;: If you haven't already, download and install Golang from the official website: &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;https://golang.org/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Up Your Workspace&lt;/strong&gt;: Create a directory for your Golang projects. For example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;go-2fa-demo
&lt;span class="nb"&gt;cd &lt;/span&gt;go-2fa-demo
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Clone the Example Project&lt;/strong&gt;: Clone the example project provided in this tutorial or create a new Golang project structure similar to the one shown below:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-2fa-demo/
├── main.go
├── templates/
│   ├── dashboard.html
│   ├── index.html
│   ├── login.html
│   ├── qrcode.html
│   └── validate.html
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Install Dependencies&lt;/strong&gt;: This project uses a third-party library for generating TOTP (Time-Based One-Time Passwords). Install the library using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/pquerna/otp/totp
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Verify Installation&lt;/strong&gt;: Ensure that your Golang environment is set up correctly by running the example project. Execute the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;You should see a message indicating that the server is starting at port 8080.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Once you've completed these steps, your Golang environment will be ready for implementing Two-Factor Authentication in your web application. &lt;/p&gt;

&lt;h2 id="implementing-two-factor-authentication-2fa-in-golang"&gt;Implementing Two-Factor-Authentication in Golang&lt;/h2&gt;

&lt;p&gt;In this section, we'll walk you through the process of implementing Two-Factor Authentication (2FA) in your Golang web application. &lt;/p&gt;

&lt;p&gt;The below project is only for demonstration purposes; in production, the application would require additional security measures and features. The complete code of the project is provided in &lt;a href="https://github.com/Imranalam28/Golang-App-2FA" rel="noopener noreferrer"&gt;this GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Choosing a 2FA Method
&lt;/h3&gt;

&lt;p&gt;Choosing the right Two-Factor Authentication (2FA) method is crucial for ensuring the security of your application. There are several 2FA methods available, each with its own advantages and considerations. In this tutorial, we'll focus on implementing Time-Based One-Time Passwords (TOTP) using the Google Authenticator app as the authenticator.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why TOTP?
&lt;/h4&gt;

&lt;p&gt;Time-Based One-Time Passwords (TOTP) is a popular 2FA method widely adopted by many online services. Here's why TOTP is a good choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: TOTP generates temporary codes that expire after a short period, making them less susceptible to replay attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline Capability&lt;/strong&gt;: TOTP does not require an internet connection for code generation, allowing users to authenticate even when offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardization&lt;/strong&gt;: TOTP is standardized under RFC 6238, ensuring compatibility with various authentication apps and libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Friendly&lt;/strong&gt;: TOTP codes are easy to generate and enter, providing a seamless user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Considerations
&lt;/h4&gt;

&lt;p&gt;Before implementing TOTP in your application, consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Adoption&lt;/strong&gt;: Ensure that your users are familiar with TOTP and comfortable using authentication apps like Google Authenticator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup Mechanism&lt;/strong&gt;: Provide users with backup codes in case they lose access to their authentication device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security vs. Convenience&lt;/strong&gt;: Strike a balance between security and convenience by implementing additional security measures like rate limiting without compromising user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you find a 2FA method suitable to your need, you can easily intergrate it to your web app using a library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Integrating 2FA Library
&lt;/h3&gt;

&lt;p&gt;After choosing a 2FA method, the next step is to integrate a third-party library that provides functionality for generating and validating TOTP codes. In our example project, we're using the &lt;code&gt;github.com/pquerna/otp/totp&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;github.com/pquerna/otp/totp&lt;/code&gt; library is a popular choice for implementing TOTP in Golang applications. Here's why it's a preferred option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature-Rich&lt;/strong&gt;: The library provides comprehensive support for TOTP generation, validation, and customization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Well-Maintained&lt;/strong&gt;: Developed and maintained by a reputable author, the library receives regular updates and bug fixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community Support&lt;/strong&gt;: Being widely used in the Golang ecosystem, the library benefits from a supportive community and extensive documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;

&lt;p&gt;To integrate the &lt;code&gt;github.com/pquerna/otp/totp&lt;/code&gt; library into your Golang project, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/pquerna/otp/totp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will download and install the library and its dependencies, making it ready for use in your application. Now, we are ready to start implementing the 2FA in our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Setting Up Routes
&lt;/h3&gt;

&lt;p&gt;Now, the next thing we have to do is set up the routes in our web app to handle the incoming requests. Setting up routes in your Golang web application is crucial for handling different HTTP requests and directing users to the appropriate handlers. In this section, we'll demonstrate how to set up routes in your project using the &lt;code&gt;net/http&lt;/code&gt; package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Importing Required Packages
&lt;/h4&gt;

&lt;p&gt;Before defining routes, ensure you import the necessary packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Defining Routes
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;main.go&lt;/code&gt; file of your project, define routes using the &lt;code&gt;http.HandleFunc()&lt;/code&gt; function. Each route corresponds to a specific URL path and is associated with a handler function that processes requests to that path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Define routes&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loginHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/dashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dashboardHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/generate-otp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generateOTPHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/validate-otp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validateOTPHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Start the server&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;http.HandleFunc()&lt;/code&gt;&lt;/strong&gt;: This function registers a handler function for the given pattern (URL path). It takes two arguments: the URL pattern and the handler function to execute when a request matches the pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt;: Handles requests to the root URL and directs users to the homepage.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/login&lt;/code&gt;: Handles login requests and processes user authentication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/dashboard&lt;/code&gt;: Handles requests to access the dashboard after successful authentication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/generate-otp&lt;/code&gt;: Handles requests to generate a One-Time Password (OTP) for Two-Factor Authentication (2FA).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/validate-otp&lt;/code&gt;: Handles requests to validate the OTP entered by the user during the 2FA setup or login process.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Creating Homepage
&lt;/h3&gt;

&lt;p&gt;The homepage serves as the entry point to your web application, providing users with initial information and navigation options. In this section, we'll create the homepage for our Golang web application and set up the corresponding handler function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Template File
&lt;/h4&gt;

&lt;p&gt;First, create an HTML template file named &lt;code&gt;index.html&lt;/code&gt; in the &lt;code&gt;templates&lt;/code&gt; directory of your project. This file will define the structure and content of the homepage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- templates/index.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Go 2FA Demo&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container mt-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Welcome to the Go 2FA Demo&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;Next, define a handler function named &lt;code&gt;homeHandler&lt;/code&gt; in your &lt;code&gt;main.go&lt;/code&gt; file to render the homepage when users access the root URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Execute the index.html template&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template File&lt;/strong&gt;: The &lt;code&gt;index.html&lt;/code&gt; template defines the structure of the homepage using HTML markup. It includes a welcome message and a button to navigate to the login page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;homeHandler&lt;/code&gt; function is responsible for handling requests to the root URL ("/"). It executes the &lt;code&gt;index.html&lt;/code&gt; template and sends the rendered HTML content as the response.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Creating Login Page
&lt;/h3&gt;

&lt;p&gt;The login page is a crucial component of your web application, allowing users to authenticate and access protected resources. In this section, we'll create the login page for our Golang web application and set up the necessary handler function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Template File
&lt;/h4&gt;

&lt;p&gt;Begin by creating an HTML template file named &lt;code&gt;login.html&lt;/code&gt; in the &lt;code&gt;templates&lt;/code&gt; directory. This file will define the structure and content of the login page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- templates/login.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container mt-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"needs-validation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Username:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;Next, define a handler function named &lt;code&gt;loginHandler&lt;/code&gt; in your &lt;code&gt;main.go&lt;/code&gt; file to render the login page and handle user authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;loginHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Render the login.html template for GET requests&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"login.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Handle POST requests for user authentication&lt;/span&gt;
    &lt;span class="c"&gt;// (Code for handling form submission and user authentication)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template File&lt;/strong&gt;: The &lt;code&gt;login.html&lt;/code&gt; template defines the structure of the login page using HTML markup. It includes form fields for entering the username and password, along with a submit button for initiating the login process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;loginHandler&lt;/code&gt; function is responsible for handling requests to the &lt;code&gt;/login&lt;/code&gt; URL path. For GET requests, it renders the &lt;code&gt;login.html&lt;/code&gt; template to display the login page. For POST requests, it will handle form submission and user authentication (to be implemented).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6: Handling User Authentication
&lt;/h3&gt;

&lt;p&gt;User authentication is a critical aspect of web applications, ensuring that only authorized users can access protected resources. In this section, we'll implement the logic for handling user authentication in our Golang web application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;loginHandler&lt;/code&gt; function of your &lt;code&gt;main.go&lt;/code&gt; file, implement the logic to authenticate users based on the provided credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;loginHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Render the login.html template for GET requests&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"login.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// For POST requests, parse form data&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error parsing form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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="c"&gt;// Retrieve username and password from the form data&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Perform user authentication&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// If authentication fails, redirect to the login page&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusFound&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="c"&gt;// If authentication succeeds, redirect to the dashboard&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/dashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusFound&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;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;loginHandler&lt;/code&gt; function handles both GET and POST requests to the &lt;code&gt;/login&lt;/code&gt; URL path. For GET requests, it renders the login page using the &lt;code&gt;login.html&lt;/code&gt; template. For POST requests, it parses the form data to retrieve the username and password entered by the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Authentication&lt;/strong&gt;: Inside the POST request handling block, the function attempts to authenticate the user based on the provided credentials. It checks if the username exists in the &lt;code&gt;users&lt;/code&gt; map and verifies that the password matches the stored password for the user. If authentication fails, the user is redirected back to the login page. If authentication succeeds, the user is redirected to the dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 7: Generating TOTP Secret
&lt;/h3&gt;

&lt;p&gt;Generating a Time-Based One-Time Password (TOTP) secret is the initial step in setting up two-factor authentication (2FA) for your web application. In this section, we'll implement the functionality to generate a TOTP secret for each user.&lt;/p&gt;

&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;Create a handler function named &lt;code&gt;generateOTPHandler&lt;/code&gt; in your &lt;code&gt;main.go&lt;/code&gt; file to handle the generation of TOTP secrets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;generateOTPHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Retrieve username from the query parameters&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Retrieve user details from the in-memory "database"&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusFound&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="c"&gt;// Generate TOTP secret if not already generated&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;totp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateOpts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Issuer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"Go2FADemo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;AccountName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;username&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to generate TOTP secret."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Construct the OTP URL for generating QR code&lt;/span&gt;
    &lt;span class="n"&gt;otpURL&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"otpauth://totp/Go2FADemo:%s?secret=%s&amp;amp;issuer=Go2FADemo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Prepare data to pass to the template&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OTPURL&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="n"&gt;OTPURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;otpURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Render the qrcode.html template with the OTP URL data&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"qrcode.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;generateOTPHandler&lt;/code&gt; function handles requests to generate TOTP secrets for users. It retrieves the username from the query parameters, then checks if the user exists in the in-memory "database". If the user exists, it generates a TOTP secret using the &lt;code&gt;totp.Generate&lt;/code&gt; function from the &lt;code&gt;otp/totp&lt;/code&gt; package. The generated secret is stored in the user's data structure. If the secret is successfully generated, the function constructs an OTP URL for generating a QR code. Finally, it renders the &lt;code&gt;qrcode.html&lt;/code&gt; template with the OTP URL data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 8: Displaying QR Code
&lt;/h3&gt;

&lt;p&gt;Displaying a QR code is a convenient way to enable users to set up two-factor authentication (2FA) using authenticator apps. We will create a seperate HTML file to display the QR code in our app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Template File
&lt;/h4&gt;

&lt;p&gt;Create an HTML template file named &lt;code&gt;qrcode.html&lt;/code&gt; in the &lt;code&gt;templates&lt;/code&gt; directory. This file will define the structure and content for displaying the QR code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- templates/qrcode.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;QR Code&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container mt-5 text-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Scan QR Code with Authenticator App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;https://chart.googleapis.com/chart?cht=qr&amp;amp;chl={{.OTPURL}&amp;gt;}&amp;amp;chs=180x180&amp;amp;choe=UTF-8&amp;amp;chld=L|2"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-fluid mb-3"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"QR Code"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/validate-otp"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"get"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{.Username}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I've Scanned the QR Code&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template File&lt;/strong&gt;: The &lt;code&gt;qrcode.html&lt;/code&gt; template defines the structure of the page for displaying the QR code. It includes an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag to display the QR code image generated using the Google Chart API. Additionally, it provides a button for users to indicate that they have scanned the QR code with their authenticator app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 9: Validating TOTP Code
&lt;/h3&gt;

&lt;p&gt;Validating the Time-Based One-Time Password (TOTP) code submitted by users is important for ensuring the security of the two-factor authentication (2FA) process. In this section, we'll implement the functionality to validate the TOTP code entered by users.&lt;/p&gt;

&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;Create a handler function named &lt;code&gt;validateOTPHandler&lt;/code&gt; in your &lt;code&gt;main.go&lt;/code&gt; file to handle the validation of TOTP codes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;validateOTPHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="c"&gt;// Retrieve the username from the query parameters&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Render the validate.html template, passing the username to it&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"validate.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="c"&gt;// Parse form data&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error parsing form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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="c"&gt;// Retrieve username and TOTP code from form data&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;otpCode&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"otpCode"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Retrieve user details from the in-memory "database"&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"User does not exist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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="c"&gt;// Validate the TOTP code using the TOTP library&lt;/span&gt;
    &lt;span class="n"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;totp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otpCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isValid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// If validation fails, redirect back to the validation page&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/validate-otp?username=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusTemporaryRedirect&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="c"&gt;// If validation succeeds, set a session cookie and redirect to the dashboard&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cookie&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"authenticatedUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;MaxAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// 1 hour for example&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/dashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusSeeOther&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;validateOTPHandler&lt;/code&gt; function handles both GET and POST requests. When a GET request is received, it retrieves the username from the query parameters and renders the &lt;code&gt;validate.html&lt;/code&gt; template, passing the username to it.&lt;/li&gt;
&lt;li&gt;When a POST request is received, it parses the form data to retrieve the username and the TOTP code submitted by the user. It then validates the TOTP code using the TOTP library. If the code is valid, it sets a session cookie to indicate successful authentication and redirects the user to the dashboard. If the code is invalid, it redirects the user back to the validation page for another attempt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 10: Dashboard Handler
&lt;/h3&gt;

&lt;p&gt;The dashboard handler is responsible for rendering the dashboard page once a user has successfully authenticated. &lt;/p&gt;

&lt;h4&gt;
  
  
  Handler Function
&lt;/h4&gt;

&lt;p&gt;Create a handler function named &lt;code&gt;dashboardHandler&lt;/code&gt; in your &lt;code&gt;main.go&lt;/code&gt; file to handle dashboard requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;dashboardHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Retrieve the authenticated user's username from the session cookie&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"authenticatedUser"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// If user is not authenticated, redirect to the homepage&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusFound&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="c"&gt;// Render the dashboard.html template&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dashboard.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&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;In the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handler Function&lt;/strong&gt;: The &lt;code&gt;dashboardHandler&lt;/code&gt; function retrieves the authenticated user's username from the session cookie. If the user is not authenticated (i.e., the session cookie is not present or expired), it redirects the user to the homepage. If the user is authenticated, it renders the &lt;code&gt;dashboard.html&lt;/code&gt; template to display the dashboard page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="testing-two-factor-authentication-2fa-implementation"&gt;Testing Your Two-Factor Authentication (2FA) Implementation&lt;/h2&gt;

&lt;p&gt;Testing your two-factor authentication (2FA) implementation is essential to ensure its robustness and effectiveness in enhancing security. &lt;/p&gt;

&lt;h3&gt;
  
  
  Running the Application and Testing
&lt;/h3&gt;

&lt;p&gt;To run the application and test the 2FA implementation, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the Application&lt;/strong&gt;: Start the web server by running the main Go file using the &lt;code&gt;go run&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;go-2fa-demo
go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access the Application&lt;/strong&gt;: Open a web browser and navigate to &lt;code&gt;http://localhost:8080/&lt;/code&gt; to access the application.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBJwELORCT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBJwELORCT.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Login&lt;/strong&gt;: Click on the "Login" button to initiate the authentication process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enter Credentials&lt;/strong&gt;: Enter the username and password (e.g., "john" and "password") to proceed.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr1XRIOC06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr1XRIOC06.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate QR Code&lt;/strong&gt;: After successful login, a QR code will be generated for TOTP setup.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkSVv_A06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkSVv_A06.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scan QR Code&lt;/strong&gt;: Use a TOTP-compatible authenticator app, such as Google Authenticator, to scan the QR code and set up 2FA for the user account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Authentication&lt;/strong&gt;: Enter the TOTP code generated by the authenticator app to verify successful authentication.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FS1eOPuRA6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FS1eOPuRA6.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Google Authenticator
&lt;/h3&gt;

&lt;p&gt;Google Authenticator is a widely used authenticator app that generates TOTP codes for 2FA authentication. It securely stores secrets and generates time-based codes, enhancing security for user accounts.&lt;/p&gt;

&lt;p&gt;To set up Google Authenticator:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the App&lt;/strong&gt;: Download and install the Google Authenticator app from the App Store (iOS) or Google Play Store (Android).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add an Account&lt;/strong&gt;: Open the app and select "Scan a QR code" or "Manual entry" to add a new account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan QR Code&lt;/strong&gt;: Use the device's camera to scan the QR code displayed on the application's login page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify Setup&lt;/strong&gt;: Once scanned, the app will display a six-digit TOTP code that refreshes every 30 seconds. Enter this code into the application to verify the setup.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="best-practices-for-two-factor-authentication-2fa"&gt;Best Practices for Two-Factor Authentication (2FA)&lt;/h2&gt;

&lt;p&gt;Implementing two-factor authentication (2FA) in your Golang web application is an important step towards enhancing security. However, to ensure its effectiveness and usability, it's essential to follow best practices. In this section, we'll discuss key best practices for implementing 2FA.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Inform Users About Backup Codes
&lt;/h3&gt;

&lt;p&gt;Educate users about the importance of backup codes and provide mechanisms for generating and securely storing them. Backup codes serve as a fallback option in case primary authentication methods are unavailable.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Rate Limiting Authentication Attempts
&lt;/h3&gt;

&lt;p&gt;Implement rate-limiting mechanisms to prevent brute-force attacks and unauthorized access attempts. Limit the number of login attempts within a specific time frame to mitigate the risk of credential stuffing attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. User Experience Considerations
&lt;/h3&gt;

&lt;p&gt;Prioritize user experience during the 2FA setup and authentication process. Design intuitive interfaces, provide clear instructions, and minimize friction to encourage users to adopt 2FA without frustration.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Secure Storage of Secrets
&lt;/h3&gt;

&lt;p&gt;Ensure the secure storage of user secrets and sensitive information related to 2FA. Implement robust encryption and hashing techniques to protect user data from unauthorized access or disclosure.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this tutorial, we've explored the implementation of two-factor authentication (2FA) in Golang web applications. We started by understanding the concept of 2FA and its significance in enhancing security for web applications.&lt;/p&gt;

&lt;p&gt;We discussed the prerequisites for implementing 2FA and provided step-by-step guidance on setting up the Golang environment and integrating a 2FA library into the project. We covered various aspects of 2FA implementation, including generating and storing secrets, handling user authentication, and validating TOTP codes.&lt;/p&gt;

&lt;p&gt;Now, you are ready to easily add 2FA in your Golang Web Application. You can find the complete project &lt;a href="https://github.com/Imranalam28/Golang-App-2FA" rel="noopener noreferrer"&gt;code in this GitHub Repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>tutorial</category>
      <category>authentication</category>
      <category>security</category>
    </item>
    <item>
      <title>Fine-Grained Access Control (FGAC): Comprehensive Guidance</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Wed, 12 Jun 2024 12:07:40 +0000</pubDate>
      <link>https://dev.to/permify/fine-grained-access-control-fgac-comprehensive-guidance-3f19</link>
      <guid>https://dev.to/permify/fine-grained-access-control-fgac-comprehensive-guidance-3f19</guid>
      <description>&lt;p&gt;Securing who can access what under which conditions,also known as authorization, is a crucial part of software systems due to scaled cloud-native environments, distinct and multi-service architectures, never-ending business requirements and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.permify.co/use-cases/rbac" rel="noopener noreferrer"&gt;Role Based Access Control (RBAC)&lt;/a&gt; is one of the most popular and traditional way to apply access controls in your applications and services. &lt;/p&gt;

&lt;p&gt;To give a brief explanation of RBAC, someone is assigned a role and they inherit the permissions associated with that role. For instance, managers might have access to certain files that entry-level employees do not.&lt;/p&gt;

&lt;p&gt;The pitfalls of RBAC model is; its coarse-grained, inflexible, and cannot scale.&lt;/p&gt;

&lt;p&gt;That's why most companies choose Fine-Grained Access Control over coarse grained RBAC.&lt;/p&gt;

&lt;p&gt;This guide is tailored to explain Fine-Grained Access Control (FGAC), highlight its significance, and provide a step-by-step implementation for your applications.&lt;/p&gt;

&lt;h2 id="what-is-fine-grained-access-control"&gt;What is Fine-Grained Access Control (FGAC)?&lt;/h2&gt;

&lt;p&gt;Fine-Grained Access Control is a detailed and nuanced approach to access control within your company's requirements. &lt;/p&gt;

&lt;p&gt;Unlike coarse grained access control models that might grant access to large sections of data or functions based on a single factor like roles, fine-grained authorization allows you to specify access rights at a much more specific level, including &lt;a href="https://docs.permify.co/use-cases/abac" rel="noopener noreferrer"&gt;Attribute-Based Access Control (ABAC)&lt;/a&gt; and &lt;a href="https://docs.permify.co/use-cases/rebac" rel="noopener noreferrer"&gt;Relationship-Based Access Control (ReBAC)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means you can define not just who can access a resource, but under what precise conditions they can do so, including actions like viewing, editing, sharing, or deleting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read More:&lt;/strong&gt; &lt;a href="https://permify.co/post/fine-grained-access-control-where-rbac-falls-short/" rel="noopener noreferrer"&gt;Fine-Grained Access Control Where RBAC falls short&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine a healthcare application that manages patient records. &lt;/p&gt;

&lt;p&gt;With fine-grained authorization, you can set up access controls that reflect the complex needs and privacy requirements of the healthcare industry. &lt;/p&gt;

&lt;p&gt;Here’s how it might work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Doctors:&lt;/strong&gt; Can view and edit the medical records of their current patients but cannot access records of patients they are not treating. Additionally, they might be allowed to share records with other doctors within the same hospital for consultation, but only if the patient has consented to this sharing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nurses:&lt;/strong&gt; Have view access to patient records but can only edit sections related to nursing care, such as notes on medication administration or patient vitals. Their access is limited to patients they are currently assigned to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Administrative Staff:&lt;/strong&gt; Can access patient contact information and billing details but cannot view medical history or notes made by the healthcare professionals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patients:&lt;/strong&gt; Can view their own medical records through a patient portal but cannot make any edits. They may be given the option to share their records with external healthcare providers, but this action requires explicit patient consent and generates an audit trail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By defining specific access controls for different user roles and conditions, the healthcare application can protect sensitive information, comply with privacy regulations, and ensure that users have the access they need to perform their roles effectively.&lt;/p&gt;

&lt;h2 id="why-companies-should-look-for-fine-grained-access-control"&gt;Why Companies Should Look for Fine-Grained Access Control?&lt;/h2&gt;

&lt;p&gt;Here are the compelling reasons why companies should prioritize fine-grained authorization:&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced Security
&lt;/h3&gt;

&lt;p&gt;By defining access with precision, fine-grained authorization minimizes the risk of unauthorized access to sensitive data. &lt;/p&gt;

&lt;p&gt;This precision ensures that individuals have access only to the data and functions necessary for their roles, significantly reducing the attack surface for potential cyber threats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compliance and Privacy
&lt;/h3&gt;

&lt;p&gt;Many industries are governed by strict regulatory requirements regarding data access and privacy (e.g., &lt;a href="https://www.consilium.europa.eu/en/policies/data-protection/data-protection-regulation/" rel="noopener noreferrer"&gt;GDPR in Europe&lt;/a&gt;, &lt;a href="https://www.techtarget.com/searchhealthit/definition/HIPAA" rel="noopener noreferrer"&gt;HIPAA&lt;/a&gt; in healthcare). &lt;/p&gt;

&lt;p&gt;Fine-Grained Access Control allows companies to meet these regulations head-on by enforcing access policies that protect personal and sensitive information, thereby avoiding hefty fines and reputational damage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operational Flexibility and Efficiency
&lt;/h3&gt;

&lt;p&gt;In the dynamic landscape of business operations, roles and responsibilities can change rapidly. &lt;/p&gt;

&lt;p&gt;Fine-Grained Access Control facilitates quick adjustments to access rights, ensuring that employees have the resources they need when they need them, without compromising security. This agility enhances overall operational efficiency and productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Audit and Oversight
&lt;/h3&gt;

&lt;p&gt;Implementing fine-grained authorization enables detailed logging and auditing of access to resources, providing clear visibility into who accessed what and when. &lt;/p&gt;

&lt;p&gt;This capability is invaluable for investigating security incidents, monitoring compliance, and refining access controls over time.&lt;/p&gt;

&lt;h2 id="how-to-build-a-fine-grained-access-control"&gt;How to Build a Fine-Grained Access Control?&lt;/h2&gt;

&lt;p&gt;In this section, we'll show how to implement Fine-Grained Access Control in our example Golang application&lt;/p&gt;

&lt;p&gt;For implementation we'll use &lt;a href="https://github.com/Permify/permify" rel="noopener noreferrer"&gt;Permify&lt;/a&gt;, an open source authorization service that enables developers to implement fine-grained access control scenarios easily. &lt;/p&gt;

&lt;p&gt;Let's dive deeper into how to use Permify to build a fine-grained authorization system, focusing particularly on the critical testing and validation phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding Permify&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Permify provides a robust platform for defining, managing, and enforcing fine-grained access controls. &lt;/p&gt;

&lt;p&gt;It allows you to specify detailed authorization rules that reflect real-world requirements, ensuring that users only access the resources they are allowed to, in accordance with their permissions to those resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up Permify&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt; Begin by running Permify as a Docker container. This approach simplifies setup and ensures consistency across environments.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3476:3476 &lt;span class="nt"&gt;-p&lt;/span&gt; 3478:3478 ghcr.io/permify/permify serve
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This command starts the Permify service, making it accessible via its REST and gRPC interfaces.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify Installation with Postman:&lt;/strong&gt; Postman is an effective tool for testing API endpoints. After launching Permify:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Postman and create a new request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the request type to GET.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter the URL &lt;code&gt;http://localhost:3476/healthz&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send the request. A successful setup is indicated by a 200 OK response, confirming that Permify is operational.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr14UsfFeC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr14UsfFeC.png" alt="Screenshot 2024-04-14 at 2.29.46 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Modeling Authorization with Permify Schema&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The schema is the heart of your authorization system, defining the entities involved and how they relate to each other. &lt;/p&gt;

&lt;p&gt;The provided schema example demonstrates a system similar to Google Docs, showcasing entities like &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;organization&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, and &lt;code&gt;document&lt;/code&gt;, along with their relationships and permissions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entities&lt;/strong&gt; represent the main components of your system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relations&lt;/strong&gt; outline how entities interact, e.g., which user owns a document or is part of a group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions&lt;/strong&gt; specify allowed actions based on roles within these relationships.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;entity user &lt;span class="o"&gt;{}&lt;/span&gt;

entity organization &lt;span class="o"&gt;{&lt;/span&gt;
    relation group @group
    relation document @document
    relation administrator @user @group#direct_member @group#manager
    relation direct_member @user

    permission admin &lt;span class="o"&gt;=&lt;/span&gt; administrator
    permission member &lt;span class="o"&gt;=&lt;/span&gt; direct_member or administrator or group.member
&lt;span class="o"&gt;}&lt;/span&gt;

entity group &lt;span class="o"&gt;{&lt;/span&gt;
    relation manager @user @group#direct_member @group#manager
    relation direct_member @user @group#direct_member @group#manager

    permission member &lt;span class="o"&gt;=&lt;/span&gt; direct_member or manager
&lt;span class="o"&gt;}&lt;/span&gt;

entity document &lt;span class="o"&gt;{&lt;/span&gt;
    relation org @organization

    relation viewer  @user  @group#direct_member @group#manager
    relation manager @user @group#direct_member @group#manager

    action edit &lt;span class="o"&gt;=&lt;/span&gt; manager or org.admin
    action view &lt;span class="o"&gt;=&lt;/span&gt; viewer or manager or org.admin
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the schema, the &lt;strong&gt;&lt;code&gt;@&lt;/code&gt;&lt;/strong&gt; symbol denotes the target of a relation (indicating a connection to another entity or a specific relation within an entity), while the &lt;strong&gt;&lt;code&gt;#&lt;/code&gt;&lt;/strong&gt; symbol specifies a particular relation within a target entity.&lt;/p&gt;

&lt;p&gt;Here's a breakdown of the schema components for clarity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;entity user {}&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Represents individual users in the system.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;entity organization&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;relation group &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;&lt;/strong&gt;: Links an organization to one or more groups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation document @document&lt;/strong&gt;: Connects an organization to documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation administrator @user &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#direct_member &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#manager&lt;/strong&gt;: Defines administrators of the organization as users who are either direct members of a group or managers within a group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation direct_member @user&lt;/strong&gt;: Identifies users who are direct members of the organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permission admin = administrator&lt;/strong&gt;: Grants administrator permissions to users defined as administrators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permission member = direct_member or administrator or group.member&lt;/strong&gt;: Assigns member permissions to users who are either direct members, administrators, or members of a group within the organization.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;entity group&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;relation manager @user &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#direct_member &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#manager&lt;/strong&gt;: Specifies the managers of the group, including users who are direct members of the group or designated as group managers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation direct_member @user &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#direct_member &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#manager&lt;/strong&gt;: Denotes direct members of the group, who can also be group managers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permission member = direct_member or manager&lt;/strong&gt;: Provides member permissions to users who are either direct members or managers of the group.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;entity document&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;relation org @organization&lt;/strong&gt;: Associates documents with their respective organizations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation viewer @user &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#direct_member &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#manager&lt;/strong&gt;: Defines viewers of the document as users who are either direct members or managers of a group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relation manager @user &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#direct_member &lt;a class="mentioned-user" href="https://dev.to/group"&gt;@group&lt;/a&gt;#manager&lt;/strong&gt;: Identifies managers of the document, which includes users who are direct members or managers in a group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;action edit = manager or org.admin&lt;/strong&gt;: Allows document editing by either the document's manager or the organization's administrators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;action view = viewer or manager or org.admin&lt;/strong&gt;: Permits viewing of the document by viewers, managers, or organization administrators.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementing Permify with Go SDK
&lt;/h2&gt;

&lt;p&gt;This section guides you through creating a simple Go application to implement Permify using its Go SDK. We assume that you already have your Permify environment set up and your schema ready.&lt;/p&gt;

&lt;p&gt;The following implementation only covers the crucial steps. To access the complete project, including all code, HTML, and CSS files, you can use this &lt;a href="https://github.com/Imranalam28/Permify-Go" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize the Permify Client
&lt;/h3&gt;

&lt;p&gt;To use the Permify SDK in a Go application, the first step is to establish a connection with the Permify server by initializing a client that communicates with the Permify service. &lt;/p&gt;

&lt;p&gt;This involves configuring the client with the endpoint of your Permify server and setting up the transport credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;permify_client.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="s"&gt;"github.com/Permify/permify-go/generated/base/v1"&lt;/span&gt;
    &lt;span class="n"&gt;permify&lt;/span&gt; &lt;span class="s"&gt;"github.com/Permify/permify-go/v1"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc/credentials/insecure"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;permify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="c"&gt;// setupPermifyClient initializes the Permify client and sets up the Permify schema.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;setupPermifyClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="c"&gt;// Initialize the Permify client&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;permify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permify&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Endpoint&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"localhost:3478"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Replace with the actual address of your Permify deployment&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTransportCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insecure&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCredentials&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="c"&gt;// Use insecure credentials for development&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create Permify client: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Setup Permify schema and other configurations&lt;/span&gt;
    &lt;span class="n"&gt;initPermifySchema&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;In this code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import necessary packages such as &lt;code&gt;context&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, and &lt;code&gt;time&lt;/code&gt; for context management, logging, and time-related operations, respectively.&lt;/li&gt;
&lt;li&gt;We import the Permify SDK packages &lt;code&gt;v1&lt;/code&gt; and &lt;code&gt;permify&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We import the &lt;code&gt;grpc&lt;/code&gt; package for setting up the gRPC connection with the Permify server.&lt;/li&gt;
&lt;li&gt;We import &lt;code&gt;credentials/insecure&lt;/code&gt; for setting up insecure transport credentials, suitable for development environments.&lt;/li&gt;
&lt;li&gt;We define a &lt;code&gt;setupPermifyClient()&lt;/code&gt; function that initializes the Permify client and sets up the Permify schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This function initializes the Permify client by specifying the endpoint of the Permify server and configuring transport credentials. It also handles any errors that occur during initialization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Define and Write the Schema
&lt;/h3&gt;

&lt;p&gt;Once you've initialized the Permify client, the next step is to define the schema for your application. The schema defines the entities, relationships between them, and the permissions associated with those relationships. Once the schema is defined, it must be written to the Permify service to be enforced.&lt;/p&gt;

&lt;h4&gt;
  
  
  Schema Definition
&lt;/h4&gt;

&lt;p&gt;The schema is defined using a domain-specific language (DSL) provided by Permify. This DSL allows you to specify entities, relationships, and permissions in a concise and human-readable format. Here's an example schema definition for a basic document management system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="n"&gt;organization&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;administrator&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;administrator&lt;/span&gt;
    &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;administrator&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;
    &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;organization&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;viewer&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;direct_member&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewer&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define four entities: &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;organization&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, and &lt;code&gt;document&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each entity can have relationships with other entities, specified using the &lt;code&gt;relation&lt;/code&gt; keyword.&lt;/li&gt;
&lt;li&gt;We define permissions (&lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;member&lt;/code&gt;) for the &lt;code&gt;organization&lt;/code&gt; entity based on its relationships with other entities.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;document&lt;/code&gt; entity has actions (&lt;code&gt;edit&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt;) associated with it, with permissions based on the relationships defined in the schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Writing the Schema
&lt;/h4&gt;

&lt;p&gt;Once the schema is defined, it must be written to the Permify service using the Permify client. This ensures that the access control rules defined in the schema are enforced by the Permify system. Here's how you can write the schema using the Permify client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;initPermifySchema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Define the schema&lt;/span&gt;
    &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`/* Schema definition goes here */`&lt;/span&gt;

    &lt;span class="c"&gt;// Write the schema to the Permify service&lt;/span&gt;
    &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaWriteRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TenantId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"t1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;schema&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to write schema: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;schemaVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaVersion&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Schema version %s written successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schemaVersion&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;In this code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We initialize a context with a timeout to ensure that the schema write operation doesn't hang indefinitely.&lt;/li&gt;
&lt;li&gt;We define the schema as a string using the DSL provided by Permify.&lt;/li&gt;
&lt;li&gt;We use the Permify client to write the schema to the Permify service, specifying the tenant ID and the schema itself.&lt;/li&gt;
&lt;li&gt;If the schema write operation is successful, we store the schema version for future reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Store Relationships and Permissions
&lt;/h3&gt;

&lt;p&gt;Once the schema has been defined and written, the next crucial step is populating the Permify system with specific instances of relationships and permissions according to your schema definitions. &lt;/p&gt;

&lt;p&gt;This involves creating data tuples that represent real-world relationships between the entities defined in your schema.&lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding Relationships and Permissions
&lt;/h4&gt;

&lt;p&gt;In the context of Permify, relationships and permissions are represented as tuples. These tuples articulate the connections between entities (such as a user and a document) and specify the kind of access allowed (e.g., viewing or editing). &lt;/p&gt;

&lt;p&gt;This structured format enables Permify to quickly evaluate access requests based on the predefined rules in your schema.&lt;/p&gt;

&lt;h4&gt;
  
  
  Writing Data Tuples Using the Permify Client
&lt;/h4&gt;

&lt;p&gt;To enforce the access control rules defined in your schema, you need to populate the Permify system with actual data that reflects the relationships in your application. &lt;/p&gt;

&lt;p&gt;This is typically done by writing data tuples to Permify after defining your schema. Each tuple represents a specific permission or relationship instance between entities.&lt;/p&gt;

&lt;p&gt;Here's how you can write data tuples using the Permify client in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;storeRelationships&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Write relationships between entities&lt;/span&gt;
    &lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataWriteRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TenantId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"t1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataWriteRequestMetadata&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;SchemaVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;schemaVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Tuples&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;Relation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"viewer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user1"&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="n"&gt;Entity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;Relation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"manager"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user3"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="c"&gt;// Add more tuples as needed&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to write data tuples: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;snapToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SnapToken&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data tuples written successfully, snapshot token: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snapToken&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;In this code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We initialize a context with a timeout to ensure that the data write operation doesn't hang indefinitely.&lt;/li&gt;
&lt;li&gt;We use the Permify client to write data tuples to the Permify service, specifying the tenant ID, schema version, and the tuples themselves.&lt;/li&gt;
&lt;li&gt;Each tuple defines a relationship between entities, such as a user being a viewer or manager of a document.&lt;/li&gt;
&lt;li&gt;If the data write operation is successful, we store the snapshot token for future reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By storing relationships and permissions in the Permify system, you enable it to enforce the access control rules defined in your schema effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Perform Access Checks
&lt;/h3&gt;

&lt;p&gt;After setting up the schema and storing relationships, the next critical step involves performing access checks to determine if a particular user has the necessary permissions to access a specific resource. &lt;/p&gt;

&lt;p&gt;This step is pivotal for enforcing the access control rules defined and stored in the Permify system.&lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding Access Checks
&lt;/h4&gt;

&lt;p&gt;Access checks involve querying the Permify system to evaluate whether a specified subject (e.g., a user) is allowed to perform a certain action (e.g., view or edit) on a resource (e.g., a document) based on the existing relationships and permissions. &lt;/p&gt;

&lt;p&gt;These checks enforce your application's security policies in real-time, ensuring that only authorized users can access specific resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementing Access Checks in the Application
&lt;/h4&gt;

&lt;p&gt;Access checks are typically triggered by user actions that require validation of permissions. For example, when a user attempts to access a protected page or resource, the application queries Permify to confirm whether the access should be allowed.&lt;/p&gt;

&lt;p&gt;Below is an example of how to implement an access check using the Permify client in a Go web application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;checkPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;checkResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PermissionCheckRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TenantId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"t1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PermissionCheckRequestMetadata&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;SnapToken&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;snapToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;SchemaVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;schemaVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Depth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;50&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;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to check permission '%s' for user '%s': %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;checkResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Can&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckResult_CHECK_RESULT_ALLOWED&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use the Permify client to perform a permission check, specifying the tenant ID, entity (document), permission, subject (user), and metadata.&lt;/li&gt;
&lt;li&gt;The access check result indicates whether the action is allowed (&lt;code&gt;CHECK_RESULT_ALLOWED&lt;/code&gt;) or denied.&lt;/li&gt;
&lt;li&gt;Proper error handling ensures that any errors encountered during the access check process are appropriately logged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing access checks in your application using Permify, you can enforce fine-grained access control policies, ensuring that only authorized users can perform specific actions on protected resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Run the Server and Handle HTTP Requests
&lt;/h3&gt;

&lt;p&gt;Once the Permify client is initialized, and the schema is defined and written to the Permify service, the next step is to run the web server and handle HTTP requests. This involves setting up HTTP routes, handling user authentication, and performing authorization based on the permissions defined in Permify.&lt;/p&gt;

&lt;h4&gt;
  
  
  Initializing Routes and HTTP Server
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;main.go&lt;/code&gt;, we initialize the HTTP routes and start the HTTP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setupPermifyClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Initialize Permify client and setup schema&lt;/span&gt;
    &lt;span class="n"&gt;setupRoutes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;       &lt;span class="c"&gt;// Initialize HTTP routes&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server started on :8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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 &lt;code&gt;setupPermifyClient()&lt;/code&gt; function initializes the Permify client and sets up the schema. The &lt;code&gt;setupRoutes()&lt;/code&gt; function initializes all the route handlers defined in &lt;code&gt;handlers.go&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Handling HTTP Requests
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;handlers.go&lt;/code&gt;, we define HTTP request handlers for different routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// setupRoutes initializes all the route handlers&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;setupRoutes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serveHome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c"&gt;// Handle requests to the home page&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handleLogin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Handle user login requests&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/protected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serveProtected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Handle requests to protected content&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;serveHome&lt;/code&gt;&lt;/strong&gt;: Handles requests to the home page (&lt;code&gt;/&lt;/code&gt;). It serves the login page HTML template.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;handleLogin&lt;/code&gt;&lt;/strong&gt;: Handles user login requests (&lt;code&gt;/login&lt;/code&gt;). It verifies user credentials and sets a session token cookie upon successful login.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;serveProtected&lt;/code&gt;&lt;/strong&gt;: Handles requests to protected content (&lt;code&gt;/protected&lt;/code&gt;). It checks if the user is authenticated and authorized to access the protected content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6: Running the Application
&lt;/h3&gt;

&lt;p&gt;To run the application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure your Permify server is running and accessible at the specified endpoint.&lt;/li&gt;
&lt;li&gt;Execute the Go application using:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   go run main.go handlers.go permify_client.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt; in your web browser to interact with the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using Other SDKs in Production
&lt;/h3&gt;

&lt;p&gt;While this example uses the Go SDK, Permify supports various SDKs suitable for different programming environments. Select the SDK that best fits your production needs to implement these functionalities seamlessly.&lt;/p&gt;

&lt;h2 id="how-can-you-save-time-and-money-with-fine-grained-access-control"&gt;How Can You Save Time and Money with Fine-Grained Access Control?&lt;/h2&gt;

&lt;p&gt;Fine-Grained Access Control offers a powerful way to secure your enterprise while remaining agile. Here’s how it saves time and money:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Administrative Overhead:&lt;/strong&gt; Automating access control reduces the need for manual intervention, freeing up your team to focus on other tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower Risk of Data Breaches:&lt;/strong&gt; By ensuring only the right people have access, you reduce the potential costs associated with data breaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased Productivity:&lt;/strong&gt; Employees have the access they need when they need it, without unnecessary barriers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, fine-grained access control is not just about securing your enterprise; it’s about enabling it to move faster, more securely, and more efficiently. &lt;/p&gt;

&lt;p&gt;By choosing the right authorization model, leveraging tools like Permify, and understanding the balance between granularity and manageability, you can build a robust access control system that scales with your needs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>architecture</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Implementing Role Based Access Control (RBAC) in Node.js and Express App</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Wed, 05 Jun 2024 15:54:26 +0000</pubDate>
      <link>https://dev.to/permify/implementing-role-based-access-control-rbac-in-nodejs-and-express-app-5df4</link>
      <guid>https://dev.to/permify/implementing-role-based-access-control-rbac-in-nodejs-and-express-app-5df4</guid>
      <description>&lt;p&gt;To ensure  that only authorized users can access specific features and data within an application, implementing Role-Based Access Control (RBAC) is essential.&lt;/p&gt;

&lt;p&gt;In this article, I will show you how to implement RBAC into a Node.js and Express application using Permify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Setting Up Node.js Express Project&lt;/li&gt;
&lt;li&gt;
Implementing RBAC in Node.js and Express App

&lt;ul&gt;
&lt;li&gt;Step 1: Designing the RBAC Model With Permify&lt;/li&gt;
&lt;li&gt;Step 2: Setting Up a Permify Local Server with Docker&lt;/li&gt;
&lt;li&gt;
Step 3: Initialize Permify Node.js Client &lt;/li&gt;
&lt;li&gt;
Step 4: Configure Authorization Model &lt;/li&gt;
&lt;li&gt;Step 5: Creating Access Control Middleware&lt;/li&gt;
&lt;li&gt;Step 6: Securing Routes with RBAC&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Testing RBAC Implementation&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2 id="setting-up-expressjs-project"&gt;Setting Up Node.js Express Project&lt;/h2&gt;

&lt;p&gt;To quickly create an application skeleton for your Express.js project, you can use the &lt;code&gt;express-generator&lt;/code&gt; tool. &lt;/p&gt;

&lt;p&gt;Follow these steps to get started:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Install express-generator:
&lt;/h3&gt;

&lt;p&gt;If you're using Node.js version 8.2.0 or later, you can run the application generator using the npx command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx express-generator


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

&lt;/div&gt;

&lt;p&gt;For earlier Node versions, you can install the application generator as a global npm package:&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; &lt;span class="nt"&gt;-g&lt;/span&gt; express-generator


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 2. Generate Your Express Application:
&lt;/h3&gt;

&lt;p&gt;Once you have &lt;code&gt;express-generator&lt;/code&gt; installed, you can create your Express application. Display the command options with the &lt;code&gt;-h&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

express &lt;span class="nt"&gt;-h&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This will show you the available options for generating your Express application.&lt;/p&gt;

&lt;p&gt;For example, to create an Express app named &lt;code&gt;permify-rbac-app&lt;/code&gt; with the Pug view engine, you can run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

express &lt;span class="nt"&gt;--view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pug permify-rbac-app


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

&lt;/div&gt;

&lt;p&gt;This command will create a folder named &lt;code&gt;permify-rbac-app&lt;/code&gt; in the current working directory, along with the necessary files and folders for your Express application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3. Install Dependencies:
&lt;/h3&gt;

&lt;p&gt;Navigate into your newly created Express application directory:&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;cd &lt;/span&gt;permify-rbac-app


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

&lt;/div&gt;

&lt;p&gt;Then, install the project dependencies using &lt;code&gt;npm&lt;/code&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 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; @permify-node


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 4. Start Your Express Application:
&lt;/h3&gt;

&lt;p&gt;On MacOS or Linux, you can start the app with the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;permify-rbac-app:&lt;span class="k"&gt;*&lt;/span&gt; npm start


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 5. Access Your Application:
&lt;/h3&gt;

&lt;p&gt;Once your Express application is running, you can access it in your browser at &lt;code&gt;http://localhost:3000/&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Directory Structure:
&lt;/h3&gt;

&lt;p&gt;The generated Express application will have the following directory structure:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

permify-rbac-app/
├── app.js
├── bin/
│   └── www
├── package.json
├── public/
│   ├── images/
│   ├── javascripts/
│   └── stylesheets/
│       └── style.css
├── routes/
│   ├── index.js
│   └── users.js
└── views/
    ├── error.pug
    ├── index.pug
    └── layout.pug


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

&lt;/div&gt;

&lt;p&gt;This structure includes the main application file (app.js), the server configuration (bin/www), routes, views, public assets, and the package.json file with project dependencies.&lt;/p&gt;

&lt;p&gt;Now that you have set up our Express.js project, we'll proceed to implement RBAC to our Express application.&lt;/p&gt;

&lt;h2 id="implementing-rbac-in-nodejs-and-express"&gt;Implementing RBAC in Node.js and Express&lt;/h2&gt;

&lt;p&gt;Implementing Role-Based Access Control (RBAC) in a Node.js and Express application involves several steps. Here's a basic implementation:&lt;/p&gt;

&lt;h3 id="designing-the-rbac-model-with-permify"&gt;Step 1: Designing the RBAC Model with Permify&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Permify/permify" rel="noopener noreferrer"&gt;Permify&lt;/a&gt; is an open source authorization service that allows developers to create authorization systems. With Permify you can model your authorization, create central authorization service in your environment and perform access checks from your applications and services.&lt;/p&gt;

&lt;p&gt;It does this by providing client SDKs, which you can add into your middleware to send authorization requests, such as access check.&lt;/p&gt;

&lt;p&gt;Permify offers a powerful domain-specific language (DSL) to define roles, permissions, and relationships. You can utilize the &lt;a href="https://play.permify.co/?s=rbac" rel="noopener noreferrer"&gt;Permify Playground&lt;/a&gt; to experiment and visualize your RBAC model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkeAJdrJ0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkeAJdrJ0.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this post, we will develop a simple file-based authorization system where users within your organization can access documents based on their roles. &lt;/p&gt;

&lt;p&gt;Different roles such as Admin, Manager, and Employee may have different levels of access to view, edit, or delete files. &lt;/p&gt;

&lt;h4&gt;
  
  
  Defining Roles and Permissions with Permify DSL
&lt;/h4&gt;

&lt;p&gt;Below is an example Permify DSL schema for our RBAC model:&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;entity&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;entity&lt;/span&gt; &lt;span class="nx"&gt;organization&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// roles &lt;/span&gt;
    &lt;span class="nx"&gt;relation&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;user&lt;/span&gt;    
    &lt;span class="nx"&gt;relation&lt;/span&gt; &lt;span class="nx"&gt;member&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;user&lt;/span&gt;    
    &lt;span class="nx"&gt;relation&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;user&lt;/span&gt;    
    &lt;span class="nx"&gt;relation&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;user&lt;/span&gt;  

    &lt;span class="c1"&gt;// organization files access permissions&lt;/span&gt;
    &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="nx"&gt;view_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt; &lt;span class="nf"&gt;or &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="nx"&gt;delete_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; 

    &lt;span class="c1"&gt;// vendor files access permissions&lt;/span&gt;
    &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="nx"&gt;view_vendor_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;
    &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="nx"&gt;delete_vendor_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;

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


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Roles and Permissions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Roles&lt;/strong&gt;: The schema defines roles for the organization entity, including &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;member&lt;/code&gt;, &lt;code&gt;manager&lt;/code&gt;, and &lt;code&gt;agent&lt;/code&gt;. These roles determine the level of access and permissions users have within the organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions&lt;/strong&gt;: Actions such as &lt;code&gt;view_files&lt;/code&gt;, &lt;code&gt;edit_files&lt;/code&gt;, &lt;code&gt;delete_file&lt;/code&gt;, &lt;code&gt;view_vendor_files&lt;/code&gt;, &lt;code&gt;edit_vendor_files&lt;/code&gt;, and &lt;code&gt;delete_vendor_file&lt;/code&gt; define the specific permissions associated with each role. For example, only admins can delete organization files, while managers and members have different levels of access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resource Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The schema distinguishes between organization files and vendor files, each with its own set of permissions. This allows for granular control over access to different types of resources within the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have our RBAC schema defined, we'll proceed to setting up an Permify Local Server.&lt;/p&gt;

&lt;h3 id="setting-up-a-permify-local-server-with-docker"&gt;Step 2: Setting Up a Permify Local Server with Docker&lt;/h3&gt;

&lt;p&gt;Docker plays a crucial role in our setup by providing a containerized environment. &lt;/p&gt;

&lt;p&gt;This environment is essential for the efficient operation of Permify, which functions as a microservice responsible for all authorization queries. &lt;/p&gt;

&lt;p&gt;Now we will cover the steps needed to set up the Permify Server with using Docker Container below:&lt;/p&gt;

&lt;h4&gt;
  
  
  Run Permify Server with Docker Container
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open a terminal window and run the following command to pull the Permify Server Docker image and start the container:
```sh
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;sudo docker run -p 3476:3476 -p 3478:3478 ghcr.io/permify/permify serve&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This command will download the Permify Server image from the GitHub Container Registry and sets up Permify, our authorization service, with the following default settings:

- The REST API running on port 3476.
- The gRPC Service running on port 3478.
- Authorization data is stored in the computer's memory.

You should see a message similar to this:
```bash


┌────────────────────────────────────────────────────────┐
│                    Permify v0.8.5                      │
│          Fine-grained Authorization Service            │
│                                                        │
│    docs: ............... https://docs.permify.co       │
│    github: .. https://github.com/Permify/permify       │
│    blog: ............... https://permify.co/blog       │
│                                                        │
└────────────────────────────────────────────────────────┘
time=2024-03-22T14:59:09.851Z level=INFO msg="🚀 starting permify service..."
time=2024-03-22T14:59:09.851Z level=ERROR msg="Account ID is not set. Please fill in the Account ID for better support. Get your Account ID from https://permify.co/account"
time=2024-03-22T14:59:09.859Z level=INFO msg="🚀 grpc server successfully started: 3478"
time=2024-03-22T14:59:09.859Z level=INFO msg="🚀 invoker grpc server successfully started: 5000"
time=2024-03-22T14:59:09.867Z level=INFO msg="🚀 http server successfully started: 3476"


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Verify Permify Server
&lt;/h4&gt;

&lt;p&gt;Once the container is running, you can verify that Permify Server is running correctly by accessing the health check endpoint. Open Postman and send a GET request to &lt;code&gt;http://localhost:3476/healthz&lt;/code&gt;. If Permify Server is running correctly, you should see a response indicating that the service is healthy.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkW9t_BeR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkW9t_BeR.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above image shows that Permify Server is up and running, you can now proceed with integrating it into your Node.js and Express application.&lt;/p&gt;

&lt;h3 id="initialize-permify-node-client"&gt;Step 3: Initialize Permify Node.js Client&lt;/h3&gt;

&lt;p&gt;In this tutorial, we'll use &lt;a href="https://github.com/Permify/permify-node" rel="noopener noreferrer"&gt;Permify Node Client&lt;/a&gt; to control authorization in our application. You can find the list of available endpoints in our &lt;a href="https://permify.github.io/permify-swagger/" rel="noopener noreferrer"&gt;Permify Swagger Docs&lt;/a&gt;. We'll be using Permify's access control checks to safeguard our endpoints. &lt;/p&gt;

&lt;p&gt;Let's initialize our our client,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// create-tenant.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permify&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;@permify/permify-node&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;permify&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="nf"&gt;newClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&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:3478&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;h3 id="configure-authorization-model"&gt;Step 4: Configure Authorization Model&lt;/h3&gt;

&lt;p&gt;Now as our Permify Server running, we need to configure our authorization model to Permify service and then we can ready to perform test access checks.&lt;/p&gt;

&lt;p&gt;To configure the authorization model, we'll send the schema we created to Permify using the Permify &lt;a href="https://docs.permify.co/api-reference/schema/write-schema" rel="noopener noreferrer"&gt;schema.write&lt;/a&gt; method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//create-schema.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permify&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;@permify/permify-node&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;permify&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="nf"&gt;newClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&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:3478&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;entity user {} &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;entity organization {&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;    relation admin @user    &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    relation member @user    &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    relation manager @user    &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    relation agent @user  &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;    action view_files = admin or manager or (member not agent)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    action edit_files = admin or manager&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    action delete_file = admin&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    action view_vendor_files = admin or manager or agent&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    action edit_vendor_files = admin or agent&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    action delete_vendor_file = agent&lt;/span&gt;&lt;span class="se"&gt;\n\n&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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="c1"&gt;// handle response&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;response&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;This code above creates a new schema using the Permify library. &lt;/p&gt;

&lt;p&gt;It is built to connect to the Permify server running on localhost port &lt;code&gt;3478&lt;/code&gt; and then calls the write method to define a schema for the specified tenant &lt;code&gt;t1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The schema defines entities such as &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;organization&lt;/code&gt; along with their relationships and actions. &lt;/p&gt;

&lt;p&gt;Now, let's run this script&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

node create-schema.js


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkdSEFHlR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkdSEFHlR.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the output in screenshot above, you can see that the new schema was successfully configured using Permify Node Js Client.&lt;/p&gt;

&lt;p&gt;Hooray! 🥳 We've successfully finished setting up the Permify authorization service. Our API is now up and running with the authorization model configured and ready for use! &lt;/p&gt;

&lt;p&gt;In the next step, we will be creating the middleware for access control.&lt;/p&gt;

&lt;h3 id="create-access-control-middleware"&gt;Step 5: Creating Access Control Middleware &lt;/h3&gt;

&lt;p&gt;Here I will show  an example of how we'll develop Express middleware to enforce role-based access control on routes. &lt;/p&gt;

&lt;p&gt;You will also learn how to implement Permify access check endpoint in the middleware to verify a user's role and permissions before allowing access to protected resources.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// auth.js&lt;/span&gt;

&lt;span class="c1"&gt;// Import Permify client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permify&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;@permify/permify-node&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;permify&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="nf"&gt;newClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&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:3478&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="c1"&gt;// Middleware function to check user's permissions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissionType&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="k"&gt;async &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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Ensure req.params.id exists&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;req&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&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 ID is missing in the request parameters&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="c1"&gt;// Convert permissionType to string if necessary&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permTypeString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissionType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Prepare data for Permify check request&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkRes&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;schemaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;snapToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;organization&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&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;permission&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;permTypeString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Use the converted permissionType&lt;/span&gt;
        &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&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&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;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="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;checkRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// If user is authorized&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;authorized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorized&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// If user is not authorized&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;authorized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not authorized&lt;/span&gt;&lt;span class="dl"&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="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="nx"&gt;err&lt;/span&gt;&lt;span class="p"&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error checking permissions:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Log the actual error message&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;500&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="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Send the actual error message to the client for debugging purposes&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;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The code above is built with the aim to implement a middleware function, &lt;a href="https://docs.permify.co/api-reference/permission/check-api" rel="noopener noreferrer"&gt;checkPermission&lt;/a&gt; by utilizing the Permify library to verify user permissions based on the provided permission type. &lt;/p&gt;

&lt;p&gt;When executed it extracts the user ID from the request parameters, converts the permission type to a string if needed, then sends a permission check request using Permify's &lt;code&gt;"permission.check"&lt;/code&gt; method to the Permify server. If authorized, it adds &lt;code&gt;"authorized"&lt;/code&gt; to the request object; otherwise, it adds &lt;code&gt;"not authorized"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Errors are further logged and returned to the client for debugging purposes.&lt;/p&gt;

&lt;p&gt;Next, we'll integrate the middleware that was created above into our Node.js and Express application to enforce Role-Based Access Control (RBAC) and ensure that only authorized users with the appropriate roles and permissions can access specific routes.&lt;/p&gt;

&lt;h3 id="securing-the-routes"&gt;Step 6: Securing Routes with RBAC&lt;/h3&gt;

&lt;p&gt;Now, let's secure our routes using the middleware we've created. We'll apply the &lt;code&gt;checkPermissions&lt;/code&gt; middleware to protect various routes in our application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// app.js&lt;/span&gt;

&lt;span class="c1"&gt;// Import required modules&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;permify&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;@permify/permify-node&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;authMiddleware&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;./auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Import the auth middleware&lt;/span&gt;

&lt;span class="c1"&gt;// Create Express app&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="c1"&gt;// Define custom middleware to populate userInfo&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;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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Simulate user authentication and populate userInfo&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;userInfo&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;req&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="c1"&gt;// Extract the id from request params&lt;/span&gt;
    &lt;span class="c1"&gt;// Add other user information if required&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="c1"&gt;// Define routes&lt;/span&gt;

&lt;span class="c1"&gt;// Route for '/users/:id' where you want to enforce permission check&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="s1"&gt;/users/viewFiles/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view_files&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="c1"&gt;// If middleware allows the request to pass through, handle the route logic here&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorized&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorized&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You have access to this user route&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;else&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;403&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="s1"&gt;You are not authorized to access this user resource&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="c1"&gt;// Route for '/admin/deleteVendorFiles/:id' where you want to enforce permission check&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="s1"&gt;/admin/deleteVendorFiles/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete_vendor_file&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="c1"&gt;// If middleware allows the request to pass through, handle the route logic here&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorized&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorized&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You have access to this admin route&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;else&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;403&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="s1"&gt;You are not authorized to access this admin resource&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="c1"&gt;// Start the server&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="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&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;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;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;This code sets up your Express application on port 3000 where specific routes are protected using a custom middleware called &lt;code&gt;authMiddleware&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This middleware, imported from the &lt;code&gt;auth.js&lt;/code&gt; file, integrates with Permify for permission checks. Below are routes being protected by the Middleware;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routes protected by the &lt;code&gt;authMiddleware&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route for &lt;code&gt;/users/viewFiles/:id&lt;/code&gt;: This route ensures that only users have permission to view files can access this route.&lt;/li&gt;
&lt;li&gt;Route for &lt;code&gt;/admin/viewFiles/:id&lt;/code&gt;: This route ensures that only admins who have permission to delete vendor files can access this route.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By applying the &lt;code&gt;authMiddleware&lt;/code&gt; to these routes, access is restricted based on the permissions granted by Permify.&lt;/p&gt;

&lt;p&gt;Let's test our implementation!&lt;/p&gt;

&lt;h2 id="testing-rbac-implementation"&gt;Testing RBAC Implementation&lt;/h2&gt;

&lt;p&gt;Let's say we have a user with userID &lt;code&gt;alice&lt;/code&gt;, Let's test to see if alice can access the &lt;code&gt;/users/viewFiles/&lt;/code&gt; API endpoint which is only accessible by admins, managers or members that are not agents as we defined in our schema earlier in this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrJL8Z7VeR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrJL8Z7VeR.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As expected, the UserID &lt;code&gt;alice&lt;/code&gt; doesn't have access to this API endpoint, Let's give &lt;code&gt;alice&lt;/code&gt; the member role using Permify Nodejs client's &lt;a href="https://docs.permify.co/api-reference/data/write-data" rel="noopener noreferrer"&gt;data.write&lt;/a&gt; method:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// write-relationship.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permify&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;@permify/permify-node&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;permify&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="nf"&gt;newClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&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:3478&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;schemaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;tuples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;organization&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;member&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&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="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;alice&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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="c1"&gt;// handle response&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;response&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;Let's run this code and try visiting the &lt;code&gt;/users/viewFiles/&lt;/code&gt; API endpoint using Postman.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJoENQNlR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJoENQNlR.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, after running the code, Alice can now successfully access the &lt;code&gt;/users/viewFiles/&lt;/code&gt; API endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt; All the code snippets featured in this article can be found in the corresponding &lt;a href="https://github.com/EbukaNduka/PERMIFY-RBAC-APP" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It's important to recognize that authorization isn't a one-time setup; it's an ongoing process. &lt;/p&gt;

&lt;p&gt;Therefore, it's imperative to regularly review your model, conduct thorough testing, and adapt it as your application evolves.&lt;/p&gt;

&lt;p&gt;This guide serves as a solid foundation for implementing RBAC in your Node.js application. &lt;/p&gt;

&lt;p&gt;However, don't hesitate to delve deeper and tailor the RBAC model to precisely fit your unique requirements. &lt;/p&gt;

&lt;p&gt;By harnessing the capabilities of Permify, you can streamline permission management and cultivate a resilient and secure application environment.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
    <item>
      <title>Implementing Role Based Access Control in SvelteKit</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Thu, 30 May 2024 11:43:46 +0000</pubDate>
      <link>https://dev.to/permify/implementing-role-based-access-control-in-sveltekit-56hf</link>
      <guid>https://dev.to/permify/implementing-role-based-access-control-in-sveltekit-56hf</guid>
      <description>&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Understanding Role-Based Access Control (RBAC)&lt;/li&gt;
&lt;li&gt;Setting Up the SvelteKit Project&lt;/li&gt;
&lt;li&gt;
Integrating RBAC Configurations and Utilities

&lt;ul&gt;
&lt;li&gt;Defining Roles and Permissions&lt;/li&gt;
&lt;li&gt;Implementing RBAC Utility Functions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Dynamic Navigation Based on User Roles&lt;/li&gt;

&lt;li&gt;Securing Routes Based on User Roles&lt;/li&gt;

&lt;li&gt;Managing Permissions Within Components&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before you begin, you'll need to have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Basic knowledge of SvelteKit&lt;/strong&gt;: Familiarity with SvelteKit's core concepts, like routing, components, and stores, will be helpful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js and npm:&lt;/strong&gt; You'll need to have Node.js and npm (Node Package Manager) installed on your system. If you haven't already, you can download and install them from the official &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git:&lt;/strong&gt; Ensure you have Git installed on your machine. If not, you can download it from the &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git website&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/Permify/permify/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPermify%2Fpermify%2Fassets%2F34595361%2F440284b3-a8d6-4c6b-a17f-116c49e72a58" alt="Github Banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="understanding-role-based-access-control-rbac"&gt;Understanding Role-Based Access Control (RBAC)&lt;/h2&gt;

&lt;p&gt;RBAC is a security model that organizes user permissions based on their roles within an application. &lt;/p&gt;

&lt;p&gt;Each role is associated with a set of permissions, and users are assigned specific roles to determine what they can access.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Roles and Permissions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Roles represent a collection of related permissions that define what a user can do within an application. &lt;/p&gt;

&lt;p&gt;For instance, an application might have roles such as &lt;code&gt;Admin&lt;/code&gt;, &lt;code&gt;Editor&lt;/code&gt;, and &lt;code&gt;Viewer&lt;/code&gt; each with different sets of permissions. &lt;/p&gt;

&lt;p&gt;Permissions, on the other hand, are specific actions or operations that a user with a particular role can perform. &lt;/p&gt;

&lt;p&gt;These can range from viewing and editing data to managing user accounts or system configurations.&lt;/p&gt;

&lt;h2 id="setting-up-the-sveltekit-project"&gt;Setting Up the SvelteKit Project&lt;/h2&gt;

&lt;p&gt;Before we start implementing RBAC, we need a SvelteKit project ready to work with. &lt;/p&gt;

&lt;p&gt;To keep things simple, we'll use a demo e-commerce project as our starting template. The complete code for this project can be found in this &lt;a href="https://github.com/TropicolX/svelte-rbac-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get the starter template, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/TropicolX/svelte-rbac-demo.git
&lt;span class="nb"&gt;cd &lt;/span&gt;svelte-rbac-demo
git checkout starter
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project structure should look like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948411%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F962ef8aa-a41c-467c-957a-2ef9a394771b_rrhaoa.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948411%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F962ef8aa-a41c-467c-957a-2ef9a394771b_rrhaoa.png%3Falign%3D" alt="Screenshot of project structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's go over the essential files and directories we'll be working with for the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/lib&lt;/code&gt;: This directory will contain all our utilities and components.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/routes&lt;/code&gt;: Contains all the routes in our application.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/(protected)&lt;/code&gt;: This folder contains all our protected routes. Only signed-in users may be able to navigate these routes.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/login&lt;/code&gt;: This is the route to the login page.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/unauthorized&lt;/code&gt;: This is the route we redirect users to when they are unauthorized in accessing a page.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+layout.svelte&lt;/code&gt;: This contains the UI layout and logic that applies to every page.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+page.svelte&lt;/code&gt;: This is our home page route.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;hooks.server.js&lt;/code&gt;: This file contains all the server-side logic we need to authenticate users when they navigate to a protected route and to redirect them when necessary. It also fetches the user data on the server and stores it in the &lt;a href="https://kit.svelte.dev/docs/hooks#server-hooks-handle" rel="noopener noreferrer"&gt;&lt;code&gt;event.locals&lt;/code&gt;&lt;/a&gt; object.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Project Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To start the project, run the following command in the root directory:&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 dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a page like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948453%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F62341754-6934-42db-a036-f0af349c3547_t34a4d.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948453%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F62341754-6934-42db-a036-f0af349c3547_t34a4d.png%3Falign%3D" alt="Screenshot of e-commerce project home page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's sign in to the app. Click the "Sign in" button at the top right corner of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948502%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Feb66d3a3-bbd9-4043-8b75-81d6771574e8_mqbx5k.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948502%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Feb66d3a3-bbd9-4043-8b75-81d6771574e8_mqbx5k.png%3Falign%3D" alt="Sign in page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can sign in as either an admin or a customer using the following credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Admin:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email:&lt;/strong&gt; &lt;code&gt;admin@gmail.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password:&lt;/strong&gt; &lt;code&gt;admin123&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Customer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email:&lt;/strong&gt; &lt;code&gt;john@mail.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password:&lt;/strong&gt; &lt;code&gt;changeme&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;After signing in, you will be redirected to the home page and should able to see two new links on the navbar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin link&lt;/li&gt;
&lt;li&gt;Profile link&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948530%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Ff3fbe006-582e-46da-a3fe-c537619ebd72_vyxsai.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948530%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Ff3fbe006-582e-46da-a3fe-c537619ebd72_vyxsai.png%3Falign%3D" alt="Initial home page when signed in"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This brings us to the current problem with our e-commerce app: We need to ensure that only admins can access the admin page, and similarly, only customers can access the profile page.&lt;/p&gt;

&lt;p&gt;Additionally, we need to ensure that only admins and customers with the required permissions can perform specific actions within their respective pages. &lt;/p&gt;

&lt;p&gt;For instance, only an admin with permission to create products should be able to do so on the admin page.&lt;/p&gt;

&lt;h2 id="integrating-rbac-configurations-and-utilities"&gt;Integrating RBAC Configurations and Utilities&lt;/h2&gt;

&lt;p&gt;Now that we've set up and familiarized ourselves with the Svelekit project let's begin implementing RBAC in our app. We'll start by defining the roles and permissions within the app.&lt;/p&gt;

&lt;h3 id="defining-roles-and-permissions"&gt;Defining Roles and Permissions&lt;/h3&gt;

&lt;p&gt;In the SvelteKit project, create a new file called &lt;code&gt;constants.js&lt;/code&gt; in the &lt;code&gt;src&lt;/code&gt; directory and add the following 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="c1"&gt;// src/constants.js&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;ROLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ADMIN&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="na"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;CREATE_PRODUCTS&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:products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;UPDATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update:products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;DELETE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;delete:products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;READ_PROFILE&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:profile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;UPDATE_PROFILE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update:profile&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;In the code above, we defined our app's roles and permission constants.&lt;/p&gt;

&lt;p&gt;Next, we need to define the permissions each role has. Navigate to the &lt;code&gt;lib&lt;/code&gt; directory and create a &lt;code&gt;rolePermissions.js&lt;/code&gt; file with the following 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="c1"&gt;// src/lib/rolePermissions.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../constants&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;rolePermissions&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CREATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DELETE_PRODUCTS&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;READ_PROFILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PROFILE&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 code above sets up each of the roles with specific permissions. We want admin users to be able to create, update, and delete products. &lt;/p&gt;

&lt;p&gt;On the other hand, we want customers to be able to read and update their profile details.&lt;/p&gt;

&lt;h3 id="implementing-rbac-utility-functions"&gt;Implementing RBAC Utility Functions&lt;/h3&gt;

&lt;p&gt;Next, let's create some utility functions to check if a user has a certain role or permission. These functions will enforce access control throughout the app.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;lib&lt;/code&gt; directory, create a &lt;code&gt;rbacUtils.js&lt;/code&gt; file and add the following 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="c1"&gt;// src/lib/rbacUtils.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rolePermissions&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;./rolePermissions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Function to check if a user has a specific role&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkRole&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;requiredRole&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="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="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="k"&gt;return&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="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;requiredRole&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function to check if a user has specific permissions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&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;requiredPermissions&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="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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rolePermissions&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;userPermissions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requiredPermissions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function to check if a user has both a specific role and permissions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkRoleAndPermissions&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;requiredRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;requiredPermissions&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="nf"&gt;checkRole&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;requiredRole&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nf"&gt;checkPermissions&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;requiredPermissions&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;With these configurations in place, we can start integrating RBAC within our app.&lt;/p&gt;

&lt;h2 id="dynamic-navigation-based-on-user-roles"&gt;Dynamic Navigation Based on User Roles&lt;/h2&gt;

&lt;p&gt;The navigation UI is the first area in our app where we'll implement RBAC. We need to ensure that users see only the navigation links relevant to their roles.&lt;/p&gt;

&lt;p&gt;Firstly, head over to the &lt;code&gt;+layout.svelte&lt;/code&gt; file in the &lt;code&gt;routes&lt;/code&gt; folder and add the following 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="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;/+&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&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;import&lt;/span&gt; &lt;span class="nx"&gt;Loading&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;$lib/components/Loading.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkRole&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;$lib/rbacUtils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../constants&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&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;cart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;products&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;../stores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../app.css&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;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkRole&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isCustomer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkRole&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;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 defined two variables, &lt;code&gt;isAdmin&lt;/code&gt; and &lt;code&gt;isCustomer&lt;/code&gt;, which check if the user is an admin or a customer, respectively. We also used reactive declarations to define the variables so that any changes to the user data, e.g., if the user logs out, will update their values.&lt;/p&gt;

&lt;p&gt;Next, let's update our navigation links:&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="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;/+&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-gray-900 text-white py-4 px-6 md:px-12 flex items-center justify-between&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hidden md:flex items-center space-x-6&lt;/span&gt;&lt;span class="dl"&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="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hover:text-gray-300&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Admin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;isCustomer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hover:text-gray-300&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/nav&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948598%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F51ff4981-2756-4d54-8b91-0311b149b3c6_xptqub.gif%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948598%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F51ff4981-2756-4d54-8b91-0311b149b3c6_xptqub.gif%3Falign%3D" alt="Demo of dynamic navigation implementation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the navigation links for the admin and profile pages will be displayed conditionally based on the user's role.&lt;/p&gt;

&lt;h2 id="securing-routes-based-on-user-roles"&gt;Securing Routes Based on User Roles&lt;/h2&gt;

&lt;p&gt;In the previous section, we added dynamic client-side navigation based on user roles. However, users may still be able to navigate to unauthorized routes by using the browser navigation. To prevent this, we need to secure the routes directly by adding role-based protection.&lt;/p&gt;

&lt;p&gt;We can do this in Svelte by adding a &lt;code&gt;+layout.server.js&lt;/code&gt; file in each route to run a server-side &lt;code&gt;load&lt;/code&gt; function. The load function will run whenever the user loads the page and will check whether the user has access to the route based on their role. If they are not authorized, they will be redirected to the &lt;code&gt;/unauthorized&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;Let's start by implementing this on the admin page. Head over to the &lt;code&gt;admin&lt;/code&gt; directory in the &lt;code&gt;(protected)&lt;/code&gt; folder, create a &lt;code&gt;+layout.server.js&lt;/code&gt; file with the following 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="c1"&gt;// src/routes/(protected)/admin/+layout.server.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;redirect&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;@sveltejs/kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkRole&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;$lib/rbacUtils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../constants&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('./$types').LayoutServerLoad} */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;locals&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locals&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkRole&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&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;isAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;307&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948663%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fa2d604ab-c976-42fc-9fcb-e4ae936c11bd_sa4ozo.gif%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948663%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fa2d604ab-c976-42fc-9fcb-e4ae936c11bd_sa4ozo.gif%3Falign%3D" alt="Demo for securing admin route"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if a non-admin user attempts to access the admin route, they will be redirected appropriately.&lt;/p&gt;

&lt;p&gt;Next, let's secure our &lt;code&gt;user&lt;/code&gt; route. Within the &lt;code&gt;(protected)&lt;/code&gt; folder, navigate to the &lt;code&gt;user&lt;/code&gt; directory and create a &lt;code&gt;+layout.server.js&lt;/code&gt; file with the following 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="c1"&gt;// src/routes/(protected)/user/+layout.server.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;redirect&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;@sveltejs/kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkRoleAndPermissions&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;$lib/rbacUtils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../constants&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('./$types').LayoutServerLoad} */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;locals&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locals&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isCustomerAndCanViewProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkRoleAndPermissions&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;READ_PROFILE&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;isCustomerAndCanViewProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;307&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948720%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fc3a93ae8-6ec6-496f-ac40-ce6492780265_rqkhwf.gif%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948720%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fc3a93ae8-6ec6-496f-ac40-ce6492780265_rqkhwf.gif%3Falign%3D" alt="Demo for securing user route"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we're doing things a bit differently by using the &lt;code&gt;checkRoleAndPermissions&lt;/code&gt; function to ensure the user is both a customer and has permission to read a profile before being able to access the profile page. &lt;/p&gt;

&lt;p&gt;This function can be helpful in more complex scenarios where a role might have additional or custom permissions different from the default permissions.&lt;/p&gt;

&lt;p&gt;Next let's look at how to manage role permissions within components.&lt;/p&gt;

&lt;h2 id="managing-permissions-within-components"&gt;Managing Permissions Within Components&lt;/h2&gt;

&lt;p&gt;Now that we've secured our routes, the next step is to safeguard actions and features within those pages to ensure only users with the necessary permissions can access them. &lt;/p&gt;

&lt;p&gt;For instance, you can take three main actions on the admin page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a product&lt;/li&gt;
&lt;li&gt;Edit a product&lt;/li&gt;
&lt;li&gt;Delete a product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948760%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F2ebbcadd-ee6a-43a6-b646-a06a24e08ed5_tqtu2y.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948760%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F2ebbcadd-ee6a-43a6-b646-a06a24e08ed5_tqtu2y.png%3Falign%3D" alt="Screenshot of admin dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, an admin has the permission to perform all these actions by default. But suppose later in development, a change was made to revoke the &lt;code&gt;create:products&lt;/code&gt; permission from the default admin role and to only be given to a select few admins. &lt;/p&gt;

&lt;p&gt;In that case, ensuring only those specific admins can create a product becomes crucial.&lt;/p&gt;

&lt;p&gt;We can check permissions in our project using the &lt;code&gt;checkPermissions&lt;/code&gt; utility function. &lt;/p&gt;

&lt;p&gt;For example, in the &lt;code&gt;+page.svelte&lt;/code&gt; file in the &lt;code&gt;admin&lt;/code&gt; directory, we can add the following code to ensure only admins with &lt;code&gt;create:product&lt;/code&gt; permission can access the "Add new product" button:&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="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;protected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;/+&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkPermissions&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;$lib/rbacUtils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&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;../../../constants&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&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;products&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;../../../stores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canCreateProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&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;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CREATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;container mx-auto px-4 md:px-8 py-12&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex flex-wrap items-center justify-between mb-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-3xl md:text-4xl font-bold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;canCreateProducts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
                &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mt-4 min-[457px]:mt-0 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 bg-gray-900 text-white hover:bg-gray-800&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we remove &lt;code&gt;PERMISSIONS.CREATE_PRODUCTS&lt;/code&gt; from the admin permissions in the &lt;code&gt;rolePermissions.js&lt;/code&gt; file, we can see the change taking effect:&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="c1"&gt;// src/lib/rolePermissions.js&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;rolePermissions&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;ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DELETE_PRODUCTS&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948810%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F4e6442ee-dba7-4b2c-b6a0-de03ce0ade0c_dgigiy.png%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948810%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2F4e6442ee-dba7-4b2c-b6a0-de03ce0ade0c_dgigiy.png%3Falign%3D" alt="Screenshot of admin dashboard with no new product button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take things a step further by securing the edit and delete feature as well:&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="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;protected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;/+&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&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;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canDeleteProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&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;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DELETE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canUpdateProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&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;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tbody&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[&amp;amp;amp;_tr:last-child]:border-0&lt;/span&gt;&lt;span class="dl"&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="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;$products&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nf"&gt;product &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tr&lt;/span&gt;
            &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-4 align-middle [&amp;amp;amp;:has([role=checkbox])]:pr-0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex items-center space-x-2&lt;/span&gt;&lt;span class="dl"&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="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;canUpdateProducts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;Update&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
                            &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 w-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;
                                &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 24 24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currentColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linecap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linejoin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-4 w-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
                                    &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/path&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;canDeleteProducts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;Delete&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
                            &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 w-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;
                                &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 24 24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currentColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linecap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linejoin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-4 w-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M3 6h18&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/path&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/path&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/path&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/tr&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/tbody&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's implement the same policy on our profile page. Navigate to the &lt;code&gt;+page.svelte&lt;/code&gt; file in the &lt;code&gt;user&lt;/code&gt; directory and add the following 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="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;protected&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="o"&gt;/+&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkPermissions&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;$lib/rbacUtils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PERMISSIONS&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;../../../constants&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../stores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canEditProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&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;PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PROFILE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;email&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="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-[calc(100svh-64px)] w-full flex items-center justify-center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
        &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rounded-lg border bg-card text-card-foreground shadow-sm w-[28rem] max-w-md&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-6 space-y-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space-y-2&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                    &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canEditProfile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space-y-2&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                    &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canEditProfile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space-y-2&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                    &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canEditProfile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space-y-2&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                    &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canEditProfile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex items-center p-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;
                &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canEditProfile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;Save&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use the &lt;code&gt;canEditProfile&lt;/code&gt; variable to determine whether the input fields and save button will be disabled. If the value is &lt;code&gt;false&lt;/code&gt;, the input fields and submit button will be disabled and vice versa.&lt;/p&gt;

&lt;p&gt;And with that, we should have a fully secured e-commerce web app using RBAC!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948845%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fd5b4fa53-3b48-4c98-b47b-c821793d927a_cqtq0a.gif%3Falign%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftropicolx%2Fimage%2Fupload%2Fv1715948845%2FImplementing%2520Role-Based%2520Access%2520Control%2520in%2520SvelteKit%2Fd5b4fa53-3b48-4c98-b47b-c821793d927a_cqtq0a.gif%3Falign%3D" alt="Final RBAC demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this tutorial, we looked at how to implement Role-Based Access Control (RBAC) in Sveltekit applications. &lt;/p&gt;

&lt;p&gt;We began by learning about the fundamentals of RBAC, such as roles and permissions and their importance in web development. &lt;/p&gt;

&lt;p&gt;We then examined its implementation, which included configuring custom roles and permissions, integrating RBAC utilities, securing routes, and managing permissions within components.&lt;/p&gt;

&lt;p&gt;As you continue developing your SvelteKit apps, remember to regularly review and update your RBAC configuration to adapt to changing requirements and mitigate potential security risks. &lt;/p&gt;

&lt;p&gt;Additionally, prioritize continual monitoring, logging, and testing to maintain the integrity and effectiveness of your RBAC implementation.&lt;/p&gt;

&lt;p&gt;You can find the complete project code in this &lt;a href="https://github.com/TropicolX/svelte-rbac-demo" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>sveltekit</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
    <item>
      <title>JWT vs PASETO: New Era of Token-Based Authentication</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Wed, 22 May 2024 15:33:51 +0000</pubDate>
      <link>https://dev.to/permify/jwt-vs-paseto-new-era-of-token-based-authentication-4hi</link>
      <guid>https://dev.to/permify/jwt-vs-paseto-new-era-of-token-based-authentication-4hi</guid>
      <description>&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How Does Token-Based Authentication Work?&lt;/li&gt;
&lt;li&gt;What is JWT?&lt;/li&gt;
&lt;li&gt;How JWT Works?&lt;/li&gt;
&lt;li&gt;Pitfalls Of JWT&lt;/li&gt;
&lt;li&gt;What is PASETO (Platform Agnostic Security Token)?&lt;/li&gt;
&lt;li&gt;How PASETO Works?&lt;/li&gt;
&lt;li&gt;How to Implement JWT or Paseto in Your Project?&lt;/li&gt;
&lt;li&gt;Key Differences Between Paseto vs JWT&lt;/li&gt;
&lt;li&gt;Choosing Between Paseto and JWT&lt;/li&gt;
&lt;li&gt;The Future of Web Tokens&lt;/li&gt;
&lt;li&gt;Summing Up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;APIs and modern web applications have brought token-based authentication to the forefront of secure authorization methods. &lt;/p&gt;

&lt;p&gt;Offering advantages like scalability, statelessness, and enhanced security compared to traditional session-based authentication, tokens have become the preferred choice for developers worldwide.&lt;/p&gt;

&lt;p&gt;Among various token-based approaches, &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;JSON Web Token (JWT)&lt;/a&gt; has gained widespread popularity because of its simplicity and ease of implementation. &lt;/p&gt;

&lt;p&gt;However, concerns surrounding potential vulnerabilities and the need for meticulous implementation have led to the exploration of more robust alternatives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://paseto.io/" rel="noopener noreferrer"&gt;Paseto (Platform-Agnostic Security Tokens)&lt;/a&gt; has emerged as a better solution, directly addressing the shortcomings of JWT. &lt;/p&gt;

&lt;p&gt;Designed with a focus on security, Paseto provides a more secure foundation for token-based authentication by mitigating vulnerabilities and enforcing secure defaults. &lt;/p&gt;

&lt;p&gt;This article delves into a comprehensive comparison of Paseto and JWT, dissecting their core functionalities, security features, and potential drawbacks. &lt;/p&gt;

&lt;p&gt;By analyzing their respective strengths and weaknesses, aiming to equip you with the knowledge to make informed decisions regarding token-based authentication in their projects&lt;/p&gt;

&lt;h2 id="how-does-token-based-authentication-work"&gt;How Does Token-Based Authentication Work?&lt;/h2&gt;

&lt;p&gt;Token-based authentication provides a secure and efficient way to manage user access in modern applications. Unlike traditional session-based methods that rely on server-side storage, token-based systems issue tokens to clients upon successful authentication. &lt;/p&gt;

&lt;p&gt;Let's break down the typical flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Login:&lt;/strong&gt; The user initiates the process by providing their credentials (username and password) to the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; The application validates these credentials against a database or other authentication mechanism, verifying the user's identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Generation:&lt;/strong&gt; Upon successful authentication, the application generates a unique, digitally signed token containing relevant user information and permissions. This token acts as a secure representation of the user's identity and access rights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Delivery:&lt;/strong&gt; The application sends the generated token to the client, usually included in the HTTP response header or body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client-Side Storage:&lt;/strong&gt; Here the client securely stores the received token, often in local storage, session storage, or cookies, for use in subsequent requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Requests:&lt;/strong&gt; When the client needs to access a protected resource, it includes the token in the authorization header of the HTTP request. This signals to the server that the client is attempting to access a restricted area.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Verification:&lt;/strong&gt; When a request with a token is received, the server confirms its validity and integrity by utilizing the corresponding secret key or public key for the token's signing algorithm. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Control:&lt;/strong&gt; Based on the validated token and its embedded permissions, the server determines whether the client has the necessary authorization to access the requested resource. If authorized, the server grants access and fulfills the request. Else, access is denied.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's visualize the flow:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJvbF36ZR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJvbF36ZR.png" alt="Token Based Authentication"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A flowchart illustrating the token-based authentication process&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="what-is-jwt"&gt;What is JWT?&lt;/h2&gt;

&lt;p&gt;JWT stands for &lt;em&gt;JSON Web Token&lt;/em&gt;. It's an open standard (RFC 7519) defining a compact and self-contained method for securely transmitting information between parties as JSON objects.&lt;/p&gt;

&lt;p&gt;JWTs are commonly used to verify user identities and granting access to private resources. Also with JWT you can securely share information between applications.&lt;/p&gt;

&lt;p&gt;A JWT comprises three parts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Header:&lt;/strong&gt; This defines the token type (JWT) and the signing algorithm used. Example,&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;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&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;strong&gt;Payload:&lt;/strong&gt; It contains statements about an entity (typically, the user), and additional data. Example,&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;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1516239022&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;strong&gt;Signature:&lt;/strong&gt; This verifies the token's authenticity and integrity. Its created by combining the encoded header, encoded payload, a secret, and the specified signing algorithm. Example (using HMAC SHA256):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;HMACSHA256&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nt"&gt;base64UrlEncode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="nt"&gt;base64UrlEncode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="nt"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2 id="how-jwt-works"&gt;How JWT Works?&lt;/h2&gt;

&lt;p&gt;The process involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token Generation:&lt;/strong&gt;
Upon successful user authentication, the server generates a JWT containing user information and permissions. This token is signed using a secret key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Sent to Client:&lt;/strong&gt;
The server sends the JWT to the client, usually within the HTTP response header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Stores Token:&lt;/strong&gt; 
The client securely stores the JWT, often in local storage or cookies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Requests Resource:&lt;/strong&gt;
The client includes the JWT in the authorization header for subsequent requests to private resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Validates Token:&lt;/strong&gt;
The server validates the JWT's signature and expiration time by using the secret key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Granted/Denied:&lt;/strong&gt;
Based on the token validation, the server grants or denies access to the requested resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="pitfalls-of-jwt"&gt;Pitfalls Of JWT&lt;/h2&gt;

&lt;p&gt;While JWT offers many advantages, it's essential to be aware of potential pitfalls and security concerns that can arise if not implemented properly. &lt;/p&gt;

&lt;p&gt;Here are some key issues associated with JWT tokens:&lt;/p&gt;

&lt;h3&gt;
  
  
  Algorithm Confusion
&lt;/h3&gt;

&lt;p&gt;JWT allows for flexibility in choosing signing algorithms, including the option of "none". &lt;/p&gt;

&lt;p&gt;If developers mistakenly set up their applications to accept unsigned tokens, it can make them ineffective and vulnerable. Attackers could exploit this by forging tokens with arbitrary claims.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Management Issues
&lt;/h3&gt;

&lt;p&gt;It's security system heavily relies on proper key management. Weak keys or improper storage can compromise the entire system. &lt;/p&gt;

&lt;p&gt;A leaked or compromised keys allow attackers to forge tokens or decrypt sensitive information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lack of Built-in Revocation
&lt;/h3&gt;

&lt;p&gt;JWTs are stateless, meaning the server doesn't maintain a record of issued tokens. &lt;/p&gt;

&lt;p&gt;Revoking tokens before they expire can be a challenge, especially in cases of compromised keys or user logout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bypassing Signature Verification
&lt;/h3&gt;

&lt;p&gt;Vulnerabilities in certain JWT libraries and implementations allow for signature verification to be bypassed. &lt;/p&gt;

&lt;p&gt;These vulnerabilities could enable attackers to create forged tokens that appear legitimate to the application.&lt;/p&gt;

&lt;h2 id="what-is-paseto"&gt;What is PASETO (Platform Agnostic Security Token)?&lt;/h2&gt;

&lt;p&gt;Paseto, which stands for &lt;em&gt;Platform-Agnostic Security Tokens&lt;/em&gt;, is a specification for secure stateless tokens. &lt;/p&gt;

&lt;p&gt;It provides a modern and better alternative to JWT, addressing some of its inherent vulnerabilities and emphasizing secure defaults and ease of implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paseto Structure
&lt;/h3&gt;

&lt;p&gt;Unlike JWT's single, generic structure, Paseto employs a versioned approach with two distinct token purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local tokens:&lt;/strong&gt; This is designed for stateful, server-side sessions where the tokens are securely stored on the server-side and associated with a user's session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public tokens:&lt;/strong&gt; This is intended for stateless applications and use cases involving public-key cryptography. These tokens can be securely transmitted and verified without needing server-side storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both local and public tokens share a similar structure, consisting of three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header:&lt;/strong&gt; This section identifies the Paseto version and purpose (local or public) along with the specific cryptographic algorithm used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload:&lt;/strong&gt; Similar to JWT, the payload contains claims representing information about an entity (usually the user) and any additional data relevant to the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Footer (optional):&lt;/strong&gt; The footer can include additional authenticated data, providing extra security and context to the token.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="how-paseto-works"&gt;How PASETO Works?&lt;/h2&gt;

&lt;p&gt;Paseto's core strength lies in its focus on secure defaults and well-defined implementations. &lt;/p&gt;

&lt;p&gt;It eliminates the risk of algorithm confusion, a known vulnerability in JWT, by explicitly specifying which cryptographic algorithms should be used for each version and purpose. This approach ensures that developers don't inadvertently choose insecure options.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local tokens:&lt;/strong&gt; Typically use symmetric-key cryptography, where the same secret key is used for both encryption and decryption. This makes them suitable for server-side session management, where the server maintains control over the key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public tokens:&lt;/strong&gt; Employ public-key cryptography, involving a public key for encryption and a private key for decryption. This enables secure communication and verification without sharing the secret key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="how-to-implement-jwt-or-paseto"&gt;How to Implement JWT or Paseto in Your Project?&lt;/h2&gt;

&lt;p&gt;Here's a basic guideline for implementing either JWT or Paseto in your project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Choose a Library:&lt;/strong&gt; Select a library for your project. There are several options available for popular languages like Python, Node.js, Java, and Ruby.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate a Secret Key:&lt;/strong&gt; Create a strong and secure secret key to sign and verify tokens. Store it securely. For local tokens, generate a secure secret key. For public tokens, generate a public-private key pair.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement Token Generation:&lt;/strong&gt; Develop a mechanism to generate the token upon successful user authentication, including relevant claims in the payload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement Token Validation:&lt;/strong&gt; Implement logic on the server-side to validate the token received in requests, verifying the signature and expiration time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Token Storage:&lt;/strong&gt; On the client-side, securely store the JWT (e.g., HttpOnly cookies with the Secure flag).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle Token Expiration:&lt;/strong&gt; Implement a strategy to handle expired tokens, such as refresh tokens or requiring re-authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload extraction and verification:&lt;/strong&gt; This steps works only for Paseto, where the payload and verified the to ensure the authenticity and integrity of the information.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="key-differences-between-paseto-vs-jwt"&gt;Key Differences Between Paseto vs JWT&lt;/h2&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Aspect&lt;/th&gt;
      &lt;th&gt;Paseto&lt;/th&gt;
      &lt;th&gt;JWT&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Approach&lt;/td&gt;
      &lt;td&gt;Versioned approach with specific purposes (local/public)&lt;/td&gt;
      &lt;td&gt;Single, generic structure&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Components&lt;/td&gt;
      &lt;td&gt;Header, payload, optional footer&lt;/td&gt;
      &lt;td&gt;Header, payload, signature&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Formatting Rules&lt;/td&gt;
      &lt;td&gt;Stricter formatting and implementation rules&lt;/td&gt;
      &lt;td&gt;More flexible, allowing for various algorithms and claims&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Security Features
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Aspect&lt;/th&gt;
      &lt;th&gt;Paseto&lt;/th&gt;
      &lt;th&gt;JWT&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Algorithm Confusion&lt;/td&gt;
      &lt;td&gt;Eliminated by specifying algorithms per version/purpose&lt;/td&gt;
      &lt;td&gt;Potential vulnerability if "none" algorithm is allowed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key Management&lt;/td&gt;
      &lt;td&gt;Promotes better practices by design&lt;/td&gt;
      &lt;td&gt;Requires careful implementation to avoid vulnerabilities&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Revocation&lt;/td&gt;
      &lt;td&gt;Easier due to versioning and purpose-specific design&lt;/td&gt;
      &lt;td&gt;Stateless nature makes it challenging; requires additional mechanisms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Configuration Defaults&lt;/td&gt;
      &lt;td&gt;Enforces secure algorithms and configurations&lt;/td&gt;
      &lt;td&gt;Allows for potential misconfigurations and vulnerabilities if not implemented carefully&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use Case Scenarios
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Token&lt;/th&gt;
      &lt;th&gt;Paseto&lt;/th&gt;
      &lt;th&gt;JWT&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Local Tokens&lt;/td&gt;
      &lt;td&gt;Stateful server-side sessions (e.g., traditional web apps)&lt;/td&gt;
      &lt;td&gt;Can be used for various use cases, including both stateful and stateless applications&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Public Tokens&lt;/td&gt;
      &lt;td&gt;Stateless authentication with public-key cryptography&lt;/td&gt;
      &lt;td&gt;Suitable for various scenarios but requires careful consideration of security implications&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FryFZOHWzR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FryFZOHWzR.png" alt="Paseto &amp;amp; JWT Structure"&gt;&lt;/a&gt;&lt;br&gt;
An image showing the structural difference of Paseto and JWT&lt;/p&gt;

&lt;h2 id="choosing-between-paseto-and-jwt"&gt;Choosing Between Paseto and JWT&lt;/h2&gt;

&lt;p&gt;Both Paseto and JWT offer distinct advantages and disadvantages, making the choice dependent on your specific needs and priorities.&lt;/p&gt;

&lt;p&gt;Here are some factors that can influence your decision:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paseto:&lt;/strong&gt; If your application demands robust security and protection against common vulnerabilities, then Paseto is probably the best fit for you. Because it is designed to mitigate issues like algorithm confusion and promote better key management practices, ensuring a higher level of security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT:&lt;/strong&gt; While JWT can be secure when implemented correctly, it necessitates meticulous attention to detail and a thorough understanding of potential pitfalls. Developers must be vigilant in avoiding common misconfiguration and vulnerabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Application Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paseto:&lt;/strong&gt; Paseto offers a clear distinction between local and public tokens, catering to different architectural requirements. Local tokens, designed for stateful server-side sessions, are ideal for traditional web applications with session management. Public tokens, geared towards stateless applications and public-key cryptography, align well with microservices and API-driven architectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT:&lt;/strong&gt; It's flexible structure accommodates both stateful and stateless applications. However, this flexibility can also lead to ambiguity and potential misuse, if not handled carefully.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Developer Familiarity&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paseto:&lt;/strong&gt; While Paseto's ecosystem is steadily growing, it might not yet match the breadth and depth of JWT's support. Developers might need to invest additional effort in finding appropriate libraries and understanding Paseto's specific implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT:&lt;/strong&gt; Due to its earlier adoption and widespread usage, JWT benefits from a larger community and readily available libraries, frameworks, and documentation across various programming languages. This makes it easier for developers to find resources and implement JWT within their projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ecosystem Support&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paseto:&lt;/strong&gt; It's ecosystem is expanding, with libraries and tools becoming increasingly available for popular programming languages. However, it may not yet match the comprehensive support of JWT, particularly for less common languages or frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT:&lt;/strong&gt; JWT enjoys extensive support across numerous programming languages, frameworks, and libraries. This widespread adoption ensures readily available resources and simplifies integration with existing tools and infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="the-future-of-web-tokens"&gt;The Future of Web Tokens&lt;/h2&gt;

&lt;p&gt;The web tokens landscape is constantly evolving, driven by advancements in cryptography, changing security threats, and the ever-growing need for secure and efficient authentication mechanisms.&lt;/p&gt;

&lt;p&gt;Here are some emerging ideas that may shape the future of web tokens:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quantum-resistant cryptography:&lt;/strong&gt; With the looming possibility of quantum computers breaking existing cryptographic algorithms, the development and adoption of quantum-resistant algorithms will be crucial for future-proofing web tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-quantum cryptography:&lt;/strong&gt; Research and standardization efforts are underway to develop and integrate post-quantum cryptography algorithms into token-based systems, ensuring long-term security and resilience against quantum threats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decentralized Identity and Self-Sovereign Identity (SSI)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verifiable credentials:&lt;/strong&gt; With the rise of verifiable credentials, this allows individuals to control and manage their digital identities, which may influence how tokens are used for authentication and authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decentralized Identifiers (DIDs):&lt;/strong&gt; This enables decentralized and self-owned identifiers, and could be integrated with token-based systems to enhance privacy and user control over personal data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improved Usability and Standardization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplified token management:&lt;/strong&gt; Efforts to streamline token generation, revocation, and renewal processes will improve user experience and developer efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardization of token formats and protocols:&lt;/strong&gt; Further standardization of token formats and communication protocols will promote interoperability and simplify integration across different platforms and services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Emerging Token Mechanisms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Macaroons:&lt;/strong&gt; This offer a more flexible and granular approach to authorization, allowing for delegation and attenuation of access rights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token binding:&lt;/strong&gt; This mechanisms can mitigate token theft and replay attacks, enhancing the security of token-based systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Influence on Paseto and JWT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Paseto's focus on security and well-defined use cases positions it well for adoption in environments with high-security requirements and where standardization is valued. &lt;/p&gt;

&lt;p&gt;Its versioned approach allows for adaptation and integration of future cryptographic advancements.&lt;/p&gt;

&lt;p&gt;JWT's flexibility and widespread adoption may lead to its continued use in various applications. However, its security shortcomings might necessitate additional safeguards and careful implementation practices to mitigate risks.&lt;/p&gt;

&lt;p&gt;The future of web tokens will probably involve a combination of existing and emerging mechanisms, each catering to specific needs and security considerations. &lt;/p&gt;

&lt;h2 id="summing-up"&gt;Summing Up&lt;/h2&gt;

&lt;p&gt;In this article, we've highlighted the strengths and weaknesses of each token mechanism, emphasizing the importance of understanding your specific needs and priorities. &lt;/p&gt;

&lt;p&gt;While JWT provides simplicity and flexibility, Paseto prioritize security and well-defined use cases. &lt;/p&gt;

&lt;p&gt;Evaluating factors such as security requirements, application architecture, and developer familiarity will guide you toward the most suitable option. &lt;/p&gt;

&lt;p&gt;Additionally, exploring emerging solutions like &lt;strong&gt;&lt;a href="https://permify.co/" rel="noopener noreferrer"&gt;Permify&lt;/a&gt;&lt;/strong&gt;, which offers a comprehensive authorization platform with fine-grained access control, can further enhance your application's security and flexibility.&lt;/p&gt;

&lt;p&gt;The choice between JWT and Paseto is not a one-size-fits-all answer, but a decision based on your unique context.&lt;/p&gt;

&lt;p&gt;Let's keep the conversation going! &lt;a href="https://discord.com/invite/n6KfzYxhPp" rel="noopener noreferrer"&gt;Join our Discord community&lt;/a&gt; to share your thoughts and experiences with JWT, Paseto, and other token mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc7519" rel="noopener noreferrer"&gt;JWT RFC 7519&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jwt.io/introduction/" rel="noopener noreferrer"&gt;JSON Web Token Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet_for_Java.html" rel="noopener noreferrer"&gt;OWASP JWT Cheat Sheet&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://paseto.io/docs/" rel="noopener noreferrer"&gt;Paseto Specifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://paragonie.com/blog/tag/paseto" rel="noopener noreferrer"&gt;Paragon Initiative Enterprises Blog (Paseto)&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Further Reading:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://auth0.com/learn/json-web-tokens/" rel="noopener noreferrer"&gt;Understanding JWTs and Their Use in APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/techschoolguru/why-paseto-is-better-than-jwt-for-token-based-authentication-1b0c"&gt;Why Paseto is Better Than JWT for Token-Based Authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jwt</category>
      <category>webdev</category>
      <category>authentication</category>
      <category>programming</category>
    </item>
    <item>
      <title>Consistent Hashing: An Overview and Implementation in Golang</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Tue, 07 May 2024 12:48:51 +0000</pubDate>
      <link>https://dev.to/permify/consistent-hashing-an-overview-and-implementation-in-golang-53je</link>
      <guid>https://dev.to/permify/consistent-hashing-an-overview-and-implementation-in-golang-53je</guid>
      <description>&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What Is Hashing?&lt;/li&gt;
&lt;li&gt;What Is Consistent Hashing?&lt;/li&gt;
&lt;li&gt;What Problem Does Consistent Hashing Solve?&lt;/li&gt;
&lt;li&gt;How Consistent Hashing Work?&lt;/li&gt;
&lt;li&gt;Where is Consistent Hashing Used?&lt;/li&gt;
&lt;li&gt;Implementing Consistent Hashing in Golang&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ever wondered how big tech websites like Netflix, Twitch, Facebook, etc. handle huge amounts of traffic and data without slowing down or crashing? The technique that makes this possible is consistent hashing. As a developer, understanding consistent hashing is a useful skill in your toolbox. &lt;/p&gt;

&lt;p&gt;In this tutorial, we'll give you an in-depth overview of consistent hashing and walk you through implementing it in Golang.&lt;/p&gt;

&lt;h2 id="what-is-hashing"&gt;What Is Hashing?&lt;/h2&gt;

&lt;p&gt;Hashing is a technique used to map data of an arbitrary size to data of a fixed size. In simple terms, it maps keys to values. The values are called hash codes or hash values.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.geeksforgeeks.org/hash-functions-and-list-types-of-hash-functions/" rel="noopener noreferrer"&gt;hash function&lt;/a&gt; is used to generate the hash code. It takes the key and returns the hash value. &lt;br&gt;
A good hash function has the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Uniform distribution:&lt;/strong&gt; It should map keys to hash values uniformly. Each hash value should have an equal chance of being the output of the hash function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deterministic:&lt;/strong&gt; The same key should always map to the same hash value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficiently computable:&lt;/strong&gt; It should be fast to compute the hash value for any key.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hashing is used for several purposes, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash tables:&lt;/strong&gt; To map keys to values for faster lookups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cryptography:&lt;/strong&gt; For message authentication and digital signatures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching:&lt;/strong&gt; To map keys to cached data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="what-is-consistent-hashing"&gt;What Is Consistent Hashing?&lt;/h2&gt;

&lt;p&gt;This is a special kind of hashing technique. It maps keys to hash values in a way that the mapping between keys and hash values remains consistent even when the number of hash values changes.&lt;/p&gt;

&lt;h2 id="what-problem-does-consistent-hashing-solve"&gt;What Problem Does Consistent Hashing Solve?&lt;/h2&gt;

&lt;p&gt;Consistent hashing solves the problem of caching by randomly mapping data to physical nodes in the cluster. With a regular hash function, adding or removing one node changes the mapping of nearly every key. &lt;/p&gt;

&lt;p&gt;Consistent hashing minimizes the number of keys that need to be remapped when a node is added or removed. It is useful in distributed caching and database systems where the number of nodes changes Frequently.&lt;/p&gt;

&lt;p&gt;It also solves the problems caused by hash collisions. &lt;a href="https://www.sciencedirect.com/topics/computer-science/hash-collision" rel="noopener noreferrer"&gt;Hash collisions&lt;/a&gt; occur when two keys map to the same hash value. This leads to extra work to handle the collision. &lt;/p&gt;

&lt;h2 id="how-consistent-hashing-work"&gt;How Consistent Hashing Work?&lt;/h2&gt;

&lt;p&gt;Hashing is a way of mapping data of arbitrary size to fixed-size values. A hash function takes input data and converts it into a hash value. The hash table stores the data using the hash value as the key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.educative.io/answers/what-is-a-distributed-hash-table" rel="noopener noreferrer"&gt;Distributed hashing&lt;/a&gt; is an extension of hashing used in distributed data stores. It allows data to be distributed across multiple nodes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FH198a_nYp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FH198a_nYp.png" alt="0cdaeb48-921b-4f4d-bd4e-31bd7a6bcc0f"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://abhistrike.hashnode.dev/the-magic-of-consistent-hashing-a-secret-weapon-for-efficient-load-balancing" rel="noopener noreferrer"&gt;Image by Abhinav Singh&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.hairizuan.com/consistent-hashing-implementation-in-golang/" rel="noopener noreferrer"&gt;consistent hashing&lt;/a&gt;, the hash values are arranged in a ring. Each key is mapped to one of the hash values on the ring. &lt;/p&gt;

&lt;p&gt;When a hash value is added or removed, only the keys mapped to that hash value are remapped. The other keys remain mapped to the same hash value.&lt;/p&gt;

&lt;p&gt;The key's hash value is used to determine which node the data is stored on. As nodes add or remove from the cluster, the mapping of keys to nodes changes. This can require massive data movement.&lt;/p&gt;

&lt;p&gt;Each node in the cluster receives one or more points on the ring. The system maps the key to a point on the ring and stores it on the node that contains that point.&lt;/p&gt;

&lt;p&gt;When a new node is added, it takes over some points on the ring. Only the keys that map to those points move to the new node. The keys mapped to other points stay where they are. &lt;/p&gt;

&lt;p&gt;Similarly, when a node is removed, its points on the ring are taken over by the remaining nodes. But keys mapped to other points are unaffected.&lt;/p&gt;

&lt;h2 id="where-is-consistent-hashing-used"&gt;Where is Consistent Hashing Used?&lt;/h2&gt;

&lt;p&gt;Many real-world applications use consistent hashing to distribute data across a cluster of servers. Some major use cases include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed caching&lt;/strong&gt;&lt;br&gt;
Consistent hashing is a popular technique for distributed caching systems like &lt;a href="https://memcached.org/" rel="noopener noreferrer"&gt;Memcached&lt;/a&gt; and Dynamo. In these systems, the caches are distributed across many servers. When a cache miss occurs, consistent hashing is used to determine which server contains the required data. This allows the overall cache to scale to handle more requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed storage&lt;/strong&gt;&lt;br&gt;
Distributed storage systems like &lt;a href="https://cassandra.apache.org/_/index.html" rel="noopener noreferrer"&gt;Cassandra&lt;/a&gt;, &lt;a href="https://aws.amazon.com/pm/dynamodb/?gclid=CjwKCAiA75itBhA6EiwAkho9ewmwgA53Rorp78BTqwd8ta30HOPLu5k1Ug-aLeqBQrClW3adowxeCRoCMy4QAvD_BwE&amp;amp;trk=5c0a5fc5-4392-49ca-8bcf-f023c39b7463&amp;amp;sc_channel=ps&amp;amp;ef_id=CjwKCAiA75itBhA6EiwAkho9ewmwgA53Rorp78BTqwd8ta30HOPLu5k1Ug-aLeqBQrClW3adowxeCRoCMy4QAvD_BwE:G:s&amp;amp;s_kwcid=AL!4422!3!645125273714!e!!g!!dynamodb!19574556905!145779852912" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt;, and &lt;a href="https://www.project-voldemort.com/" rel="noopener noreferrer"&gt;Voldemort&lt;/a&gt; also use consistent hashing. In these systems, data is partitioned across many servers. Consistent hashing is used to map data to the servers that store the data. When new servers are added or removed, consistent hashing minimizes the amount of data that needs to be remapped to different servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Balancing&lt;/strong&gt;&lt;br&gt;
Many people commonly use consistent hashing for load balancing in distributed systems. It allows you to add or remove nodes from the cluster without affecting too many keys. With a traditional hash function, adding or removing a node changes the mapping of nearly every key. Consistent hashing minimizes the number of keys that need to be remapped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peer-to-Peer Networks&lt;/strong&gt;&lt;br&gt;
Some peer-to-peer networks use consistent hashing to map nodes to the key space. This allows nodes to join and leave the network with minimal disruption. New nodes can take over responsibility for keys that were previously assigned to nodes that left.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt;&lt;br&gt;
The domain name system (DNS) uses consistent hashing to map domain names to DNS servers. This fault tolerance is provided by reassigning the keys of a DNS server to other servers with minimal changes if it goes down.&lt;/p&gt;

&lt;h2 id="implementing-consistent-hashing-in-golang"&gt;Implementing Consistent Hashing in Golang&lt;/h2&gt;

&lt;p&gt;To implement consistent hashing in Golang, you'll need to have the following installed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A code editor, &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; Preferably&lt;/li&gt;
&lt;li&gt;&lt;a href="https://golang.org/dl/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hashicorp/memberlist" rel="noopener noreferrer"&gt;hashicorp/memberlist&lt;/a&gt;: &lt;code&gt;go get -u github.com/hashicorp/memberlist&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/grpc/grpc-go" rel="noopener noreferrer"&gt;grpc-go&lt;/a&gt;: &lt;code&gt;go get -u google.golang.org/grpc&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/protocolbuffers/protobuf" rel="noopener noreferrer"&gt;protobuf&lt;/a&gt;: &lt;code&gt;go get -u google.golang.org/protobuf/proto&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step 1: Define the Protocol Buffers (proto) file
&lt;/h3&gt;

&lt;p&gt;Before we begin let's define the following terms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://protobuf.dev/" rel="noopener noreferrer"&gt;Protocol Buffers (protobuf):&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Protocol Buffers, or protobuf, is a data serialization format developed by Google. It offers a language-agnostic way to define data structures, enabling efficient serialization and deserialization across different programming languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://grpc.io/docs/" rel="noopener noreferrer"&gt;gRPC:&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
gRPC, which stands for gRPC Remote Procedure Calls, is an open-source RPC framework, also developed by Google. It uses protobuf as its interface definition language, describing the structure of data exchanged between servers and clients. &lt;/p&gt;

&lt;p&gt;Now, create a file named &lt;code&gt;consistency.proto&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;consistency&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;GetNodeForRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;AddNodeForRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;RemoveNodeForRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;NodeRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;NodeResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;Empty&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to generate Go files from the proto file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;protoc &lt;span class="nt"&gt;--go_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--go_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;source_relative &lt;span class="nt"&gt;--go-grpc_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--go-grpc_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;source_relative consistency.proto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command generates &lt;code&gt;consistency.pb.go&lt;/code&gt; and &lt;code&gt;consistency_grpc.pb.go&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Implement Consistent Hashing and gRPC Service
&lt;/h3&gt;

&lt;p&gt;Let's break down this step into three parts for better understanding.&lt;/p&gt;

&lt;h4&gt;
  
  
  Part 1: Initialization and Type Definitions
&lt;/h4&gt;

&lt;p&gt;In this part, we initialize the &lt;code&gt;HashRing&lt;/code&gt; struct, which represents the consistent hash ring. The struct includes fields for maintaining nodes, their corresponding IP addresses, keys, and a memberlist for handling membership in the distributed system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c"&gt;//import these packages&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"hash/crc32"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net"&lt;/span&gt;
    &lt;span class="s"&gt;"sort"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/hashicorp/memberlist"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// HashRing represents the consistent hash ring&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;HashRing&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;
    &lt;span class="n"&gt;Nodes&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;nodeToIP&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;nodeToKey&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;uint32&lt;/span&gt;
    &lt;span class="n"&gt;mlist&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memberlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Memberlist&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// NodeService represents the gRPC service for nodes&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NodeService&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;HashRing&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HashRing&lt;/code&gt; struct: It includes a mutex for thread safety, a slice to keep track of nodes, maps for storing node-to-IP and node-to-key mappings, and a memberlist for handling membership.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NodeService&lt;/code&gt; struct: It represents the gRPC service and holds a reference to the &lt;code&gt;HashRing&lt;/code&gt; struct.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Part 2: The Functions
&lt;/h4&gt;

&lt;p&gt;Here, we define the functions that perform actions on the hash ring, such as adding nodes, removing nodes, and getting the node responsible for a given key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// AddNode adds a new node to the hash ring&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AddNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c"&gt;// Node already exists&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChecksumIEEE&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToIP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Strings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Update memberlist&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to join memberlist: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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="c"&gt;// RemoveNode removes a node from the hash ring&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RemoveNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c"&gt;// Node does not exist&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToIP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Remove the node from the slice&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Update memberlist&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Leave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;memberlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NodeMetaPreload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to leave memberlist: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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="c"&gt;// GetNode returns the node responsible for the given key&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChecksumIEEE&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// GetNodeForRequest returns the node responsible for the given gRPC request&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// AddNodeForRequest adds a new node for the given gRPC request&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AddNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// RemoveNodeForRequest removes a node for the given gRPC request&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RemoveNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AddNode&lt;/code&gt;, &lt;code&gt;RemoveNode&lt;/code&gt;, &lt;code&gt;GetNode&lt;/code&gt;: These functions handle modifications to the hash ring.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetNodeForRequest&lt;/code&gt;, &lt;code&gt;AddNodeForRequest&lt;/code&gt;, &lt;code&gt;RemoveNodeForRequest&lt;/code&gt;: These functions are gRPC service methods for corresponding client requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Part 3: The Main Function
&lt;/h4&gt;

&lt;p&gt;This part includes the main function where we set up the memberlist, create the gRPC server, register the service, and start the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Example usage&lt;/span&gt;
    &lt;span class="n"&gt;hashRing&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;nodeToIP&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;nodeToKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Create and start memberlist&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;memberlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultLocalConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt; &lt;span class="c"&gt;// Set a unique name for the node&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;memberlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create memberlist: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;hashRing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;

    &lt;span class="c"&gt;// Create and register gRPC server&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;nodeService&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeService&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hashRing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;RegisterNodeServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodeService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Start gRPC server&lt;/span&gt;
    &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":50051"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to listen: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server listening on :50051"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to serve: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;ul&gt;
&lt;li&gt;Initialization: We create a &lt;code&gt;HashRing&lt;/code&gt; instance and configure a memberlist.&lt;/li&gt;
&lt;li&gt;Server Setup: We create a gRPC server, register the &lt;code&gt;NodeService&lt;/code&gt;, and start listening for connections on port 50051.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a file named &lt;code&gt;consistency.go&lt;/code&gt;, and add the code snippets of the 3 parts into the file for the complete implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Build and Run
&lt;/h3&gt;

&lt;p&gt;Run the following command to build and run the gRPC server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run consistency.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the gRPC server on &lt;code&gt;localhost:50051&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Test with a gRPC Client
&lt;/h3&gt;

&lt;p&gt;Create a file named &lt;code&gt;client.go&lt;/code&gt; with the following code to test the gRPC server:&lt;/p&gt;

&lt;p&gt;In this code, we will add and remove two keys ("key1" and "key2") with corresponding nodes ("Node-A" and "Node-B").&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Connect to the gRPC server&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:50051"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithInsecure&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to connect: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewNodeClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Add nodes&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Node-A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Node-B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// Get node for key1&lt;/span&gt;
    &lt;span class="n"&gt;key1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;
    &lt;span class="n"&gt;response1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting node for key1: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Key '%s' belongs to Node: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Remove Node-A&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Node-A"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// Get node for key2&lt;/span&gt;
    &lt;span class="n"&gt;key2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;
    &lt;span class="n"&gt;response2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNodeForRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NodeRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error getting node for key2: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After removing Node-A, key '%s' belongs to Node: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Node&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;After running this code, your output should look like this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Key &lt;span class="s1"&gt;'key1'&lt;/span&gt; belongs to Node: Node-A
After removing Node-A, key &lt;span class="s1"&gt;'key2'&lt;/span&gt; belongs to Node: Node-B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output indicates the node assignment for each key before and after removing a node. The specific output will depend on the keys and nodes you choose during the execution. &lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Now you understand the basics of consistent hashing and have built a simple implementation of a consistent hash ring in Golang. Consistent hashing is a clever solution for mapping keys to nodes in a distributed system. &lt;/p&gt;

&lt;p&gt;You've seen how it handles node additions and removals gracefully without disrupting the entire mapping. While this was just a basic example, the concepts you learned apply to more complex, real-world systems.&lt;/p&gt;

</description>
      <category>go</category>
      <category>tutorial</category>
      <category>microservices</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>How to Add Firebase Authentication To Your NodeJS App</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Wed, 01 May 2024 16:48:58 +0000</pubDate>
      <link>https://dev.to/permify/how-to-add-firebase-authentication-to-your-nodejs-app-2e68</link>
      <guid>https://dev.to/permify/how-to-add-firebase-authentication-to-your-nodejs-app-2e68</guid>
      <description>&lt;p&gt;Security is an absolute must for any application, whether you are building a simple pet project or a potential unicorn startup. &lt;/p&gt;

&lt;p&gt;Therefore, it's important to implement robust authentication systems to not only protect user data but also to provide personalized experiences to users.&lt;/p&gt;

&lt;p&gt;In most cases, we tend to build authentication systems from scratch; this has been the de facto approach. However, an alternative and often more efficient method is to utilize existing tools and services that are already up to industry standards. &lt;/p&gt;

&lt;p&gt;This way, you don't need to worry about the nitty-gritty details of security implementations, but rather, you can focus your efforts on building the core functionality of your apps.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll explore &lt;a href="https://firebase.google.com/docs/auth" rel="noopener noreferrer"&gt;Firebase Authentication&lt;/a&gt; and walk you through the step-by-step process of securing Node.js apps by integrating Firebase authentication providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Getting Started With Firebase Authentication in Node.js&lt;/li&gt;
&lt;li&gt;Step 1: Setting Up Your Firebase Project&lt;/li&gt;
&lt;li&gt;Step 2: Configure Firebase Authentication Service&lt;/li&gt;
&lt;li&gt;Step 3: Creating A Node.js Project&lt;/li&gt;
&lt;li&gt;Step 4: Initializing Firebase in Your Node.js Application&lt;/li&gt;
&lt;li&gt;Step 5: Implementing Authentication Features&lt;/li&gt;
&lt;li&gt;Step 6: Handling Basic User Authentication Processes&lt;/li&gt;
&lt;li&gt;Step 7: Handling Account Management Tasks&lt;/li&gt;
&lt;li&gt;Step 8: Defining the API Routes&lt;/li&gt;
&lt;li&gt;Testing Authentication Flow&lt;/li&gt;
&lt;li&gt;Best Practices When Handling Authentication Using Firebase&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2 id="getting-started-with-firebase-authentication-in-nodejs"&gt;Getting Started With Firebase Authentication in Node.js&lt;/h2&gt;

&lt;p&gt;Firebase Authentication offers an easy-to-use SDK that simplifies the process of adding authentication features to your Node.js apps. The beauty of this SDK lies in its ability to abstract away complex security implementations, such as password hashing and multi-factor authentication, allowing you to focus on building your application's core functionality. &lt;/p&gt;

&lt;p&gt;The SDK supports multiple authentication providers, including email/password combinations, social providers like Google, and more. This ensures that your apps cater to diverse user requirements, enabling them to authenticate with their preferred method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you get started, make sure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Basic knowledge of Node.js and its environment setup. If you don't have Node.js installed on your system, make sure you download and install it from the &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;official Node.js website&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Node.js comes bundled with npm (Node Package Manager)—it will be installed automatically with Node.js. You will use it to install a number of libraries that you use in your project.&lt;/p&gt;

&lt;p&gt;After completing the installation process, you can run the following commands on your terminal to check if both Node.js and npm are installed correctly:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
npm &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An active Firebase project and familiarity with the Firebase Console. Don't worry too much about this; in the next section, I will walk you through the process of setting up a Firebase project and navigating the Firebase console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A code editor (&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; is my go-to IDE), but feel free to use any code editor you're comfortable with.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these prerequisites in place, you are ready to dive into the project. Let's start by creating a Firebase project.&lt;/p&gt;

&lt;h2 id="step-1-setting-up-your-firebase-project"&gt;Step 1: Setting Up Your Firebase Project&lt;/h2&gt;

&lt;p&gt;To get started, follow these steps to set up a Firebase project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Head over to &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase Developer Console&lt;/a&gt; homepage, sign in using your Gmail address, and click the &lt;strong&gt;Go to Console&lt;/strong&gt; button to navigate to the console's overview page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the console's overview page, click the &lt;strong&gt;Create a project&lt;/strong&gt; button to create a new project. Then, provide a name for your project.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr1eqhaRRp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2Fr1eqhaRRp.jpg" alt="firabse homepage"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once the project is successfully created, navigate to the project's overview page. You need to register your application on Firebase to generate API keys. &lt;/p&gt;

&lt;p&gt;To register an app, click on the &lt;strong&gt;Web icon&lt;/strong&gt; (highlighted in the image below), provide the app name, and click on the Register app button.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJn3hTC0a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHJn3hTC0a.jpg" alt="firebase-project-overview-page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After registering your Node.js app, Firebase will provide your app's configuration object code. This code includes your API keys and other project-specific details. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkkbOzQ10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkkbOzQ10.png" alt="Firebase-app-config-code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy this configuration object code; you'll need it later when integrating Firebase SDK into your Node.js application.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Great! You've successfully created a new Firebase project and registered a web application within that project. In the next step, you'll learn how to configure Firebase authentication service in the developer console.&lt;/p&gt;

&lt;h2 id="step-2-configure-firebase-authentication-service"&gt;Step 2: Configure Firebase Authentication Service&lt;/h2&gt;

&lt;p&gt;Once you have registered your application on Firebase, the next step is to configure the Firebase Authentication service.&lt;/p&gt;

&lt;p&gt;In your project's overview page, select &lt;strong&gt;Authentication&lt;/strong&gt; section, and click on the &lt;strong&gt;Get started&lt;/strong&gt; button.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSyRJpT0Ap.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSyRJpT0Ap.jpg" alt="select authentication"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Firebase Authentication supports multiple authentication providers, for this tutorial however, we will focus on implementing the native email/password provider to secure your Node.js app.&lt;/p&gt;

&lt;p&gt;On the authentication settings page, click on the &lt;strong&gt;Sign-in method&lt;/strong&gt; tab, then click the &lt;strong&gt;Email/Password provider&lt;/strong&gt; button.Then, toggle the &lt;strong&gt;Enable&lt;/strong&gt; button.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FryCXtG7J0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FryCXtG7J0.png" alt="authentication-settings-page"&gt;&lt;/a&gt;&lt;br&gt;
Make sure to also enable the &lt;strong&gt;Email link&lt;/strong&gt; feature. Later on, we will make use of this feature to implement email verification and password reset functionality for the authentication system of the Node.js app. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSyOd66RCp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSyOd66RCp.jpg" alt="enable email link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enable Email link feature, toggle the &lt;strong&gt;Enable&lt;/strong&gt; button in the &lt;code&gt;Email link (passwordless sign in)&lt;/code&gt; section, and then click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After saving the changes, the status of the &lt;strong&gt;email/password&lt;/strong&gt; provider will change to &lt;strong&gt;Enabled&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkH3qz7y0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHkH3qz7y0.png" alt="emai-password-provider-enabled"&gt;&lt;/a&gt;&lt;br&gt;
If you want to add a new provider, simply click the &lt;strong&gt;Add new provider&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;Now, with these updates, you are ready to jump into the code and implement the authentication functionality in your Node.js app.&lt;/p&gt;

&lt;h2 id="step-3-creating-a-nodejs-project"&gt;Step 3: Creating A Node.js Project&lt;/h2&gt;

&lt;p&gt;Now, before you dive into the code, let's go over the objectives. Essentially, we need to build a Node.js authentication API that is powered by Firebase SDK. This means we'll create various routes, along with their handler functions to allow users to register, login, logout, verify their emails, as well as reset their passwords. &lt;/p&gt;

&lt;p&gt;Instead of building this functionality from scratch, we will tap into the Firebase email/password provider and the SDK's user authentication methods.&lt;/p&gt;

&lt;p&gt;To get started, first, create a folder locally to hold your project files. Then, change the current directory to the project's working directory.&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;mkdir &lt;/span&gt;firebase-auth-node
&lt;span class="nb"&gt;cd &lt;/span&gt;firebase-auth-node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, go ahead, and initialize npm to create a &lt;code&gt;package.json&lt;/code&gt; file, which will hold the project's dependencies.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm init --y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, you need to install a couple of packages for this project. For the web server, we will create an Express.js app. Go ahead and install Express.js, as well as these additional packages.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install express cookie-parser firebase firebase-admin dotenv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;firebase&lt;/code&gt; package allows you to access the Firebase SDK for Node.js and its functionalities. We'll also use &lt;code&gt;firebase-admin&lt;/code&gt;, which provides a server-side interface for interacting with Firebase services, including Authentication.&lt;/p&gt;

&lt;p&gt;Now, go ahead, and open your project folder in your preferred code editor to start development.&lt;/p&gt;

&lt;h2 id="step-4-initializing-firebase-in-your-nodejs-application"&gt;Step 4: Initializing Firebase in Your Node.js Application&lt;/h2&gt;

&lt;p&gt;Let's add the Firebase SDK configurations to your Node.js application. To do that, in your root project folder, create a folder called &lt;code&gt;src&lt;/code&gt;, as well as a &lt;code&gt;.env&lt;/code&gt; file—this file will hold your application's environment variables.&lt;/p&gt;

&lt;p&gt;Inside the src folder, create a new &lt;code&gt;config&lt;/code&gt; directory. Inside the config directory, add a new file called &lt;code&gt;firebase.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, copy and paste the Firebase SDK configuration object code from the Firebase Console to your &lt;code&gt;.env&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;//file : .env 

&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5000

&lt;span class="nv"&gt;FIREBASE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-api-key&amp;gt;
&lt;span class="nv"&gt;FIREBASE_AUTH_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-auth-domain&amp;gt;
&lt;span class="nv"&gt;FIREBASE_PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-project-id&amp;gt;
&lt;span class="nv"&gt;FIREBASE_STORAGE_BUCKET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-storage-bucket&amp;gt;
&lt;span class="nv"&gt;FIREBASE_MESSAGING_SENDER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-messaging-sender-id&amp;gt;
&lt;span class="nv"&gt;FIREBASE_APP_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-app-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in the &lt;code&gt;config/firebase.js&lt;/code&gt; file, include the following code to initialize Firebase in your Node.js (Express) application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// file: src/config/firebase.js 


require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dotenv"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.config&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
const firebase &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"firebase/app"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const firebaseConfig &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

firebase.initializeApp&lt;span class="o"&gt;(&lt;/span&gt;firebaseConfig&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this code, you have successfully initialized Firebase SDK in your application. Now, let's create the Express server. In your src directory, create an &lt;code&gt;app.js&lt;/code&gt; file, and include the following 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="c1"&gt;// file: src/app.js &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;cookieParser&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;cookie-parser&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="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;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;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="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&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="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="nf"&gt;cookieParser&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="s1"&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="s1"&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;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;`Listening on port &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;Go ahead and start the development server. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;node src/app.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should see the log output indicating that the server is listening on port 5000.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FS1xpMfQyR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FS1xpMfQyR.png" alt="express-web-server-running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! With these changes, you have successfully created an Express application and initialized Firebase in your project to access its features.&lt;/p&gt;

&lt;p&gt;Let's proceed to implement the authentication features. We need to define endpoints, as well as their handler functions to manage the authentication functionality.&lt;/p&gt;

&lt;h2 id="step-5-implementing-authentication-features"&gt;Step 5: Implementing Authentication Features&lt;/h2&gt;

&lt;p&gt;There are a few things you need to be aware of about how the Firebase SDK handles authentication. The Firebase SDK provides methods attached to the &lt;code&gt;firebase/auth&lt;/code&gt; module to handle various authentication workflows. &lt;/p&gt;

&lt;p&gt;Since we're implementing the &lt;strong&gt;email/password&lt;/strong&gt; provider, we'll primarily focus on the methods that allow us to create a new user with an email address and password, log a user in, log them out, and handle user account management tasks such as email verification and password resets.&lt;/p&gt;

&lt;p&gt;To access the &lt;code&gt;auth&lt;/code&gt; module and its methods, make the following addition to the &lt;code&gt;config/firebase.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="c1"&gt;// file: src/config/firebase.js &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;getAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;createUserWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;sendEmailVerification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;sendPasswordResetEmail&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;firebase/auth&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;Make sure to export them as follows:&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="c1"&gt;// file: src/config/firebase.js &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;getAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createUserWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendEmailVerification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendPasswordResetEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;admin&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start by implementing the handler functions that manage the user authentication processes.&lt;/p&gt;

&lt;h2 id="step-6-handling-basic-user-authentication-processes"&gt;Step 6: Handling Basic User Authentication Processes&lt;/h2&gt;

&lt;p&gt;You need define controller functions that will manage the requests to register, login, or logout users. To do that, create a &lt;code&gt;controllers&lt;/code&gt; folder. Inside this folder, include a new file called &lt;code&gt;firebase-auth-controller.js&lt;/code&gt;, and then,First, import the following methods:&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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &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;getAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;createUserWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;sendEmailVerification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendPasswordResetEmail&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="s1"&gt;../config/firebase&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;Each of the authentication methods takes a number of parameters, including a mandatory &lt;code&gt;auth&lt;/code&gt; object that needs to be included and passed alongside the requests. To access this object, go ahead and include this 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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This object is essential for authentication methods because it provides a secure and isolated context for each user's authentication state. By passing it alongside the authentication requests to Firebase backend, you ensure that the operations are performed within the correct authentication context, preventing unauthorized access or manipulation of user data.&lt;/p&gt;

&lt;p&gt;Now, there are a couple of ways you can define your controller functions. Essentially, it's really important to keep the codebase concise and readable. &lt;/p&gt;

&lt;p&gt;In this case, you can opt to create each handler function independently, or alternatively, bundle all related handlers into a class and export the instance itself. &lt;/p&gt;

&lt;p&gt;You can then tap into the class methods to access the handler functions. To do that, start by creating the controller's class. Then, define the user registration handler function:&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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FirebaseAuthController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;registerUser&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="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;email&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="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;email&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;password&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;422&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password is required&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="nf"&gt;createUserWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;userCredential&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="nf"&gt;sendEmailVerification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;201&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="s2"&gt;Verification email sent! User created successfully!&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;catch&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;error&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="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;500&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;Error sending email verification&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="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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;An error occurred while registering user&lt;/span&gt;&lt;span class="dl"&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;500&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="nx"&gt;errorMessage&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FirebaseAuthController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To register a user, this code will check for the presence of email and password in the request body. &lt;/p&gt;

&lt;p&gt;If provided, it utilizes Firebase's &lt;code&gt;createUserWithEmailAndPassword&lt;/code&gt; method to create a new user account( Firebase also provides a dedicated Cloud storage to manage this data—you can view the registered users on the console. Upon successful registration, Firebase's &lt;code&gt;sendEmailVerification&lt;/code&gt; method is invoked to send a verification email. &lt;/p&gt;

&lt;p&gt;Notice that we are including the email verification within the registration endpoint. There are various approaches to this, especially when you have a client consuming such an API; it all depends on your app's specific requirements. &lt;/p&gt;

&lt;p&gt;For instance, a common scenario would be—on the client-side—the user provides their credentials to register, then they get redirected to a new page, or you update a component to render an email verification prompt where the user provides their email. &lt;/p&gt;

&lt;p&gt;Then, Firebase handles verification by sending the user a verification link to their email, such as this one:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSycvRC0Cp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSycvRC0Cp.jpg" alt="verify email"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, ideally, you can opt to separate the registration handler and email verification handler function, and then, consume them separately as needed.&lt;/p&gt;

&lt;p&gt;But in this case, once the user is registered, we immediately tap into the user's authentication data in the response body, and send a verification link to the email address. Once they click that email, they should be verified (this logic is handled by Firebase).&lt;/p&gt;

&lt;p&gt;You should also note that by default, when you use the &lt;code&gt;createUserWithEmailAndPassword&lt;/code&gt;  method, it internally performs a sign-in operation after successfully creating the user. &lt;/p&gt;

&lt;p&gt;This behavior is a design choice in Firebase Authentication to maintain consistency and simplicity in the authentication flow. This ensures that the newly created user is authenticated and can immediately access protected resources or perform other actions without the need for an additional log-in step.&lt;/p&gt;

&lt;p&gt;Now to handle users sign-in's, within the same class, go ahead and include the following login handler. We'll use the &lt;code&gt;signInWithEmailAndPassword&lt;/code&gt; method to allow users to sign in with their credentials:&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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &lt;/span&gt;

 &lt;span class="nf"&gt;loginUser&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="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;email&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="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;email&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;password&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;422&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password is required&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="nf"&gt;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;userCredential&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;idToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userCredential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_tokenResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idToken&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;idToken&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;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User logged in successfully&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userCredential&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="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;500&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;Internal Server Error&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="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="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;error&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;An error occurred while logging in&lt;/span&gt;&lt;span class="dl"&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;500&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="nx"&gt;errorMessage&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;There are a couple of things happening in this code. First, it handles user login by extracting email and password from the request body, ensuring both are provided.&lt;/p&gt;

&lt;p&gt;Upon a successful login attempt, it retrieves the user's authentication token (Firebase handles the token creation process by default) from the user object returned in the response body, and stores it in an HTTP-only cookie named &lt;code&gt;access_token&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Why is this important? Well, securing your app's resources is of paramount concern. This means you need to be able to ensure that you only allow access to authenticated and legitimate users.&lt;/p&gt;

&lt;p&gt;Firebase SDK's handles JWT token generation, providing you with a variety of tokens, including the access and refresh tokens in the &lt;code&gt;stsTokenManager&lt;/code&gt; object in the response body. &lt;/p&gt;

&lt;p&gt;In this case, we are setting the &lt;code&gt;idToken&lt;/code&gt;, which holds information about the authenticated user, in a cookie. Whenever a user makes subsequent requests, the token will be include in the requests, and you can, through a middleware, access the token and validate it. &lt;/p&gt;

&lt;p&gt;However, it's important to note that this is just one way of implementing user authentication and protecting your application's resources. You can further enhance the security of your application by implementing additional measures, such as implementing role-based access control.&lt;/p&gt;

&lt;p&gt;Now, to handle the token validation process, you need to define a middleware function that will validate the token.&lt;/p&gt;

&lt;p&gt;Firebase provides tools for this, but it requires a service account first—a JSON file containing credentials and information necessary for server-to-server interactions with Firebase services. It will grant your Node.js application access to Firebase's administrative features, including token validation.&lt;/p&gt;

&lt;p&gt;To access the service account, head over to your Firebase console, click on the &lt;strong&gt;Settings&lt;/strong&gt; icon in the top-left corner of the developer console, and select &lt;strong&gt;Project Settings&lt;/strong&gt;. Then, select the &lt;strong&gt;Service Account&lt;/strong&gt; tab, and click on &lt;strong&gt;Generate new private key&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrJeSRRRRa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrJeSRRRRa.jpg" alt="service accout key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste the downloaded JSON file from the download folder into the &lt;code&gt;src&lt;/code&gt; directory of your project, and rename it as follows: &lt;code&gt;FirebaseService.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then. in the &lt;code&gt;config/firebase.js&lt;/code&gt; file, include the following 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="c1"&gt;// file: src/config/firebase.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&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;firebase-admin&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;serviceAccount&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;../firebaseService.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serviceAccount&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;This code initializes the Firebase Admin SDK in the Node.js app, providing administrative access to Firebase services, using the service account credentials loaded from the JSON file. &lt;/p&gt;

&lt;p&gt;This ensures that the application has the necessary privileges to interact with and manage Firebase resources programmatically, including accessing and validating tokens included in subsequent HTTP requests.&lt;/p&gt;

&lt;p&gt;Make sure to export the admin instance in your code.&lt;br&gt;
&lt;code&gt;module.exports = {admin};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, create the middleware that will validate the tokens. To do that, create a new &lt;code&gt;middleware&lt;/code&gt; directory in the &lt;code&gt;src&lt;/code&gt; folder, and inside this folder, create a new &lt;code&gt;index.js&lt;/code&gt; file, and include the following 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="c1"&gt;// file: src/middleware/index.js&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;admin&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;../config/firebase&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;verifyToken&lt;/span&gt; &lt;span class="o"&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;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;=&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;idToken&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;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&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;idToken&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;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="s1"&gt;No token provided&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;try&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;decodedToken&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;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;verifyIdToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idToken&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;decodedToken&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;catch &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="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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error verifying token:&lt;/span&gt;&lt;span class="dl"&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="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="s1"&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="nx"&gt;verifyToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This middleware will verify the authenticity of the tokens passed in subsequent requests, ensuring secure access to protected routes. We'll include it in the routes that require authentication.&lt;/p&gt;

&lt;p&gt;Finally, include this logout handler to sign out users, and clear the token cookies:&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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &lt;/span&gt;

&lt;span class="nf"&gt;logoutUser&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;clearCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access_token&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User logged out successfully&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;catch&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;error&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="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;500&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;Internal Server Error&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will effectively logs out a user, clear their access token cookie, and sends an appropriate response. &lt;/p&gt;

&lt;h2 id="step-7-handling-account-management-tasks"&gt;Step 7: Handling Account Management Tasks&lt;/h2&gt;

&lt;p&gt;Now, let's implement a handler function that will allow users to manage and reset their passwords. Firebase will take care of the underlying complexities, from generating the email reset link and sending it, to updating the password. &lt;/p&gt;

&lt;p&gt;To do that, include this &lt;code&gt;resetPassword&lt;/code&gt; controller in the controllers class:&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="c1"&gt;// file: src/controllers/firebase-auth-controller.js &lt;/span&gt;

&lt;span class="nf"&gt;resetPassword&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&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="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;email&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;422&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is required&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;sendPasswordResetEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password reset email sent successfully!&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;catch&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;error&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="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;500&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;Internal Server Error&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sendPasswordResetEmail&lt;/code&gt; method will send a password reset email to the specified email address. Users can then update their update their passwords through Firebase's UI page rendered on the browser.&lt;/p&gt;

&lt;h2 id="step-8-defining-the-api-routes"&gt;Step 8: Defining the API Routes&lt;/h2&gt;

&lt;p&gt;Now, create a new &lt;code&gt;routes&lt;/code&gt; folder. Inside this folder, add a new &lt;code&gt;index.js&lt;/code&gt; file, and include the following contents:&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="c1"&gt;// file: src/routes/index.js &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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&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;firebaseAuthController&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;../controllers/firebase-auth-controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&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;/api/register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firebaseAuthController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;router&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;/api/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firebaseAuthController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;router&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;/api/logout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firebaseAuthController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logoutUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;router&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;/api/reset-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firebaseAuthController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetPassword&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;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, import the routes object in the app.js file as follows:&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="c1"&gt;// file: src/app.js &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&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;./routes&lt;/span&gt;&lt;span class="dl"&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;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Let's proceed to testing your API's authentication functionality.&lt;/p&gt;

&lt;h2 id="testing-authentication-flow"&gt;Testing Authentication Flow&lt;/h2&gt;

&lt;p&gt;Go ahead and restart the development server.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node src/app.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are several testing approaches you can take to ascertain the functionality of the auth API. One way would be to automate the testing using unit tests with tools like &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/supertest" rel="noopener noreferrer"&gt;Supertest&lt;/a&gt;. Alternatively, you can make use of API clients like &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; or the &lt;a href="https://www.thunderclient.com/" rel="noopener noreferrer"&gt;Thunder Client&lt;/a&gt; VS Code extension to test the API.&lt;/p&gt;

&lt;p&gt;In this case, we'll make use of Postman to test the various endpoints. For starters, assuming you want to register a new user using their email and password, go ahead and make a POST request and pass these values to this endpoint: &lt;code&gt;http://localhost:5000/api/register&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSktqNkyJC.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSktqNkyJC.jpg" alt="user registration endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should receive a successful registration status message along with the email verification message. Check your inbox for the email, and click the link provided to verify your email address. &lt;/p&gt;

&lt;p&gt;The good thing is that Firebase provides default UI pages for such processes. However, depending on your implementation, feel free to customize the pages to match your app's designs.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrksTVJk1C.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrksTVJk1C.jpg" alt="email verification UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, with the same credentials, make a POST request to the &lt;code&gt;http://localhost:5000/api/login&lt;/code&gt; endpoint to test the login endpoint.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FB16lryky0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FB16lryky0.jpg" alt="login endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once a user successfully logins with their credentials, a user object with various user-specific information is returned. Assuming they had verified their email after registration, the response will include an emailVerified key with a true value. You can then use this information to allow them to access certain features or resources in your application.&lt;/p&gt;

&lt;p&gt;Moreover, once they log in, the access token will be set in the cookies as follows:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSkHXrJ11C.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSkHXrJ11C.jpg" alt="access token cookie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is set, it will be automatically included in subsequent requests in the app to access protected resources.&lt;/p&gt;

&lt;p&gt;For instance, assuming you want to build a blog and render a list of posts to authenticated users, go ahead, and create a new &lt;code&gt;controllers/post-controller.js&lt;/code&gt; file. Then, define the following controller that should return a list of user posts:&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="c1"&gt;// file: src/controllers/post-controller.js&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;getPosts&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="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usersPosts&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="dl"&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;Post 1&lt;/span&gt;&lt;span class="dl"&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;2&lt;/span&gt;&lt;span class="dl"&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;Post 2&lt;/span&gt;&lt;span class="dl"&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;3&lt;/span&gt;&lt;span class="dl"&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;Post 3&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usersPosts&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, include this route, along with the &lt;code&gt;verifyToken&lt;/code&gt; middleware you created earlier to validate the token passed alongside the requests.&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="c1"&gt;// file: src/routes/index.js &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verifyToken&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;../middleware&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;PostsController&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;../controllers/posts-controller.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;router&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="s1"&gt;/api/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;verifyToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PostsController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, once you successfully log in and make a GET request to access the list of posts through this endpoint: &lt;code&gt;http://localhost:5000/api/posts&lt;/code&gt;, you should receive the following data as a response:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSJvqH1yJC.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FSJvqH1yJC.jpg" alt="posts endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember, this is just a basic implementation. Ideally, the &lt;code&gt;PostsController&lt;/code&gt; should be trying to access your app's resources, including data in the database, and return it to the user on the client-side app.&lt;/p&gt;

&lt;p&gt;Now, assuming a user wants to reset their password, Firebase's &lt;code&gt;sendPasswordResetEmail&lt;/code&gt; takes the &lt;code&gt;auth&lt;/code&gt; object and email as parameters, and similar to the email verification method, it sends a password reset email containing a link that allows you to access the password reset UI page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkDRH1k1C.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBkDRH1k1C.jpg" alt="password reset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the link provided in the password reset email to access the Firebase default password reset UI page to reset and save the new password.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrkAy8kkk0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FrkAy8kkk0.jpg" alt="password reset UI page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that when you want to update the password using the Firebase Authentication reset password method, you should use the POST HTTP method to send the request, instead of the PATCH method. Ideally, Firebase's reset password flow typically involves the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends a POST request to a server endpoint (e.g., /api/reset-password) with the user's email address in the request body. &lt;/li&gt;
&lt;li&gt;The server receives the request and calls the &lt;code&gt;sendPasswordResetEmail&lt;/code&gt; function from the Firebase Authentication SDK, passing the provided email address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this flow, the client is not updating a specific resource on the server. Instead, the client is initiating a password reset process by sending a POST request with the user's email address. The server then triggers the Firebase Authentication password reset flow, which is handled entirely by Firebase.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;PATCH&lt;/code&gt; method, however, is typically used when you want to update a specific resource on the server, such as a user's profile data or a specific document in a database. However, in the case of the Firebase Authentication reset password method, there is no specific resource being updated on the server side. The server is simply acting as an intermediary to initiate the password reset process with Firebase.&lt;/p&gt;

&lt;h2 id="best-practices-when-handling-authentication-using-firebase"&gt;Best Practices When Handling Authentication Using Firebase&lt;/h2&gt;

&lt;p&gt;When handling authentication using Firebase, it's essential to follow best practices to ensure secure and efficient authentication systems. Here are some key points to consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Securing Firebase API keys in Node.js applications is a critical step to maintain the security and integrity of your application. &lt;/p&gt;

&lt;p&gt;The recommended approach is to store sensitive information like Firebase API keys and configuration details as environment variables on your server or hosting platform. This prevents these sensitive values from being exposed in your codebase, reducing the risk of accidental leaks or unauthorized access. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Firebase authentication provides a robust and scalable authentication system that supports various authentication providers. &lt;/p&gt;

&lt;p&gt;However, it's also essential to implement proper user management practices, such as handling authentication states appropriately in your application, including implementing secure storage mechanisms for user tokens (e.g., encrypted cookies or local storage), as well as handling token refresh when necessary to maintain uninterrupted access for the user. &lt;br&gt;
And when users logout or sessions expire, revoke access tokens to prevent unauthorized use of user accounts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When handling errors related to authentication and user management, implement proper error handling mechanisms that capture and log errors, while also, displaying user-friendly messages and feedback UI screens to guide users through appropriate steps to resolve issues, as well as provide a great user experience.&lt;/p&gt;

&lt;p&gt;Avoid logging raw error messages or stack traces (especially in production), as they may contain sensitive information that could be utilized for malicious purposes. &lt;/p&gt;

&lt;p&gt;Furthermore, make sure to implement input validation and sanitization to prevent common security vulnerabilities like SQL injection, cross-site scripting (XSS), and other types of attacks. &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this article, we covered the essential steps to integrate Firebase Authentication into a Node.js application, covering the implementation of user registration, login, logout, and password reset functionality using Firebase Authentication SDK.&lt;/p&gt;

&lt;p&gt;If you're interested in learning more about Firebase Authentication and its integration with Node.js, here are some valuable resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://firebase.google.com/docs/auth" rel="noopener noreferrer"&gt;Firebase authentication documentation&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can find this project's code in this &lt;a href="https://github.com/ItsWachira/Firebase-authentication-Express.js" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firebase offers a comprehensive suite of services beyond just Authentication, including Realtime Database, Cloud Firestore, Cloud Functions, and more. We encourage you to explore these services to build scalable, secure, and feature-rich applications.&lt;/p&gt;

</description>
      <category>node</category>
      <category>authentication</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Policy-Based Access Control (PBAC): A Comprehensive Overview</title>
      <dc:creator>Ege Aytin</dc:creator>
      <pubDate>Tue, 16 Apr 2024 14:22:24 +0000</pubDate>
      <link>https://dev.to/permify/policy-based-access-control-pbac-a-comprehensive-overview-1n9f</link>
      <guid>https://dev.to/permify/policy-based-access-control-pbac-a-comprehensive-overview-1n9f</guid>
      <description>&lt;p&gt;Broken access control, privilege creep and role explosion put all organizations at risk. Long gone are the days when we just had couple roles within an organization, today we’re looking at dozens or even hundreds of different roles. This not only makes the task of managing roles harder but it also puts those organizations at risk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What Is Policy Based Access Control (PBAC)?&lt;/li&gt;
&lt;li&gt;Differences Between ABAC, RBAC, ReBAC and PBAC&lt;/li&gt;
&lt;li&gt;Major Strengths of PBAC&lt;/li&gt;
&lt;li&gt;PBAC Use Cases And Examples&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modeling and managing user access within systems is more crucial than ever for data security, integrity and compliance.&lt;/p&gt;

&lt;p&gt;There are plenty of access control models available on the market today. &lt;/p&gt;

&lt;p&gt;Well-known examples include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role-Based Access Control (RBAC), &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://permify.co/post/relationship-based-access-control-rebac/"&gt;Relationship-Based Access Control (ReBAC)&lt;/a&gt;, &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://permify.co/post/implementing-opa/"&gt;Attribute-Based Access Control (ABAC)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, in this piece we're focusing on the &lt;strong&gt;PBAC&lt;/strong&gt; model also known as &lt;strong&gt;Policy-Based Access Control&lt;/strong&gt; and how it differentiates itself these from traditional access control models in terms of scalability, flexibility and security.&lt;br&gt;
&lt;a href="https://github.com/Permify/permify/"&gt;&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---W8iDHJa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/Permify/permify/assets/34595361/c3933934-c3a4-44fb-a3fc-dbdf5aff4e95" alt="Local Image" width="800" height="230"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="what-is-policy-based-access-control-pbac"&gt;What Is Policy Based Access Control (PBAC)?&lt;/h2&gt;

&lt;p&gt;To put it simply, it is an authorization method which governs access to resources based on policies that reflect an organization's business objectives.&lt;/p&gt;

&lt;p&gt;The PBAC model uses both attributes and roles to derive policies, unlike traditional access control frameworks where only roles or attributes are used to derive access rights. This feature makes PBAC a truly powerful and dynamic approach to control parameters. &lt;/p&gt;
&lt;h3&gt;
  
  
  Powered by Policy As Code (PaC)
&lt;/h3&gt;

&lt;p&gt;Unlike traditionally where policies are manually enforced, not scalable and lack framework for implementation. The PBAC model applies policies in a completely different way.&lt;/p&gt;

&lt;p&gt;The PBAC model uses a methodology called policy as code (PaC), meaning that policy can be written directly into code. &lt;/p&gt;

&lt;p&gt;It gets rid of the manual work of compliance teams and merges into the code automating its processes along the way. From version control, review and validation, everything is automated from A to Z.&lt;/p&gt;

&lt;p&gt;And you’ve guessed it, there are multiple benefits to automating policy management with PaC, here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More secure&lt;/li&gt;
&lt;li&gt;Helps avoiding human error&lt;/li&gt;
&lt;li&gt;Easier to audit&lt;/li&gt;
&lt;li&gt;Running test cases is a lot easier&lt;/li&gt;
&lt;li&gt;Check and enforcement of policy is automated&lt;/li&gt;
&lt;li&gt;Automation = Scalable&lt;/li&gt;
&lt;li&gt;Saves times and money&lt;/li&gt;
&lt;li&gt;Integrates policy within development&lt;/li&gt;
&lt;li&gt;Gives a framework to how policies are to be implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: A policy can be anything that governs operations and processes within an application or organization using PBAC, this can be a rule, condition or an instruction.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="differences-between-abac-rbac-rebac-and-pbac"&gt;Differences Between ABAC, RBAC, ReBAC and PBAC&lt;/h2&gt;

&lt;p&gt;To better explain the differences between PBAC and these common access control models, first, we'll give a brief summary of them, then move on to PBAC and the differentiation.&lt;/p&gt;

&lt;p&gt;Let's start with Attribute Based Access Control (ABAC).&lt;/p&gt;
&lt;h3&gt;
  
  
  Attribute-based Access Control (ABAC)
&lt;/h3&gt;

&lt;p&gt;An ABAC model will use attributes derived from a subject, resource or environment to decide if access is granted or not to a resource within a system. &lt;/p&gt;

&lt;p&gt;These attributes can be any value which makes this model able to handle complex scenarios.&lt;/p&gt;

&lt;p&gt;In this model, authorization is more fine-grained because these attributes can have a dynamic value which can change. &lt;/p&gt;

&lt;p&gt;Enabling us to define dynamic authorization rules and behaviors, one example is controlling which action can be performed within a system based on a user’s time, location and IP address.&lt;/p&gt;

&lt;p&gt;ABAC models can get quite complex and come with the risk of unwanted behaviors if the values of these attributes aren’t looked after and audited. It is also complex to administrate, it takes longer to learn and become an expert at.&lt;/p&gt;
&lt;h3&gt;
  
  
  Role-based Access Control (RBAC)
&lt;/h3&gt;

&lt;p&gt;In a RBAC model permissions are defined as actions a user can take on a resource. &lt;/p&gt;

&lt;p&gt;These permissions are then grouped into roles and those roles are then assigned to subjects in a system. These subjects can be Users, Groups or Systems. &lt;/p&gt;

&lt;p&gt;Roles in this type of model are static making it a lot easier to map and see how they relate to each other.&lt;/p&gt;

&lt;p&gt;The RBAC model comes with a downside which is &lt;a href="https://permify.co/post/role-explosion/"&gt;role explosion&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This happens when there are so many authorization scenarios that a large number of roles are required to cover all of them. Which makes the task of managing roles a lot more difficult and in some cases can be a security concern. &lt;/p&gt;

&lt;p&gt;One of the downsides of this model is that it takes considerable time to implement because administrators need time to figure out each role and their permissions.&lt;/p&gt;
&lt;h3&gt;
  
  
  Relationship-based Access Control (ReBAC)
&lt;/h3&gt;

&lt;p&gt;As the name says, this model relies on relationships to derive authorization. &lt;/p&gt;

&lt;p&gt;This is done by ascribing relationships between subjects and resources in a system. These relationships can get quite complex when grouping resources. ReBAC is a “policy-as-data” type of model, unlike other models which are “policy-as-code” type.&lt;/p&gt;

&lt;p&gt;This type of authorization modeling can be done with other models, but is a lot easier and concise when done with ReBAC because a graph is often used to build this type of model. &lt;/p&gt;

&lt;p&gt;It is also a flexible model allowing us to have authorization at a resource level and it also offers a parent-child relationship between subjects and resources.&lt;/p&gt;
&lt;h3&gt;
  
  
  Policy-based Access Control (PBAC)
&lt;/h3&gt;

&lt;p&gt;PBAC has some key benefits over older frameworks, the key reason is that policies are used to derive authorization by combining both a subject’s tasks and policies using a policy-as-code methodology.&lt;/p&gt;

&lt;p&gt;Another key feature which makes it a lot more attractive than other solutions is its simplicity in creating and testing policies. This is great for running audits and being compliant with strict privacy laws in certain jurisdictions.&lt;/p&gt;

&lt;p&gt;While a role-based system grants access based on roles, a policy based system grants access based on policies, this offers us a lot of flexibility when managing access permissions. PBAC models are built to scale with an organization’s growth through automation, write once and it takes care of the rest. &lt;/p&gt;

&lt;p&gt;Unlike ABAC where rules are written in eXtensible Access Control Markup Language (XACML) or using the Open Policy Agent (OPA) using the Rego language which is often hard to understand for someone without a background in IT.&lt;/p&gt;

&lt;p&gt;On the other hand, PBAC providers allow policies to be coded in a plain language format and in some cases using a Graphical User Interface (GUI). Making implementing access control policies easier for management teams by not having to rely on the IT department to make changes every now and then.&lt;/p&gt;

&lt;p&gt;Here’s a simple illustration of how a PBAC model would work in a work environment with employees:&lt;/p&gt;

&lt;p&gt;Pieces of information and data are the building blocks of a PBAC model, it relies on them to make access decisions. By using existing data it offers a flexible solution to policy building. In terms of clarity PBAC is the winner, it gives administrators a clear view of who has access to what, when and how across all assets within an organization.&lt;/p&gt;

&lt;p&gt;Let’s have a deeper look into what makes PBAC so unique.&lt;/p&gt;

&lt;h2 id="major-strengths-of-pbac"&gt;Major Strengths of PBAC&lt;/h2&gt;
&lt;h3&gt;
  
  
  Dynamic and Flexible
&lt;/h3&gt;

&lt;p&gt;PBAC models are dynamic, meaning that they can take multiple parameters into consideration when granting access and permissions to a user, which enables us to be specific when creating rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User attributes (Employee, CEO, CTO)&lt;/li&gt;
&lt;li&gt;Resource attributes (File, Database, Network segments)&lt;/li&gt;
&lt;li&gt;Action attributes (Login, Read, Write)&lt;/li&gt;
&lt;li&gt;Contextual or environmental attributes (Physical Location, Device, Time)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PBAC uses Boolean logic when assessing if access should be granted or not, it does so by processing these attributes in an “if, then” manner which is different from other models.&lt;/p&gt;

&lt;p&gt;We can apply rules within a PBAC system in a fully-automated fashion, making it adaptable to changing conditions, such as not allowing an employee to gain access to a system during weekends from his home computer. This gives us more control and enables us to make access decisions in real-time with high-granularity by taking context into consideration.&lt;/p&gt;

&lt;p&gt;Policy based systems are dynamic by nature, making them adaptable to an organization's needs, whether it’s a small startup or a full blown enterprise with dozens of departments.&lt;/p&gt;

&lt;p&gt;They’re also blazingly fast, as an administrator you have full control over user permissions, you can add, remove or edit permissions to every single user within an organization at the click of your mouse.&lt;/p&gt;
&lt;h3&gt;
  
  
  Secure and Reliable
&lt;/h3&gt;

&lt;p&gt;As humans we’re prone to errors and this is no exception when it comes to managing policies and access control. Policy management can be automated within a PBAC system removing the need of a human to manually review policies which is great for security.&lt;/p&gt;

&lt;p&gt;Another benefit of using the PBAC model is the separation of privileges within an organization where each component is isolated to minimize the risk in the event of a security breach. Take for example a hacker who compromises one segment of a network, they won’t get full access to the rest of the network if privileges are strictly regulated across the network.&lt;/p&gt;

&lt;p&gt;PBAC closes the security gaps left open by RBAC and this is done by being proactive with access control security.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compliant and Consistent
&lt;/h3&gt;

&lt;p&gt;Being compliant today is important when it comes to following regulatory laws in certain jurisdictions. PBAC systems make the task a lot easier for compliance teams to follow legal requirements from data privacy and security laws such as GDPR, HIPAA and CPRA.&lt;/p&gt;

&lt;p&gt;PBAC enables us to easily align internal policies with access control by regulating access to sensitive data across an organization or application in a consistent and systematic way.&lt;/p&gt;

&lt;h2 id="pbac-use-cases-and-examples"&gt;PBAC Use Cases And Examples&lt;/h2&gt;

&lt;p&gt;As said earlier, PBAC is extremely dynamic in nature and can adapt to different environments. It can scale with an organization’s growth, if a policy states that “HR can access employee data”, it does not matter if there are a hundred or a thousand employees. The policy still applies and is enforced.&lt;/p&gt;

&lt;p&gt;Let’s have a look at real-world examples where PBAC is in action:&lt;/p&gt;

&lt;p&gt;Let’s see a simple example of an attorney working in a legal firm, here’s how access control policies in a PBAC system would be applied to him.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Policy&lt;/strong&gt;: Allow access to the firm’s main portal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Policy&lt;/strong&gt;: Allow access to client files assigned to him.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Action Policy&lt;/strong&gt;: Allow permission to read and edit files of clients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environmental and Contextual Policy&lt;/strong&gt;: Block access to the firm's portal on Sunday’s and Saturday’s.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how it would be implemented in Python using the &lt;a href="https://aws.amazon.com/about-aws/whats-new/2023/05/cedar-open-source-language-access-control/"&gt;Cedar&lt;/a&gt; policy language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cedar.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CedarClient&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize Cedar client
&lt;/span&gt;&lt;span class="n"&gt;cedar_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CedarClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_CEDAR_API_KEY_HERE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CEDAR_API_BASE_URL_HERE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# User Policy: Allow access to the firm's main portal.
&lt;/span&gt;&lt;span class="n"&gt;user_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;employee&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resource&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;portal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;firm&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;permission&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;allow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Resource Policy: Allow access to client files assigned to him.
&lt;/span&gt;&lt;span class="n"&gt;resource_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;employee&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resource&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;file_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;client&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;permission&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;allow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Action Policy: Allow permission to read and edit files of clients.
&lt;/span&gt;&lt;span class="n"&gt;action_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;employee&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;read&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;edit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;permission&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;allow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Environmental and Contextual Policy: Block access to the firm's portal on Sundays and Saturdays.
&lt;/span&gt;&lt;span class="n"&gt;contextual_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;day&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Sunday&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Saturday&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resource&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;portal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;firm&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;permission&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deny&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Add policies to Cedar
&lt;/span&gt;&lt;span class="n"&gt;cedar_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_policy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cedar_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resource_policy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource_policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cedar_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action_policy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action_policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cedar_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;contextual_policy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contextual_policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Here’s how to check access for a user attempting to login into the firm's portal on a Sunday.
&lt;/span&gt;&lt;span class="n"&gt;user_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;employee&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;resource_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;portal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;firm&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Sunday&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;access_permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cedar_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource_attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access permission:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;access_permission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There are multiple access control models out there, all with their pros and cons when it comes to authorization management. &lt;/p&gt;

&lt;p&gt;As we’ve seen, some of them require a high level of expertise in access control management to implement, others not.&lt;/p&gt;

&lt;p&gt;In this article, we’ve seen the nuts and bolts of each one of them and how they manage and derive access control rulings using either attributes, roles, relationships or policies. &lt;/p&gt;

&lt;p&gt;The PBAC model using the policy-as-code approach to define, update and enforce policies helps bridge the gap between the RBAC and ABAC model, offering the best of both worlds. &lt;/p&gt;

&lt;p&gt;It fills the gap left by older models, by making management easier and by being preventative and blocking potential doors leading to vulnerabilities.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
