Implementing Fine-grained Authorization in ASP.NET Application
Integrate fine-grained authorization into your ASP.NET application to build enterprise-grade systems where users can perform actions and access resources based on precisely defined permissions.
This guide shows you how to add fine-grained authorization to an ASP.NET application using Permit.io. You will set up a policy for creating posts and comments, register users, assign them roles (like Author, Moderator, or Reader), and enforce permissions directly in your app's endpoints.
By the end, you will have a working example where only authorized users can access protected endpoints, and you will understand how to integrate Permit.io into your own ASP.NET applications.
Prerequisites
- ASP.NET application
- Docker (for running the PDP server)
- Node.js (for installing and running the Permit CLI)
- Permit.io account (Follow this guide to create an account)
Policy Configuration
Before integrating Permit.io with your ASP.NET application, you need to configure a policy. If you already have a policy configured, you can skip this section and proceed directly to the integration guide.
Configure Policy in Permit
Installing the Permit CLI
First, install the Permit CLI. The Permit CLI is a command-line tool that allows you to create policies, run the PDP server, and perform other tasks. To install the CLI, run the following command in your terminal:
npm install -g @permitio/cli
Once the installation is complete, run permit
to confirm the installation.
Authenticating the CLI
To use the CLI, authenticate it with your Permit account. Run:
permit login
This command opens a browser window and prompts you to log in with your Permit account. After logging in, the CLI is authenticated and ready to use. This also logs you into the default environment (a project can have multiple environments).
You can change the environment by running permit env select
and then selecting the environment you want to use.
Creating a policy with a template
The Permit CLI offers various templates to create a policy with predefined roles and resources using best practices. This simplifies policy creation compared to starting from scratch.
To check the available templates, run permit template list
. You can also visit the Permit CLI repo to see the templates and the actual terraform code for each template.
Use the blogging-platform template to create the policy. This template helps you set up a policy for a blogging platform with roles and resources. The policy is explained in detail in the next step.
To apply the template, run the following command:
permit template apply --template blogging-platform
You will see a success message in the terminal.
Understanding and accessing the policy from the dashboard
Next, go to the Permit dashboard, select your project, and click on the Policy tab in the left sidebar. You will see the policy you just created.
- For the blog application, there are two resources: Posts and Comments. Depending on the role and action, the user will have access to the resource. New users accessing the blog are assigned the Reader role and have permission to read posts.
- As users become Authors, they gain access to create and update blog posts and manage comments.
- There is also a relationship between Post and Comment resources: the person who creates a post automatically becomes a Comment Moderator.
- A Free Post resource set filters non-premium posts, allowing Readers to access only free content. This is a ReBAC setup.
This setup combines ABAC and ReBAC to enforce flexible and secure permissions. You can easily add or remove permissions by checking or unchecking them in the policy editor.
Integration Guide
Now that you have a policy configured, you can integrate Permit.io with your ASP.NET application. The following steps will guide you through the integration process.
Getting the API key
To get the API key:
- Click on Projects in the left sidebar.
- Click on the three dots for the environment you want to use.
- Click on Copy API Key and store it in a safe place. You will use this API key to authenticate your application with Permit.io. If you have any difficulty getting the API key, follow this guide.
Once you have the API key, proceed to integrate Permit.io with your ASP.NET application.
Setting up the ASP.NET application with Permit.io
Start by creating a new ASP.NET application. Create a new file called Program.cs
and add the following code to it.
// Program.cs
using System;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using PermitSDK;
using PermitSDK.Models;
using PermitSDK.OpenAPI.Models;
namespace PermitOnboardingApp
{
// HttpServer class to handle the incoming connections and route the requests to the appropriate endpoints
class HttpServer
{
public static HttpListener listener;
public static string url = "http://localhost:8000/";
public static string clientToken = Environment.GetEnvironmentVariable("PERMIT_API_KEY");
public static string pdpUrl = Environment.GetEnvironmentVariable("PDP_URL") ?? "http://localhost:7766";
public static Permit permit = new Permit(
clientToken,
"http://localhost:7766",
"default",
true
);
// HandleIncomingConnections function to handle the incoming connections and route the requests to the appropriate endpoints
public static async Task HandleIncomingConnections()
{
bool runServer = true;
while (runServer)
{
HttpListenerContext ctx = await listener.GetContextAsync();
HttpListenerRequest req = ctx.Request;
HttpListenerResponse resp = ctx.Response;
string path = req.Url.AbsolutePath.ToLower();
string method = req.HttpMethod.ToUpper();
// Handle the incoming connections and route the requests to the appropriate endpoints
try
{
if (method == "POST" && path == "/register")
{
await HandleRegister(req, resp);
}
else if (method == "POST" && path == "/posts")
{
await HandlePosts(req, resp);
}
else
{
resp.StatusCode = 404;
await SendJsonAsync(resp, new { error = "Not found" });
}
}
catch (Exception ex)
{
resp.StatusCode = 500;
await SendJsonAsync(resp, new { error = ex.Message });
}
}
}
}
}
The Permit SDK is initialized with the PERMIT_API_KEY
(the API key you copied from the Permit dashboard) and the PDP_URL
(the URL of the PDP server). You will set these up later.
HandleIncomingConnections
is the main function that handles the incoming connections and routes the requests to the appropriate endpoints. HandleRegister
and HandlePosts
are the endpoints for registering a user and creating a post respectively.
Main and helper functions
Add the following code to the HttpServer
class:
// Program.cs
// SendJsonAsync function to send a JSON response
public static async Task SendJsonAsync(HttpListenerResponse resp, object obj)
{
resp.ContentType = "application/json";
var json = JsonSerializer.Serialize(obj);
byte[] data = Encoding.UTF8.GetBytes(json);
await resp.OutputStream.WriteAsync(data, 0, data.Length);
resp.Close();
}
public static void Main(string[] args)
{
listener = new HttpListener();
listener.Prefixes.Add(url);
listener.Start();
Console.WriteLine("Listening for connections on {0}", url);
Task listenTask = HandleIncomingConnections();
listenTask.GetAwaiter().GetResult();
listener.Close();
}
Main
function starts the server and listens for incoming connections.SendJsonAsync
is a helper function to send a JSON response.
Registering a new user
To register a user, create an endpoint that registers a user inside the HttpServer
class.
// Program.cs
public class RegisterRequest
{
public string email { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
}
// HandleRegister function to register a user
public static async Task HandleRegister(HttpListenerRequest req, HttpListenerResponse resp)
{
using var reader = new StreamReader(req.InputStream, req.ContentEncoding);
var body = await reader.ReadToEndAsync();
var data = JsonSerializer.Deserialize<RegisterRequest>(body);
if (data == null || string.IsNullOrEmpty(data.email) || string.IsNullOrEmpty(data.first_name) || string.IsNullOrEmpty(data.last_name))
{
resp.StatusCode = 400;
await SendJsonAsync(resp, new { error = "Missing required fields" });
return;
}
var userObj = new UserCreate {
Key = data.email,
Email = data.email,
First_name = data.first_name,
Last_name = data.last_name,
Attributes = new System.Collections.Generic.Dictionary<string, object>()
};
var user = await permit.Api.SyncUser(userObj);
var assignedRole = new {
user = data.email,
role = "Reader",
tenant = "default"
};
var roleAssignment = await permit.Api.AssignRole(assignedRole.user, assignedRole.role, assignedRole.tenant);
resp.StatusCode = 201;
await SendJsonAsync(resp, new { message = "User registered and role assigned", user, role_assignment = roleAssignment });
}
This handler creates a /register
endpoint that allows new users to register for the blog application and assigns them the Reader role, giving them access to read posts.
Testing the registration process
To demonstrate the registration process, use the curl
command to make a request to the /register
endpoint. Register two users John and Emma. Both of these users will be automatically assigned the Reader role.
As shown in the image above, the users are created successfully and you receive information about the users in the response, such as id
, project_id
, key
, etc.
In the next step, we will assign John with the Author role to allow them to create a post.
Giving the user access to the resource
By default, users are assigned the Reader role. To allow John to create posts, assign him the Author role:
- Select Directory from the left sidebar in the Permit dashboard.
- Beside the user, click on the Add Instance Role button.
- Select tenant (default) from the dropdown.
- Select the Author role and Save button.
You will verify this later when you check the access.
Setting up the PDP server
At this point, your application is ready with the user synced and the policy created. To enforce the policy, use Permit's PDP (Policy Decision Point) to check if the user has access to the resource. First, set up the PDP.
Run the following command to spin up your environment PDP in a Docker container:
permit pdp run
After you run the above command, you will see output with information such as container ID, name, etc.
The PDP server runs on port 7766
by default. You can change the port if needed. Finally, update the PDP_URL
environment variable in your application.
Limiting the access to the resource
Add the following code to the HttpServer
class:
// Program.cs
// PostsRequest class to store the request body
public class PostsRequest
{
public string user { get; set; }
}
// HandlePosts function to check if the user has access to the resource
public static async Task HandlePosts(HttpListenerRequest req, HttpListenerResponse resp)
{
using var reader = new StreamReader(req.InputStream, req.ContentEncoding);
var body = await reader.ReadToEndAsync();
var data = JsonSerializer.Deserialize<PostsRequest>(body);
var action = "create";
var resource = "Post";
if (data == null || string.IsNullOrEmpty(data.user))
{
resp.StatusCode = 400;
await SendJsonAsync(resp, new { error = "Missing required fields" });
return;
}
bool permitted = await permit.Check(data.user, action, resource);
resp.StatusCode = permitted ? 200 : 403;
await SendJsonAsync(resp, new { message = permitted ? "User is permitted" : "User is not permitted" });
}
Since the blog application can have various elements like creating a post, commenting, editing, etc., create a new endpoint /posts
to demonstrate access control. Only users with the Author role can create a post.
You can use the same pattern to protect other endpoints, such as commenting, editing, or accessing premium content, by adjusting the action and resource values accordingly.
Checking the access
Now, check the policy enforcement. Since you have added the John user as an Author, you can check if the user has create access to the Post resource. To do this, use the curl
command to make a request to the /posts
endpoint.
As shown in the image above, the user is permitted to access the resource.
Now, check the access for Emma. Since she is not assigned the Author role, she should not be able to create a post and access the resource.
As shown in the image above, the user is not permitted to access the resource. This is how you can enforce policies using Permit.io with ASP.NET.
Conclusion
In this guide, you learned how to integrate Permit.io with ASP.NET. You created a simple ASP.NET application that syncs users and tenants with Permit.io. You also created endpoints to check whether users can access resources. You used the Permit SDK to enforce policies and check authorization. You also set up the PDP server locally using Docker.
Further Reading
- .NET SDK Documentation - Explore advanced features and API methods
- Building RBAC Policies - Create and manage role-based authorization policies
- Deploy to Production - Best practices for production deployment