How manage access-control, permission and authorization with Permit.io
Permit.io is a platform for managing your permission infrastructure and allowing you to focus on the actual business requirement. With Permit.io you do not have to build your own solution to implement authorization, it has all the features(GUI Interface, Developer SDK) which comes really handy to manage the users roles and their authorization.
As being an external tool for handling access-control, permission and authorization, permit.io can be integrated with your web application or mobile app with their powerful SDK.
In this blog post we will talk about Permit.io and how you can make yourself familiar with this tool. Here are are key steps which we will go through -
- Setup an account with Permit.io
- Create Workspace
- Define Policy
- How to use Permit.io SDK to connect with you application
- Conclusion
Permit.io has a really good SDK support for other programming languages such as Node.js, Python, Java, .net, Go,Ruby. But for this blog I will be using Java as my preferred programming language to interact with the SDK.
1. 1. Setup an account with Permit.io
To begin with Permit.io you must sign up and create an account. For setting up an account you can goto app.permit.io. There are couple of ways you can register yourself -
- Using the Google Account
- Using the GitHub Account
I chose GitHub to proceed with the signup. In the next step GitHub will ask you to authorize Permit.io to access your GitHub account and you can simply click on Authorize permitio
After successful registration you will be redirected to welcome page of Permit.io for setting up -
- Policies
- Assign Roles
- Connect you app
Click on the Let’s Go to proceed forward
2. Create Workspace
To work with permit.io first we need to create a workspace and inside the workspace we will define policy and roles. Permit.io is really robust and it allows you to create multiple workspaces so that you can create multiple different projects.
But let’s just focus on a single project and we'll create our workspace with the name - JhooqOrg
Along with that you need to create Workspace Key and choose Company Size -
3. Define Policy
3.1 Create Resource and Actions
After creating the workspace we need to define the resource which needs to be protected. Let’s take an example to understand resource analogy while using permit.io
Let’s assume the resource name is a blog for Jhooq Org. Why I have chosen the resource name to be jhooq-blog because Jhooq is devops blog and following actions can be performed on the _jhooq-blog_ resource
- Read - This action will allow users to view the blog post.
- Edit - This action will allow users to compose new post as well as update any existing post on the blog
- Approve - This action is for providing the approval on the post.
- Delete - This action is for removing the post from the blog
- Copy-approval - This action is specifically for the copywriter to verify any copyright infringement.
So let’s first create a resource jhooq-blog
Now we need to define the actions on the jhooq-blog resource and these actions are - read, edit, approve, delete, copy-approval
3.2 Create RBAC(Role based access control)
Now let’s define the RBAC roles for the actions. We are going with the 4 roles .i.e. - Admin, Writer, Reviewer and Copywriter. Permit.io has a really simple UI to fill the inputs for the RBAC roles. After you have assigned the RBACs you can simply click on the Assign Permissions button.
3.3 Assign roles to the users
On the next screen you can assign RBAC roles to the different users present in your organization. (Since this blogpost is all about how to use permit.io, so i am gonna create some dummy users.)
You can even add some additional users by clicking on the Add User button if needed.
Great, now you have a user with correct RBAC roles assigned and you should see the following message.
In the next steps we are going to use the SDK provided by permit.io to use the RBAC policy which we have created.
4. How to use Permit.io SDK to connect with your application
After setting up the RBAC roles permit.io will provide you with the detailed instructions on how to use their SDK so that your application can connect with permit.io
As off now permit.io has a support for following programming languages -
- Node.js
- Python
- Java
- .net
To view the respective instructions you should click on the correct programming language. For this blog post I am going to choose the Java to be my preferred language to interact with permit.io
4.1 Install docker
The first primary requirement for using the permit.io is to install the docker so that you can start the docker container locally.
If you do not have docker installed then please refer to the official docker installation documentation.
4.2 Pull the latest permitio docker Image
After installing the docker image, you need to pull the latest permitio docker image. Run the following command to pull the docker image -
1docker pull permitio/pdp:latest
4.3 Run docker container with PDP_API_KEY
Now after downloading the latest docker image you need to run the docker image but for that you need PDP_API_KEY which is connected to your permit.io account and this key is unique for you to work with permit.io
Note - Then PDP_API_KEY will be available for you once you complete sign up and RBAC setup on permit.io
Here is the docker run command -
1docker run \
2-p 7766:7000 \
3--env PDP_API_KEY=eyJhbGciOiJSUzI1NiIsImtpZCI6IjRjYjFhYjYyLWVhZTctNDFmZS04NWMwLTAyZjFlNjMyN2FlZCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NTM3Mzc0MjAsImV4cCI6MTY4NTE4NzAyMCwiYXVkIjoiaHR0cHM6Ly9hcGkucGVybWl0LmlvL3YxLyIsImlzcyI6Imh0dHBzOi8vYXV0aC5wZXJtaXQuaW8vIiwic3ViIjoiNmU4NTJjNDM5OGU5NDg4YzhmODYzZTU5MjVlNDc2YWIifQ.E89NZ_tkIu8gMaa9CWQVRWjn23NIa2TxKCE-KEKt8_k9o-M-5HeCr_nF12oxTUsdGNAB6aJ_l6qMN_PM77jCyv2obyrHHtXCld-LLIKWjkogw7ESKW_a9Xy686PDu07OsoU0iF_FleEKotDqQ42XmL42LnKkLYvyzT6c3jfTIBDg3xwth-g3dVo5QXrOnPCfVSyb8LzN8v-1BmZc0yVUG-kyvdiMriMwctvzZ1dDPN_RxcmTXSCA6w3xsT9uOMLNzyToogns3M3sKC-PsnWH9gCWMmva7OCPIUJp1d9EjlubS6pTkT-2iZdUnedhM41gPHoojudMzsdDcN-d5kKzUONljxpZI9kRHIP4L54tUA57O0pFwM3fvuIcgJMKb9jpdKy6ZNp0gZrhvy9K13j-z2k_nK0DqbfQW4byLjWZr3EG0gTHj6SOI19J6yGQqUGJ5HXBy4EIjUpDr1K8rjB8eyS9muFlFWP7Nh93TWUtCCVFabT-p2MuFn0QDvPx_C56g5Qmz9QThwBfycZYmNeTV05kBNn626XrXYZ-wWR471CDcck_VORrm0BJkH0EpJgyv_6hWMfJxzJCLYoLOlKL-UkqKZXBqO9vRjuKscFZ-ac9VDahA-ls705NGauHDHO2F1HuJCLqusTb9kaSVUrpHYArm-OjzD7FGZf7YFQ1iEi29M \
4permitio/pdp
5
4.4 Setup your Spring Boot Application
So till now we have set up RBAC roles and successfully ran the docker image of permit.io. Now we will work on the actual application side where we will be using those RBAC roles inside the Spring Boot application.
1. Create a spring boot project - If you are using IDE like Intellij then it is very easy to create an spring boot project from the IDE (Intellij->File->New->Project->Spring Initializr) or else you can do it manually and the same instructions you can find it on the documentation shared by permit.io
But since now a days everyone uses the IDE and i prefer using Intellij, so i will create a Spring boot project from my intellij -
Also selected the Spring Boot 2.7.0 version along with few more dependencies lombok, Spring Configuration processor (The other dependencies are not mandatory but good to have)
Here is an screenshot of my project structure inside my Intellij -
2. Update the build.gradle - Now we have the basic spring boot project ready but to work with Permit.io we need to include the gradle dependencies which are needed to make the API call towards the Permit.io.
1dependencies {
2 implementation 'org.springframework.boot:spring-boot-starter'
3 compileOnly 'org.projectlombok:lombok'
4 annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
5 annotationProcessor 'org.projectlombok:lombok'
6 testImplementation 'org.springframework.boot:spring-boot-starter-test'
7 implementation 'org.springframework.boot:spring-boot-starter-web'
8
9 //Additional dependencies i have added to my project
10 implementation 'ch.qos.logback:logback-classic:1.2.10'
11 implementation 'ch.qos.logback:logback-core:1.2.10'
12 implementation 'org.slf4j:slf4j-api:1.7.33'
13 implementation 'com.google.guava:guava:30.1.1-jre'
14 implementation 'com.google.code.gson:gson:2.8.9'
15 implementation 'com.squareup.okhttp3:okhttp:4.9.3'
16
17 // add this line to install the Permit.io Java SDK in your project
18 implementation 'io.permit:permit-sdk-java:0.0.11'
19}
Note - For this complete setup to work you must use at least JDK 11 or higher version.
3. SpringBootController - We have everything ready except we need to write our own implementation on how we are going to use the Permit.io java SDK.
To keep the code simple and easy to understand we are gonna implement a REST API which will expects three parameters -
- fName - First Name
- lName - Last Name
- emailId - Email Id
After passing the above mentioned parameters we are gonna make a call towards the Permit.io to validate the user RBAC policies based on the parameters which we have passed.
Here is the breakdown of the code -
Initialize the permit SDK -
1private String apiKey = "<PUT_YOUR_API_KEY>";
2private String pdpURL = "http://localhost:7766";
3
4@GetMapping("/")
5ResponseEntity<String> home(@RequestParam final String fName,
6 @RequestParam final String lName,
7 @RequestParam final String emailId,
8 @RequestParam final String action) throws IOException,
9 PermitApiException {
10 // init the permit SDK
11Permit permit = new Permit(
12 new PermitConfig.Builder(apiKey)
13 .withPdpAddress(pdpURL)
14 .withDebugMode(true)
15 .build()
16);
Build a User Object -
1User user = new User.Builder(emailId)
2 .withEmail(emailId)
3 .withFirstName(fName)
4 .withLastName(lName)
5 .build();
Validate the user RBAC roles -
This is a crucial part because here our spring boot application is making a call towards Permit.io for validating the user’s RBAC roles. Since this is not a production grade application and our setup is pretty simple. We will pass-in three parameters -
- User object - This will have all the user attribute First name, Last Name and Email ID
- Action - The name of the action which you want to validate and it can be any of the following -
- read
- approve
- copy-approval
- edit
- delete
- Resource - The last would be the resource name and it should be the exact resource name which we have created during the initial setup .i.e. Jhooq-blog
After preparing the parameters we need to call permit.check(user, action, resource), it will do the RBAC validation based on the parameters which we have supplied.
Here is the code snippet -
1boolean permitted = permit.check(
2 user,
3 action,
4 Resource.fromString("jhooq-blog")
5);
The permit.check(user, action, resource) will return us back a boolean flag and based on the return value of the boolean flag we can make a decision for allowing the user or not.
The following code snippet returns a message in string format based on the value of the boolean flag.
1if (permitted) {
2 return ResponseEntity.status(HttpStatus.OK).body(
3 "Access is Allowed!"
4 );
5 } else {
6 return ResponseEntity.status(HttpStatus.FORBIDDEN).body(
7 "Access is not Allowed!"
8 );
9 }
4.5 Run and Test your spring boot application
Now our project is ready and we can create a spring boot jar file using the Gradle build task.
If you are using a terminal then you can run the gradle build
command to build the project and generate jar files.
After generating the jar file you can start the spring boot application from the terminal using the command -
1Java-jar JhooqPermitIO-0.0.1-SNAPSHOT.jar
Running the SpringBootApplication from Intellij - If you are doing some local development on Permit.io then you can run the application from Intelij itself.
Once you start the spring boot application you can verify it via logs which are generated during the application startup -
As you can see my spring boot application has started on the port 8080.
Test the rest endpoint to verify the RBAC - After starting the spring boot application let’s call the rest endpoint and we are gonna verify the RBAC policy using the two REST API calls for following actions -
- edit
- delete
Use Case 1 - As we have created a user Batman and he is Reviewer so he should be able view and edit the articles. So let’s pass the following parameters -
- fName - Bat
- lName - man
- emailId - batman@jhooq.com
- Action - edit
As you can see it has returned a successful message - You have a permission to edit article
Here is the java code for the reference -
1@PostMapping("/")
2 ResponseEntity<String> home(@RequestParam final String fName,
3 @RequestParam final String lName,
4 @RequestParam final String emailId) throws IOException{
5 Permit permit = new Permit(
6 new PermitConfig.Builder(apiKey)
7 .withPdpAddress(pdpURL)
8 .withDebugMode(true)
9 .build()
10 );
11
12 User user = new User.Builder(emailId)
13 .withEmail(emailId)
14 .withFirstName(fName)
15 .withLastName(lName)
16 .build();
17
18 boolean permitted = permit.check(
19 user,
20 "edit",
21 Resource.fromString("jhooq-blog")
22 );
23
24 if (permitted) {
25 return ResponseEntity.status(HttpStatus.OK).body(
26 "You have a permission to edit article"
27 );
28 } else {
29 return ResponseEntity.status(HttpStatus.FORBIDDEN).body(
30 "You don't have permission to edit"
31 );
32 }
33 }
Use Case 2 - Considering the same example which we have taken in Use Case 1 for Batman but this time we are gonna pass the action delete. So as we know Batman is a Reviewer and he does not have permission to delete the article, only users with admin role can delete the post.
Let’s verify the same with API and this time we are gonna pass following parameters -
- fName - Bat
- lName - man
- emailId - batman@jhooq.com
Here is the java code for your reference -
1@PostMapping("/updateRole")
2 ResponseEntity<String> updateRole(@RequestParam final String emailId,
3 @RequestParam final String role) throws IOException,
4 PermitApiException {
5 // init the permit SDK
6 Permit permit = new Permit(
7 new PermitConfig.Builder(apiKey)
8 .withPdpAddress(pdpURL)
9 .withDebugMode(true)
10 .build()
11 );
12
13 permit.api.assignRole(emailId,
14 role,
15 "default");
16 return ResponseEntity.status(HttpStatus.OK).body("Successfully update the role " + role);
17 }
18
4.6 Update the roles and permission on real time using permit API
In the previous use cases we validated the RBAC for the users. But apart from RBAC validations, Permit.io API lets you assign role, unassign role, create tenant, delete tenant, delete user on real time.(Please refer to api documentation for more details)
Let’s take an example where we will be assigning an Admin role to Batman user. If you remember, in our initial setup we have only assigned a Reviewer role.
Here is how we are gonna make a api call for assignRole -
1 permit.api.assignRole(emailId,
2 role,
3 "default");
We need to pass following parameters -
- emailId - batman@jhooq.com
- Role - admin
- tenant - default (Note- since we only have one tenant)
We can verify the same by logging into the permit.io UI -
Here is the complete code snippet for implementing updateRole API -
1 @DeleteMapping("/")
2 ResponseEntity<String> deleteRole(@RequestParam final String fName,
3 @RequestParam final String lName,
4 @RequestParam final String emailId) throws IOException, {
5 Permit permit = new Permit(
6 new PermitConfig.Builder(apiKey)
7 .withPdpAddress(pdpURL)
8 .withDebugMode(true)
9 .build()
10 );
11
12 User user = new User.Builder(emailId)
13 .withFirstName(fName)
14 .withLastName(lName)
15 .withEmail(emailId)
16 .build();
17
18 boolean permitted = permit.check(
19 user,
20 "delete",
21 Resource.fromString("jhooq-blog")
22 );
23
24 if (permitted) {
25 return ResponseEntity.status(HttpStatus.OK).body(
26 "Deleted Successfully"
27 );
28 } else {
29 return ResponseEntity.status(HttpStatus.FORBIDDEN).body(
30 "You don't have permission to delete"
31 );
32 }
33 }
5. Conclusion
Using Permit.io you can benefit from the advantages of OPA(Open policy agent for generic policy-based decision engine) as well OPAL(Open policy administration layer to provide a real-time solution to keep policy agents updated with the policies and data they need in an event-driven distributed fashion.)
Also there are many use cases and advantages which I can vouch for Permit.io after using it -
- You have very granular control over the RBAC roles and Permit.io has done a very good job by segregating the workflow in term of Workspace, Resource, Tenants, Actions on resources
- Using Permit.io you have an advantage of making real time changes to the policy so that paid user/subscription based users do not have to wait to activate their services.
- Multiple tenants concept can help you to implement Access and Authorization solutions across multiple products of your ecosystem.
- Permit.io has a really good support for SDK in different flavors(Node.js, Python, Java, Go, .net, Ruby) which makes it more adaptive and easy to integrate.
Caveats - Examples and code taken in this blog are not meant to be used in production because all the REST API calls have to be secured and must be made accessible on https. Permit.io API Key must be stored securely and if possible must be stored in vaults so that it does not end up in a public code repository.