Simple roles like Admin or User are no longer sufficient for authorization in contemporary ASP.NET Core apps. Context-aware authorization is necessary for enterprise systems, where decisions about access are based on the user’s identity, the customer they belong to, and the business or tenant they work for.
This article demonstrates a production-grade authorization architecture using:
- JWT claims (
UserId,CustomerId,CompanyId) - Attribute-based policies
- Custom authorization handlers
- Strongly typed claim access
- Multi-tenant data isolation
- Testable and reusable design
This approach is ideal for microservices, SaaS platforms, and B2B systems.
1. Context-Aware JWT Design
A secure JWT should carry authorization context, not UI state.
1 2 3 4 5 6 7 | <span class="token punctuation">{</span> <span class="token property">"UserType"</span><span class="token operator">:</span> <span class="token string">"Transporter"</span><span class="token punctuation">,</span> <span class="token property">"UserId"</span><span class="token operator">:</span> <span class="token string">"89"</span><span class="token punctuation">,</span> <span class="token property">"CustomerId"</span><span class="token operator">:</span> <span class="token string">"501"</span><span class="token punctuation">,</span> <span class="token property">"CompanyId"</span><span class="token operator">:</span> <span class="token string">"42"</span><span class="token punctuation">,</span> <span class="token property">"exp"</span><span class="token operator">:</span> <span class="token number">1770228296</span> <span class="token punctuation">}</span> |
Each claim answers a question:
| Claim | Purpose |
|---|---|
| UserId | Who is the caller |
| CustomerId | Which customer scope |
| CompanyId | Which tenant/company |
| UserType | High-level access boundary |
2. JWT Authentication Setup
JWT validation happens locally in every microservice.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | builder<span class="token punctuation">.</span>Services <span class="token punctuation">.</span><span class="token function">AddAuthentication</span><span class="token punctuation">(</span><span class="token string">"Bearer"</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">AddJwtBearer</span><span class="token punctuation">(</span><span class="token string">"Bearer"</span><span class="token punctuation">,</span> options <span class="token operator">=></span> <span class="token punctuation">{</span> options<span class="token punctuation">.</span>TokenValidationParameters <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">TokenValidationParameters</span> <span class="token punctuation">{</span> ValidateIssuer <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">,</span> ValidateAudience <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">,</span> ValidateLifetime <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">,</span> ValidateIssuerSigningKey <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">,</span> IssuerSigningKey <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">SymmetricSecurityKey</span><span class="token punctuation">(</span> Encoding<span class="token punctuation">.</span>UTF8<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span><span class="token string">"StrongSecretKey"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
This removes runtime dependency on the authentication service and improves performance.
3. Authorization Policies (The Rules Engine)
Policies define what must be true for access.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddAuthorization</span><span class="token punctuation">(</span>options <span class="token operator">=></span> <span class="token punctuation">{</span> options<span class="token punctuation">.</span><span class="token function">AddPolicy</span><span class="token punctuation">(</span><span class="token string">"UserOnly"</span><span class="token punctuation">,</span> policy <span class="token operator">=></span> policy<span class="token punctuation">.</span><span class="token function">RequireClaim</span><span class="token punctuation">(</span><span class="token string">"UserId"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> options<span class="token punctuation">.</span><span class="token function">AddPolicy</span><span class="token punctuation">(</span><span class="token string">"UserWithCustomer"</span><span class="token punctuation">,</span> policy <span class="token operator">=></span> policy<span class="token punctuation">.</span><span class="token function">RequireClaim</span><span class="token punctuation">(</span><span class="token string">"CustomerId"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> options<span class="token punctuation">.</span><span class="token function">AddPolicy</span><span class="token punctuation">(</span><span class="token string">"UserWithCompany"</span><span class="token punctuation">,</span> policy <span class="token operator">=></span> policy<span class="token punctuation">.</span><span class="token function">RequireClaim</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> options<span class="token punctuation">.</span><span class="token function">AddPolicy</span><span class="token punctuation">(</span><span class="token string">"UserWithCustomerAndCompany"</span><span class="token punctuation">,</span> policy <span class="token operator">=></span> policy<span class="token punctuation">.</span><span class="token function">RequireClaim</span><span class="token punctuation">(</span><span class="token string">"CustomerId"</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">RequireClaim</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Policies are reusable, composable, and testable.
4. Attribute-Based API Contracts
Attributes expose authorization intent directly on endpoints.
User + Company Attribute
1 2 3 4 5 6 7 8 | <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">AttributeUsage</span><span class="token attribute-arguments"><span class="token punctuation">(</span>AttributeTargets<span class="token punctuation">.</span>Method<span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-sealed">sealed</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">UserWithCompanyAttribute</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AuthorizeAttribute</span></span> <span class="token punctuation">{</span> <span class="token keyword keyword-public">public</span> <span class="token function">UserWithCompanyAttribute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Policy <span class="token operator">=</span> <span class="token string">"UserWithCompany"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
User + Customer + Company Attribute
1 2 3 4 5 6 7 8 | <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">AttributeUsage</span><span class="token attribute-arguments"><span class="token punctuation">(</span>AttributeTargets<span class="token punctuation">.</span>Method<span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-sealed">sealed</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">UserWithCustomerAndCompanyAttribute</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AuthorizeAttribute</span></span> <span class="token punctuation">{</span> <span class="token keyword keyword-public">public</span> <span class="token function">UserWithCustomerAndCompanyAttribute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Policy <span class="token operator">=</span> <span class="token string">"UserWithCustomerAndCompany"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
This keeps controllers declarative and clean.
5. Strongly Typed Claim Access
Avoid repeating FindFirst() everywhere.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-static">static</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">IdentityContext</span> <span class="token punctuation">{</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-static">static</span> <span class="token return-type class-name"><span class="token keyword keyword-int">int</span></span> <span class="token function">UserId</span><span class="token punctuation">(</span><span class="token keyword keyword-this">this</span> <span class="token class-name">ClaimsPrincipal</span> user<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword keyword-int">int</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"UserId"</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-static">static</span> <span class="token return-type class-name"><span class="token keyword keyword-int">int</span><span class="token punctuation">?</span></span> <span class="token function">CustomerId</span><span class="token punctuation">(</span><span class="token keyword keyword-this">this</span> <span class="token class-name">ClaimsPrincipal</span> user<span class="token punctuation">)</span> <span class="token operator">=></span> user<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"CustomerId"</span><span class="token punctuation">)</span> <span class="token keyword keyword-is">is</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token return-type class-name">c <span class="token punctuation">?</span></span> <span class="token keyword keyword-int">int</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>Value<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">;</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-static">static</span> <span class="token return-type class-name"><span class="token keyword keyword-int">int</span><span class="token punctuation">?</span></span> <span class="token function">CompanyId</span><span class="token punctuation">(</span><span class="token keyword keyword-this">this</span> <span class="token class-name">ClaimsPrincipal</span> user<span class="token punctuation">)</span> <span class="token operator">=></span> user<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">)</span> <span class="token keyword keyword-is">is</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token return-type class-name">c <span class="token punctuation">?</span></span> <span class="token keyword keyword-int">int</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>Value<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
This pattern:
- Eliminates null bugs
- Improves readability
- Centralizes parsing logic
6. Custom IAuthorizationHandler (Enterprise Control)
Policies validate presence.
Handlers validate relationships.
Requirement
1 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-sealed">sealed</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">CompanyAccessRequirement</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IAuthorizationRequirement</span></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-sealed">sealed</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">CompanyAccessHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">AuthorizationHandler<span class="token punctuation"><</span>CompanyAccessRequirement<span class="token punctuation">></span></span></span> <span class="token punctuation">{</span> <span class="token keyword keyword-protected">protected</span> <span class="token keyword keyword-override">override</span> <span class="token return-type class-name">Task</span> <span class="token function">HandleRequirementAsync</span><span class="token punctuation">(</span> <span class="token class-name">AuthorizationHandlerContext</span> context<span class="token punctuation">,</span> <span class="token class-name">CompanyAccessRequirement</span> requirement<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> userId <span class="token operator">=</span> context<span class="token punctuation">.</span>User<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"UserId"</span><span class="token punctuation">)</span><span class="token punctuation">?.</span>Value<span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> companyId <span class="token operator">=</span> context<span class="token punctuation">.</span>User<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">)</span><span class="token punctuation">?.</span>Value<span class="token punctuation">;</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword keyword-string">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span><span class="token keyword keyword-string">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>companyId<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> context<span class="token punctuation">.</span><span class="token function">Succeed</span><span class="token punctuation">(</span>requirement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-return">return</span> Task<span class="token punctuation">.</span>CompletedTask<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Registration
1 | builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSingleton</span><span class="token generic class-name"><span class="token punctuation"><</span>IAuthorizationHandler<span class="token punctuation">,</span> CompanyAccessHandler<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
This enables fine-grained, business-aware authorization.
7. Controller Usage (Method-Level Precision)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">ApiController</span></span><span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Route</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"api/orders"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">OrdersController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ControllerBase</span></span> <span class="token punctuation">{</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">HttpGet</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"company"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">UserWithCompany</span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name">IActionResult</span> <span class="token function">GetCompanyOrders</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-return">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword keyword-new">new</span> <span class="token punctuation">{</span> UserId <span class="token operator">=</span> User<span class="token punctuation">.</span><span class="token function">UserId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> CompanyId <span class="token operator">=</span> User<span class="token punctuation">.</span><span class="token function">CompanyId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">HttpPost</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"secure"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">UserWithCustomerAndCompany</span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name">IActionResult</span> <span class="token function">CreateOrder</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-return">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span><span class="token keyword keyword-new">new</span> <span class="token punctuation">{</span> UserId <span class="token operator">=</span> User<span class="token punctuation">.</span><span class="token function">UserId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> CustomerId <span class="token operator">=</span> User<span class="token punctuation">.</span><span class="token function">CustomerId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> CompanyId <span class="token operator">=</span> User<span class="token punctuation">.</span><span class="token function">CompanyId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Controllers remain thin, focused only on application logic.
8. Multi-Tenant Data Isolation (EF Core)
Prevent cross-tenant data leaks using global query filters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">AppDbContext</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">DbContext</span></span> <span class="token punctuation">{</span> <span class="token keyword keyword-private">private</span> <span class="token keyword keyword-readonly">readonly</span> <span class="token class-name">IHttpContextAccessor</span> _http<span class="token punctuation">;</span> <span class="token keyword keyword-public">public</span> <span class="token function">AppDbContext</span><span class="token punctuation">(</span> <span class="token class-name">DbContextOptions</span> options<span class="token punctuation">,</span> <span class="token class-name">IHttpContextAccessor</span> http<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword keyword-base">base</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span> <span class="token punctuation">{</span> _http <span class="token operator">=</span> http<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-protected">protected</span> <span class="token keyword keyword-override">override</span> <span class="token return-type class-name"><span class="token keyword keyword-void">void</span></span> <span class="token function">OnModelCreating</span><span class="token punctuation">(</span><span class="token class-name">ModelBuilder</span> modelBuilder<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> companyId <span class="token operator">=</span> _http<span class="token punctuation">.</span>HttpContext<span class="token punctuation">?</span> <span class="token punctuation">.</span>User<span class="token punctuation">.</span><span class="token function">FindFirst</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">)</span><span class="token punctuation">?.</span>Value<span class="token punctuation">;</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span>companyId <span class="token operator">!=</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> modelBuilder<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Entity</span><span class="token generic class-name"><span class="token punctuation"><</span>Order<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">HasQueryFilter</span><span class="token punctuation">(</span>o <span class="token operator">=></span> o<span class="token punctuation">.</span>CompanyId <span class="token operator">==</span> <span class="token keyword keyword-int">int</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>companyId<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
This guarantees tenant isolation by default.
9. Unit Testing Authorization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-async">async</span> <span class="token return-type class-name">Task</span> <span class="token function">Should_Authorize_When_CompanyId_Exists</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> user <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">ClaimsPrincipal</span><span class="token punctuation">(</span><span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">ClaimsIdentity</span><span class="token punctuation">(</span><span class="token keyword keyword-new">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">Claim</span><span class="token punctuation">(</span><span class="token string">"UserId"</span><span class="token punctuation">,</span> <span class="token string">"1"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">Claim</span><span class="token punctuation">(</span><span class="token string">"CompanyId"</span><span class="token punctuation">,</span> <span class="token string">"42"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"Test"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> requirement <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">CompanyAccessRequirement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> context <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">AuthorizationHandlerContext</span><span class="token punctuation">(</span> <span class="token keyword keyword-new">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> requirement <span class="token punctuation">}</span><span class="token punctuation">,</span> user<span class="token punctuation">,</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> handler <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">CompanyAccessHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-await">await</span> handler<span class="token punctuation">.</span><span class="token function">HandleAsync</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span> Assert<span class="token punctuation">.</span><span class="token function">True</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span>HasSucceeded<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Authorization becomes fully testable.
10. Making It NuGet-Ready
This architecture can be packaged into a shared library:
- Attributes
- Policies
- Handlers
- Claim helpers
Usage becomes:
1 | services<span class="token punctuation">.</span><span class="token function">AddContextAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Perfect for large microservice ecosystems.
Final Architecture Rule
Authentication proves identity
Authorization proves permission
Services enforce business rules
Never mix them.
Conclusion
By combining:
- JWT claims
- Attribute-based authorization
- Custom handlers
- Multi-tenant isolation
You get a secure, scalable, and enterprise-ready authorization system that works across microservices and teams.
This is the pattern used in real-world SaaS and enterprise platforms, not demos.
Recommendation for ASP.NET 10.0 Hosting
A solid base for developing online services and applications is ASP.NET. Before creating an ASP.NET web application, you must be proficient in JavaScript, HTML, CSS, and C#. There are thousands of web hosting providers offering ASP.NET hosting on the market. However, there are relatively few web hosting providers that offer top-notch ASP.NET hosting.
ASP.NET is the best development language in Windows platform, which is released by Microsoft and widely used to build all types of dynamic Web sites and XML Web services. With this article, we’re going to help you to find the best ASP.NET Hosting solution in Europe based on reliability, features, price, performance and technical support. After we reviewed about 30+ ASP.NET hosting providers in Europe, our Best ASP.NET Hosting Award in Europe goes to HostForLIFE.eu, one of the fastest growing private companies and one of the most reliable hosting providers in Europe.
