{"id":17078517,"url":"https://github.com/dazinator/dazinator.aspnetcore.authorization","last_synced_at":"2026-01-18T11:42:31.773Z","repository":{"id":56532691,"uuid":"224854070","full_name":"dazinator/Dazinator.AspNetCore.Authorization","owner":"dazinator","description":"Useful classes and extensions when working with Microsoft.Extensions.Authorization","archived":false,"fork":false,"pushed_at":"2020-11-02T07:20:25.000Z","size":69,"stargazers_count":1,"open_issues_count":6,"forks_count":1,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2024-04-13T21:44:35.563Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dazinator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-29T12:54:04.000Z","updated_at":"2020-10-30T21:58:16.000Z","dependencies_parsed_at":"2022-08-15T20:30:57.041Z","dependency_job_id":null,"html_url":"https://github.com/dazinator/Dazinator.AspNetCore.Authorization","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.AspNetCore.Authorization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.AspNetCore.Authorization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.AspNetCore.Authorization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.AspNetCore.Authorization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dazinator","download_url":"https://codeload.github.com/dazinator/Dazinator.AspNetCore.Authorization/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247415966,"owners_count":20935387,"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":"2024-10-14T12:22:27.649Z","updated_at":"2026-01-18T11:42:31.716Z","avatar_url":"https://github.com/dazinator.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://dev.azure.com/darrelltunnell/Public%20Projects/_apis/build/status/dazinator.Dazinator.AspNetCore.Authorization?branchName=master)](https://dev.azure.com/darrelltunnell/Public%20Projects/_build/latest?definitionId=10\u0026branchName=master)\n\n## Features\n\n\n### Composite Authorization Policy Provider\nAllows you to build a composite `AuthorizationPolicyProvider` for your ASP.NET Core application.\nThis basically allows you to consolidate multiple `IAuthorizationPolicyProvider`s into a single one,\nwhich will loop through the inner providers in order, to query each one to obtain the policy. \nIf a NULL policy is returned by a provider, it will proceed to query the next provider in the list, until either the policy is returned, or the last NULL is returned.\n\n\nUsage in `startup.cs`:\n\n```csharp\n\n            services.AddCompositeAuthorizationPolicyProvider((builder) =\u003e\n            {\n                builder.AddProvider\u003cPermissionPolicyProvider\u003e((a) =\u003e a.AsSingleton())\n                       .AddProvider\u003cTestPolicyProvider\u003e((s) =\u003e\n                       {\n                           s.AsSingleton((sp) =\u003e new TestPolicyProvider(\"Bar\"));\n                       })\n\t\t\t\t\t   .AddProvider\u003cDefaultAuthorizationPolicyProvider\u003e((a) =\u003e a.AsSingleton()); // Asp.net default provider.\n            });\n    ```\n\nSee the tests for more information regarding usage.\n\n## MemoryCaching AuthorizationPolicyProvider\n\nAllows you to decorate an `IAuthorizationPolicyProvider` provider with a Memory Caching one, along with configuring cache expiration for policies.\nSee tests and README in the Caching project for more info.\n\nUsage:\n\n```csharp\n\n            services.AddCompositeAuthorizationPolicyProvider((builder) =\u003e\n            {\n                builder.AddProvider\u003cTestPolicyProvider\u003e((a) =\u003e\n                {\n                    a.AsSingleton((sp) =\u003e new TestPolicyProvider()) // custom factory method\n                     .AddCaching((cacheOptions) =\u003e\n                     {\n                         cacheOptions.SetMemoryCacheFactory(sp =\u003e new MemoryCache(new MemoryCacheOptions\n                         {\n                             SizeLimit = 1024\n                         })).SetConfigureCacheEntry((policyName, entry) =\u003e\n                         {\n                             entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);\n                         });\n                     });\n                })\n                .AddProvider\u003cDefaultAuthorizationPolicyProvider\u003e((a) =\u003e a.AsSingleton());  // add more providers to composite.             \n\n            });   \n```\n\n## Note to Provider Authors\n\nAre you writing a custom AuthorizationPolicyProvider that others might user?\nI would recommend adhering to the following pattern so that your provider will behave well as either part of a composite provider,\nor just registered on it's own but with a specific desired fallback provider:\n\n\n```csharp\n\n    public class CustomAuthorizationPolicyProvider : IAuthorizationPolicyProvider\n    {\n        public const string PolicyPrefix = \"Custom:\";\n        private readonly IAuthorizationPolicyProvider _innerProvider;\n        private readonly Task\u003cAuthorizationPolicy\u003e NullResult = Task.FromResult(default(AuthorizationPolicy));\n\n        public PermissionsAuthorizationPolicyProvider(IAuthorizationPolicyProvider innerProvider = null)\n        {\n            _innerProvider = innerProvider;\n        }\n\n        public Task\u003cAuthorizationPolicy\u003e GetDefaultPolicyAsync()\n        {\n            if (_innerProvider == null)\n            {\n                return NullResult;\n            }\n            return _innerProvider?.GetDefaultPolicyAsync();\n        }\n\n#if NETCOREAPP3_0\n        public Task\u003cAuthorizationPolicy\u003e GetFallbackPolicyAsync()\n        {\n            if (_innerProvider == null)\n            {\n                return NullResult;\n            }\n            return _innerProvider?.GetFallbackPolicyAsync();\n        }\n#endif\n\n        public Task\u003cAuthorizationPolicy\u003e GetPolicyAsync(string policyName)\n        {\n            if (!policyName.StartsWith(PolicyPrefix, StringComparison.OrdinalIgnoreCase))\n            {\n                if (_innerProvider == null)\n                {\n                    return NullResult;\n                }\n                return _innerProvider?.GetPolicyAsync(policyName);\n            }\n\n            // TODO: Build policy but also think about caching!\n            // var policy = new AuthorizationPolicyBuilder()\n            //     .RequireClaim(CustomClaimTypes.Foo, permissionClaimValues)\n            //     .Build();\n\n            return Task.FromResult(policy);\n        }\n    } \n\n\n```\n\nBy sticking to this pattern, consumers of your provider will have the most flexibility. They can either register it with any provider they'd like as the fallback, for example the Default provider:\n\n\n```csharp\n\n   services.AddSingleton\u003cIAuthorizationPolicyProvider, CustomAuthorizationPolicyProvider\u003e(sp=\u003e {\n                return new CustomAuthorizationPolicyProvider(new DefaultAuthorizationPolicyProvider(sp.GetRequiredService\u003cIOptions\u003cAuthorizationOptions\u003e\u003e()));\n            });\n\n```\n\nOr they can use it as part of a `CompositePolicyProvider` (as provided in this repository) and shown in above in this readme. \nIn either situation, your provider should work.\n\nAs a bonus, here is an example of the extension method you might ship with your custom provider, so consumers can add it directly and specify it's inner provider, when not wishing to add it using the composite pattern provided by this repo:\n\n```csharp\n\n    public static class ServiceCollectionExtensions\n    {\n        public static IServiceCollection AddMyCustomAuthorisationPolicyProvider(this IServiceCollection services, Func\u003cIServiceProvider, IAuthorizationPolicyProvider\u003e innerProviderFactory = null)\n        {\n            services.AddSingleton\u003cIAuthorizationPolicyProvider, PermissionsAuthorizationPolicyProvider\u003e(sp =\u003e\n            {\n                return new PermissionsAuthorizationPolicyProvider(innerProviderFactory?.Invoke(sp));\n            });\n           \n            return services;\n        }\n    }\n    \n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdazinator%2Fdazinator.aspnetcore.authorization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdazinator%2Fdazinator.aspnetcore.authorization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdazinator%2Fdazinator.aspnetcore.authorization/lists"}