PermitSDK.AspNet
1.0.0
See the version list below for details.
dotnet add package PermitSDK.AspNet --version 1.0.0
NuGet\Install-Package PermitSDK.AspNet -Version 1.0.0
<PackageReference Include="PermitSDK.AspNet" Version="1.0.0" />
<PackageVersion Include="PermitSDK.AspNet" Version="1.0.0" />
<PackageReference Include="PermitSDK.AspNet" />
paket add PermitSDK.AspNet --version 1.0.0
#r "nuget: PermitSDK.AspNet, 1.0.0"
#:package PermitSDK.AspNet@1.0.0
#addin nuget:?package=PermitSDK.AspNet&version=1.0.0
#tool nuget:?package=PermitSDK.AspNet&version=1.0.0
Permit AspNet
Easily protect APIs with Permit.io via attributes!
[HttpGet("articles/{id}")]
[Permit("read", "article")]
public Article[] GetArticles()
{
...
}
[HttpPost("articles/{id}")]
[Permit("write", "article")]
public Article UpdateArticle([FromRoute] string id, [FromBody] Article article)
{
...
}
Getting Started
Install the package from
NuGet
Configure the middleware:
// appsettings.json { ... "Permit": { "ApiKey": "<API_KEY>", // Required "PdpUrl": "http://localhost:7760" // Optional "DefaultTenant": "default" // Optional "UseDefaultTenantIfEmpty": true // Optional } }
// Program.cs builder.Services.AddPermit(builder.Configuration); // Or directly var permitOptions = new PermitOptions { ApiKey = "<API_KEY>" }; builder.Services.AddPermit(permitOptions);
Enable the middleware:
app.UseAuthentication(); // Require by default app.UseAuthorization(); // Add this line app.UsePermit(); app.MapControllers();
Use the
Permit
attribute to protect controllers or actions:[Permit(action: "read", resourceType: "article")] public Article[] GetArticles() { return new Article[] { ... }; }
How it works
For each request, the middleware does:
- Extract the user ID from the JWT token
NameIdentifier
claim (overridable) - Extract
action
andresourceType
from thePermit
attribute- Multiple attributes are run sequentially. Controller first, then action
- Use the
HttpClientFactory
to get aHttpClient
and call the PDP's/allowed
endpoint - If the user is not allowed, a
403
is returned - If the user is allowed, the request is processed
Minimal API
This library works with the new Minimal API introduced in ASP.NET Core 6 too:
app.MapGetArticles()
.WithName("GetArticles")
.RequirePermit("read", "article");
Resource instances
It's possible to specify a resource instance key in the Permit
attribute:
[HttpGet("articles/{id}")]
[Permit("read", "article", ResourceKeyFromRoute = "id")]
public Article GetArticle([FromRoute] string id)
{
...
}
There are many ways to specify the resource instance:
Property | Description |
---|---|
ResourceKey |
Static value |
ResourceKeyFromRoute |
From a route parameter |
ResourceKeyFromHeader |
From a header |
ResourceKeyFromQuery |
From a query parameter |
ResourceKeyFromClaim |
From a token claim |
ResourceKeyFromBody |
From the body. Nesting supported with dots |
ResourceKeyProviderType |
Custom provider, explained below |
Tenant
The tenant can be specified with the DefaultTenant
property in PermitOptions
.
For more granular control, the same options as resource instances are available:
Property | Description |
---|---|
Tenant |
Static value |
TenantFromRoute |
From a route parameter |
TenantFromHeader |
From a header |
TenantFromQuery |
From a query parameter |
TenantFromClaim |
From a token claim |
TenantFromBody |
From the body. Nesting supported with dots |
TenantProviderType |
Custom provider, explained below |
Permit providers
Providers are classes that can extract specific information from the request.
There are three types of providers for specific use cases
IPermitValueProvider
: Extract a single value- Used for resource instance key
- Used for tenant
ResourceKeyProviderType = typeof(MyCustomValueProvider) TenantProviderType = typeof(MyCustomValueProvider)
IPermitValuesProvider
: Extract a dictionary- Used for attributes
- Used for context
AttributesProviderType = typeof(MyCustomValuesProvider) ContextProviderType = typeof(MyCustomValuesProvider)
IPermitUserKeyProvider
: Extract the user key
Example
public class FakeUserKeyProvider: IPermitUserKeyProvider
{
public Task<UserKey> GetUserKeyAsync(HttpContext httpContext)
{
return Task.FromResult(new UserKey("net@permit.io"));
}
}
Global providers
To apply these providers for each request, there is a second argument in the AddPermit
method:
builder.Services.AddPermit(builder.Configuration, options =>
{
conf.GlobalUserKeyProviderType = typeof(FakeUserKeyProvider);
});
// Or directly
var permitOptions = new PermitOptions
{
GlobalUserKeyProviderType = typeof(FakeUserKeyProvider);
}
builder.Services.AddPermit(permitOptions);
Dependency injection
Providers support DI out the box, just register the class in the DI container:
// Provider
public class RegionsContextProvider : IPermitValuesProvider
{
private readonly IRegionsProvider _regionsProvider;
public RegionsContextProvider(IRegionsProvider regionsProvider)
{
_regionsProvider = regionsProvider;
}
public Task<Dictionary<string, object>> GetValues(HttpContext httpContext)
{
return _regionsProvider.GetRegionsAsync();
}
}
// Registration
builder.Services.AddSingleton<IRegionsProvider, RegionsProvider>();
builder.Services.AddScoped<RegionsContextProvider>();
Custom attributes
The Permit
attribute is not mandatory, you can create your own:
// Custom attribute
public class ProtectArticleAttribute : PermitAttribute
{
public ProtectArticleAttribute(string action)
: base(action, "article",
ResourceKeyFromRoute = "id",
TenantFromHeader = "X-Org-Id") { }
}
// Usage
[HttpGet("articles/{id}")]
[ProtectArticle("read")]
public Article GetArticle([FromRoute] string id)
{
...
}
[HttpPost("articles/{id}")]
[ProtectArticle("write")]
public Article UpdateArticle([FromRoute] string id, [FromBody] Article article)
{
...
}
Call the PDP
If you need to call the PDP, you can inject the PdpService
, which is a wrapper around the HttpClient
created by NSwag
.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.