Policy-based authorization article overhaul#37231
Conversation
There was a problem hiding this comment.
Pull request overview
This PR modernizes and restructures the policy-based authorization documentation by shifting MVC and Razor Pages–specific guidance into their own new articles and refocusing the main article on Blazor-oriented examples, while also updating related cross-references and Entra ID links across the docs set.
Changes:
- Overhauls
security/authorization/policies.mdto use Razor component examples and updated samples (including a new external-service sample section). - Adds new companion articles for MVC and Razor Pages policy-based authorization and wires them into
aspnetcore/toc.yml. - Updates multiple related docs to point to the new anchors/pages and refreshes Microsoft Entra ID links +
ms.datemetadata.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| aspnetcore/toc.yml | Adds TOC entries for the new MVC and Razor Pages policy-based authorization articles. |
| aspnetcore/security/how-to-choose-identity-solution.md | Updates Entra link + ms.date metadata. |
| aspnetcore/security/authorization/resource-based.md | Updates xref fragments and sample namespace/path text to match the new policies doc structure. |
| aspnetcore/security/authorization/policies/samples/stubs/copy_of_IAuthorizationService.cs | Removes copied framework source stub previously used for an include snippet. |
| aspnetcore/security/authorization/policies/includes/policies5.md | Removes pre-6.0 include content that was previously injected into the policies article. |
| aspnetcore/security/authorization/policies.md | Major rewrite: policy concepts + Blazor-focused examples + new external-service sample walkthrough. |
| aspnetcore/security/authorization/iauthorizationpolicyprovider.md | Updates xref fragments + ms.date. |
| aspnetcore/security/authorization/dependencyinjection.md | Updates xref fragments + ms.date. |
| aspnetcore/security/authorization/customizingauthorizationmiddlewareresponse.md | Updates ms.date. |
| aspnetcore/security/authorization/custom-authorization-policies-with-iauthorizationrequirementdata.md | Replaces hard-coded user values with placeholders in decoded JWT example. |
| aspnetcore/release-notes/aspnetcore-5.0.md | Updates Entra link + ms.date. |
| aspnetcore/razor-pages/security/authorization/resource-based.md | Updates xref fragment to new policies doc anchor. |
| aspnetcore/razor-pages/security/authorization/policies.md | New Razor Pages–specific policy-based authorization article. |
| aspnetcore/mvc/security/authorization/resource-based.md | Updates xref fragment to new policies doc anchor. |
| aspnetcore/mvc/security/authorization/policies.md | New MVC-specific policy-based authorization article (including MVC handler Resource guidance). |
| aspnetcore/migration/70-to-80.md | Updates xref to point to the new MVC policies article section. |
| aspnetcore/migration/22-to-30.md | Updates xrefs to the new policies anchor/article for handler resource guidance. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…et/AspNetCore.Docs into guardrex/policy-based-authz
|
@tdykstra ... Pinging again for review. |
tdykstra
left a comment
There was a problem hiding this comment.
Looks great!
I'm approving it but be sure to look at all the comments I made before merging it. 😄
| description: Learn how to create and use authorization policy handlers for enforcing authorization requirements in an ASP.NET Core MVC app. | ||
| monikerRange: '>= aspnetcore-3.1' | ||
| ms.author: wpickett | ||
| ms.custom: mvc |
There was a problem hiding this comment.
| ms.custom: mvc |
There was a problem hiding this comment.
❓... Should I open an issue to remove "mvc" from ms.custom metadata across all Blazor node articles?
There was a problem hiding this comment.
You can do that; I wouldn't consider it a high priority though.
| ms.date: 07/10/2026 | ||
| uid: security/authorization/authorizationmiddlewareresulthandler | ||
| --- | ||
| # Customize the behavior of `AuthorizationMiddleware` |
There was a problem hiding this comment.
| # Customize the behavior of `AuthorizationMiddleware` | |
| # Customize the behavior of authorization middleware |
| * Creating requirements. | ||
| * Registering and applying policies. |
There was a problem hiding this comment.
To avoid gerunds:
| * Creating requirements. | |
| * Registering and applying policies. | |
| * How to create requirements. | |
| * How to register and apply policies. |
| In practice, a policy is applied with `[Authorize(Policy = "...")]` (Razor components, pages, and controllers) or `RequireAuthorization(...)` (endpoints), and the framework uses handlers to evaluate the requirements behind a policy. <xref:Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider> (<xref:security/authorization/iauthorizationpolicyprovider> documentation) generates policies dynamically instead of registering them at app startup. | ||
|
|
||
| In the preceding example, an "AtLeast21" policy is created. It has a single requirement—that of a minimum age, which is supplied as a parameter to the requirement. | ||
| [Role-based authorization](xref:security/authorization/roles) and [claim-based authorization](xref:security/authorization/claims) use a requirement, a requirement handler, and a preconfigured authorization policy. These building blocks support the expression of authorization evaluations in code. |
There was a problem hiding this comment.
| [Role-based authorization](xref:security/authorization/roles) and [claim-based authorization](xref:security/authorization/claims) use a requirement, a requirement handler, and a preconfigured authorization policy. These building blocks support the expression of authorization evaluations in code. | |
| [Role-based authorization](xref:security/authorization/roles) and [claims-based authorization](xref:security/authorization/claims) use a requirement, a requirement handler, and a preconfigured authorization policy. These building blocks support the expression of authorization evaluations in code. |
| [Role-based authorization](xref:security/authorization/roles) and [claim-based authorization](xref:security/authorization/claims) use a requirement, a requirement handler, and a preconfigured authorization policy. These building blocks support the expression of authorization evaluations in code. | ||
|
|
||
| ## IAuthorizationService | ||
| This article uses Razor component examples and focuses on [Blazor](xref:blazor/index) authorization scenarios for ASP.NET Core 3.1 or later. For Razor Pages and MVC guidance, which apply to all releases of ASP.NET Core, see the following resources after reading this article: |
There was a problem hiding this comment.
| This article uses Razor component examples and focuses on [Blazor](xref:blazor/index) authorization scenarios for ASP.NET Core 3.1 or later. For Razor Pages and MVC guidance, which apply to all releases of ASP.NET Core, see the following resources after reading this article: | |
| This article uses Razor component examples and focuses on [Blazor](xref:blazor/index) authorization scenarios for ASP.NET Core 3.1 or later. For Razor Pages and MVC guidance that applies to all releases of ASP.NET Core, see the following resources after reading this article: |
| policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything"))); | ||
| :::moniker range=">= aspnetcore-7.0" | ||
|
|
||
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy%2A?displayProperty=nameWithType> in the app's `Program` file. In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: |
There was a problem hiding this comment.
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy%2A?displayProperty=nameWithType> in the app's `Program` file. In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: | |
| A policy is registered as part of the authorization service configuration in the app's `Program` file, by calling <xref:Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy%2A?displayProperty=nameWithType>. The following example creates an `AtLeast21` policy with a single requirement of a minimum age, and it sets the minimum age to 21 years old. |
| :::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0" | ||
|
|
||
| <a name="apply-policies-to-mvc-controllers"></a> | ||
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.AddPolicy%2A?displayProperty=nameWithType> in the app's `Program` file. In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: |
There was a problem hiding this comment.
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.AddPolicy%2A?displayProperty=nameWithType> in the app's `Program` file. In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: | |
| A policy is registered as part of the authorization service configuration in the app's `Program` file, by calling <xref:Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy%2A?displayProperty=nameWithType>. The following example creates an `AtLeast21` policy with a single requirement of a minimum age, and it sets the minimum age to 21 years old: |
| :::moniker range="< aspnetcore-6.0" | ||
|
|
||
| :::code language="csharp" source="~/security/authorization/policies/samples/6.0/AuthorizationPoliciesSample/Controllers/AtLeast21Controller.cs" id="snippet" highlight="1"::: | ||
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.AddPolicy%2A?displayProperty=nameWithType> in `Startup.ConfigureServices` (`Startup.cs`). In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: |
There was a problem hiding this comment.
| A policy is registered as part of the authorization service configuration with <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.AddPolicy%2A?displayProperty=nameWithType> in `Startup.ConfigureServices` (`Startup.cs`). In the following example, the `AtLeast21` policy is created with a single requirement of a minimum age (`MinimumAgeRequirement`) and setting the minimum age to 21 years old: | |
| A policy is registered as part of the authorization service configuration in `Startup.ConfigureServices` (`Startup.cs`), by calling <xref:Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy%2A?displayProperty=nameWithType>. The following example creates an `AtLeast21` policy with a single requirement of a minimum age, and it sets the minimum age to 21 years old: |
|
|
||
| ### Configure the sample | ||
|
|
||
| The following demonstration relies on using the [NSwag (Swagger/OpenAPI)](https://github.com/RicoSuter/NSwag) or [cURL](https://curl.se/) in a command shell. |
There was a problem hiding this comment.
| The following demonstration relies on using the [NSwag (Swagger/OpenAPI)](https://github.com/RicoSuter/NSwag) or [cURL](https://curl.se/) in a command shell. | |
| The following demonstration relies on using [NSwag (Swagger/OpenAPI)](https://github.com/RicoSuter/NSwag) or [cURL](https://curl.se/) in a command shell. |
| ``` | ||
|
|
||
| * Open the [ContosoAPI.collection.json](https://github.com/dotnet/AspNetCore.Docs.Samples/blob/main/samples/aspnetcore-authz-with-ext-authz-service/ContosoAPI.collection.json) file and configure an environment with the following: | ||
| You can add breakpoints in the `Contoso.Security.API.SecurityPolicyController` and observe the passed client ID (`appid`) is used to assert whether it is allowed to obtain weather data. |
There was a problem hiding this comment.
| You can add breakpoints in the `Contoso.Security.API.SecurityPolicyController` and observe the passed client ID (`appid`) is used to assert whether it is allowed to obtain weather data. | |
| You can add breakpoints in the `Contoso.Security.API.SecurityPolicyController` and see that the passed client ID (`appid`) is used to assert whether it is allowed to obtain weather data. |
|
Thanks, @tdykstra! ... I'll address of your feedback shortly. I just had one question on removing "mvc" from the Blazor articles' metadata. Should I open an issue to do it everywhere, either only across the Blazor node or everywhere across the doc set? |
I addressed this in a comment earlier - I would consider it a very low priority, but it's something that you can do to make things more consistent. I would apply it across the doc set, not just Blazor. |
Fixes #35817
Tom ... I worked quite long time on this one, longer than usual. The current article (live link) seems like it has a lot of problems to address.
Notes
Internal previews
Toggle expand/collapse