{"id":28028381,"url":"https://github.com/permitio/permit-aspnet","last_synced_at":"2025-05-11T07:12:28.362Z","repository":{"id":189830857,"uuid":"681141314","full_name":"permitio/permit-aspnet","owner":"permitio","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-08T10:21:13.000Z","size":107,"stargazers_count":5,"open_issues_count":1,"forks_count":4,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-11T07:12:25.641Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/permitio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-21T11:05:21.000Z","updated_at":"2025-05-08T10:21:17.000Z","dependencies_parsed_at":"2024-03-20T18:43:41.589Z","dependency_job_id":"a00fc701-f091-406f-bb07-db7ce74be43f","html_url":"https://github.com/permitio/permit-aspnet","commit_stats":null,"previous_names":["permitio/permit-aspnet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-aspnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-aspnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-aspnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-aspnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/permitio","download_url":"https://codeload.github.com/permitio/permit-aspnet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253528978,"owners_count":21922637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-11T07:12:27.696Z","updated_at":"2025-05-11T07:12:28.348Z","avatar_url":"https://github.com/permitio.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NOTE: Unoffical SDK / DEPRECATED\nThis SDK was contributed by a Permit.io customer, but is no longer under active development, please use [.Net](https://github.com/permitio/permit-dotnet) SDK instead.\n\n\n# Permit AspNet\n\nEasily protect APIs with Permit.io via attributes!\n\n```csharp\n[HttpGet(\"articles/{id}\")]\n[Permit(\"read\", \"article\")]\npublic Article[] GetArticles()\n{\n    ...\n}\n\n[HttpPost(\"articles/{id}\")]\n[Permit(\"write\", \"article\")]\npublic Article UpdateArticle([FromRoute] string id, [FromBody] Article article)\n{\n    ...\n}\n```\n\n## Getting Started\n\n* Install the package from `NuGet`\n* Configure the middleware:\n   ```json\n  // appsettings.json\n  {\n    ...\n    \"Permit\": {\n      \"ApiKey\": \"\u003cAPI_KEY\u003e\", // Required\n      \"PdpUrl\": \"http://localhost:7760\" // Optional\n      \"DefaultTenant\": \"default\" // Optional\n      \"UseDefaultTenantIfEmpty\": true // Optional \n    }\n  }\n  ```\n  ```csharp  \n  // Program.cs\n  builder.Services.AddPermit(builder.Configuration);\n  \n  // Or directly\n  var permitOptions = new PermitOptions\n  {\n      ApiKey = \"\u003cAPI_KEY\u003e\"\n  };\n  builder.Services.AddPermit(permitOptions);\n  ```\n  \n* Enable the middleware:\n  ```csharp\n  app.UseAuthentication(); // Require by default\n  app.UseAuthorization();\n  \n  // Add this line\n  app.UsePermit();\n\n  app.MapControllers();\n  ```\n* Use the `Permit` attribute to protect controllers or actions:\n  ```csharp\n  [Permit(action: \"read\", resourceType: \"article\")]\n  public Article[] GetArticles()\n  {\n      return new Article[] { ... };\n  }\n  ```\n  \n## How it works\n\nFor each request, the middleware does:\n* Extract the user ID from the *JWT* token claims (overridable)\n  * The following claim types are checked in exact order `Sub`, `NameIdentifier`, `FullyQualifiedId`, `ObjectIdentifier`\n* Extract `action` and `resourceType` from the `Permit` attribute\n  * Multiple attributes are run sequentially. Controller first, then action\n* Use the `HttpClientFactory` to get a `HttpClient` and call the PDP's `/allowed` endpoint \n* If the user is not allowed, a `403` is returned\n* If the user is allowed, the request is processed\n\n## Minimal API\n\nThis library works with the new *Minimal API* introduced in *ASP.NET Core 6* too:\n\n```csharp\napp.MapGetArticles()\n    .WithName(\"GetArticles\")\n    .RequirePermit(\"read\", \"article\");\n```\n\n## Allow multiple actions\n\nIt's also possible to allow multiple actions by separating them with a comma.\n\n\u003e Multiple attributes will act as an AND condition. Comma  separated actions will act as an OR condition.\n\n```csharp\n// Controller\n[HttpGet(\"articles/{id}\")]\n[Permit(\"read,write\", \"article\")]\npublic Article GetArticle([FromRoute] string id)\n{\n    ...\n}\n\n// Minimal API\napp.MapGetArticles()\n    .WithName(\"GetArticles\")\n    .RequirePermit(\"read,write\", \"article\");\n```\n\n## Resource instances\n\nIt's possible to specify a resource instance key in the `Permit` attribute:\n\n```csharp\n[HttpGet(\"articles/{id}\")]\n[Permit(\"read\", \"article\", ResourceKeyFromRoute = \"id\")]\npublic Article GetArticle([FromRoute] string id)\n{\n    ...\n}\n```\n\nThere are many ways to specify the resource instance:\n\n| Property                  | Description                                |\n|---------------------------|--------------------------------------------| \n| `ResourceKey`             | Static value                               |\n| `ResourceKeyFromRoute`    | From a route parameter                     | \n| `ResourceKeyFromHeader`   | From a header                              |\n| `ResourceKeyFromQuery`    | From a query parameter                     |\n| `ResourceKeyFromClaim`    | From a token claim                         |\n| `ResourceKeyFromBody`     | From the body. Nesting supported with dots |\n| `ResourceKeyProviderType` | Custom provider, explained below           |\n\n## Tenant\n\nThe tenant can be specified with the `DefaultTenant` property in `PermitOptions`.\n\nFor more granular control, the same options as resource instances are available:\n\n| Property             | Description                                |\n|----------------------|--------------------------------------------|\n| `Tenant`             | Static value                               |\n| `TenantFromRoute`    | From a route parameter                     |\n| `TenantFromHeader`   | From a header                              |\n| `TenantFromQuery`    | From a query parameter                     |\n| `TenantFromClaim`    | From a token claim                         |\n| `TenantFromBody`     | From the body. Nesting supported with dots |\n| `TenantProviderType` | Custom provider, explained below           |\n\n## Permit providers\n\nProviders are classes that can extract specific information from the request.\n\nThere are three types of providers for specific use cases\n* `IPermitValueProvider`: Extract a single value\n  * Used for *resource instance key*\n  * Used for *tenant*\n    ```csharp\n    ResourceKeyProviderType = typeof(MyCustomValueProvider)\n    TenantProviderType = typeof(MyCustomValueProvider)\n    ```\n* `IPermitValuesProvider`: Extract a dictionary\n  * Used for *attributes*\n  * Used for *context*\n    ```csharp\n    AttributesProviderType = typeof(MyCustomValuesProvider)\n    ContextProviderType = typeof(MyCustomValuesProvider)\n    ```\n* `IPermitUserKeyProvider`: Extract the user key\n\n### Example\n\n```csharp\npublic class FakeUserKeyProvider: IPermitUserKeyProvider\n{\n    public Task\u003cUserKey\u003e GetUserKeyAsync(HttpContext httpContext)\n    {\n        return Task.FromResult(new UserKey(\"net@permit.io\"));\n    }\n}\n```\n\n### Global providers\n\nTo apply these providers for each request, there is a second argument in the `AddPermit` method:\n\n```csharp\nbuilder.Services.AddPermit(builder.Configuration, options =\u003e\n    {\n        conf.GlobalUserKeyProviderType = typeof(FakeUserKeyProvider);\n    });\n\n\n// Or directly\nvar permitOptions = new PermitOptions\n{\n    GlobalUserKeyProviderType = typeof(FakeUserKeyProvider);\n}\nbuilder.Services.AddPermit(permitOptions);\n```\n\n### Dependency injection\n\nProviders support *DI* out the box, just register the class in the *DI* container:\n\n```csharp\n// Provider\npublic class RegionsContextProvider : IPermitValuesProvider\n{\n    private readonly IRegionsProvider _regionsProvider;\n\n    public RegionsContextProvider(IRegionsProvider regionsProvider)\n    {\n        _regionsProvider = regionsProvider;\n    }\n    \n    public Task\u003cDictionary\u003cstring, object\u003e\u003e GetValues(HttpContext httpContext)\n    {\n        return _regionsProvider.GetRegionsAsync();\n    }\n}\n\n// Registration\nbuilder.Services.AddSingleton\u003cIRegionsProvider, RegionsProvider\u003e();\nbuilder.Services.AddScoped\u003cRegionsContextProvider\u003e();\n```\n\n## Custom attributes\n\nThe `Permit` attribute is not mandatory, you can create your own:\n\n```csharp\n// Custom attribute\npublic class ProtectArticleAttribute : PermitAttribute\n{\n    public ProtectArticleAttribute(string action)\n      : base(action, \"article\",\n        ResourceKeyFromRoute = \"id\",\n        TenantFromHeader = \"X-Org-Id\") { }\n}\n\n// Usage\n[HttpGet(\"articles/{id}\")]\n[ProtectArticle(\"read\")]\npublic Article GetArticle([FromRoute] string id)\n{\n    ...\n}\n\n[HttpPost(\"articles/{id}\")]\n[ProtectArticle(\"write\")]\npublic Article UpdateArticle([FromRoute] string id, [FromBody] Article article)\n{\n    ...\n}\n```\n\n## Call the PDP\n\nIf you need to call the *PDP*, you can inject the `PdpService`, which is a wrapper around the `HttpClient` created by `NSwag`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Fpermit-aspnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpermitio%2Fpermit-aspnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Fpermit-aspnet/lists"}