Although this application code is built with Next.js, Permit.io provides SDKs for any common language, So this example can give you a good idea of how it should look in your language. Note that this tutorial is meant to be used on an application with Hanko authentication already set up. We highly recommend cloning our demo application so you can follow the steps more easily. If you prefer to read the article without cloning the application, skip this section and continue to Setup Basic Role Based Authorization.Documentation Index
Fetch the complete documentation index at: https://docs.hanko.io/llms.txt
Use this file to discover all available pages before exploring further.
To clone the demo application, run the following commands:
Setting up Hanko Passkey Authentication:
Setup your Hanko Webapp
Create a new project
Paste API URL
.env.local, in the root directory of
the application. When we run the application again, we can see that the error
is gone, and we can see the login page.Now, when we run the application again,
we can see that the error is gone, and we can see the login page.Add the authentication window
app/auth/login/page.tsx file.Redirection Logic
middleware.ts file that redirects the user to the login page if they are not authenticated:Setup Basic Role Based Authorization
With authentication done, it is time to set up our authorization layer. We’ll start with setting up basic role-based access control (RBAC) to determine the actions our users can perform. In the/app/api/notes/route.ts,
you’ll find four functions, GET, POST, PUT, and DELETE - responsible for the logic of getting, creating, updating, and deleting notes,
respectively.
If you look at the route.ts file, you will see that we are going to use a generic
permit.check middleware.ts
file.
permit.check function that checks the permissions configured for the application using three factors:
User - the entity that attempts to perform the operation (in our case, a user authenticated with Hanko).
Action - the operation that the user will attempt to perform (in our case, GET).
Resource - the entity that the user will attempt to perform the operation on (in our case, the note).
Create a Permit.io account
Create Roles

Create Resources and Actions
get, post, delete, and put.
Setup Permissions
post notes, and only admins to put, and delete notes.
Setup API Credentials
Copy SDK API Key.
Add the key in your in the env.local file:Sync Hanko Users to Permit.io
To check the permissions we configured, we need to sync the users from Hanko to Permit.io, so our users will be known to the Permit policy engine. We will want to automatically assign a user role to every new user, so they will also be part of our newly configured policy. This role helps us to keep the principle of least privilege and give new users only very basic permissions in the application. In the demo application, you can find the following code in thesrc/app/api/permit/route.ts file:
Check the Permissions
Login with a user
localhost:3000 page, log in with a user of your choice, and make
sure you have the right passkey configured.Create a new note
Check the Audit Logs
post action was logged. Clicking the log will allow
you to see detailed information about the authorization decision that
allowed for this action to be performed. Allow will equal true as this
user has the User role.
Add Fine-Grained Attribute-Based Authorization
Enable ABAC in Permit Dashboard

Define Resource Set Rule

Create a New Policy
put and
delete actions exclusively for the note’s owner. Ensure the admin role
retains all-action privileges.
Test with a New User

Create and Delete a Note
Enforce Permissions Everywhere
Sometimes, you will encounter a situation where you need to check permissions in the middle of the application logic. For example, you could want to restrict a particular operation to premium users only. Using Permit, the policy configuration always remains the same, and you’ll only have to use thepermit.check function in every place within the code to determine allowed/not allowed permissions.
permit.check function also lets you make decisions based on data that might not exist in the scope of the request in the middleware, so you get more granular decisions with no code changes.
Add Fine-Grained Relationship Based Authorization
Another approach for fine-grained authorization that we can use is Relationship-Based Access Control (ReBAC). Assuming a note app, we might want to create workspaces, organizations, and folders for our notes. In this case, we might do not have a dedicated owner field in the note entity, but we have a relationship between the note and the workspace. Permit also supports the configuration of ReBAC policies, we can easily implement it in our application without changing thepermit.check or any enforcement code in the app. Read more about modeling ReBAC here.