Navigation
Recherche
|
How to use resource-based authorization in ASP.NET Core
jeudi 23 janvier 2025, 10:00 , par InfoWorld
When implementing authorization in ASP.NET Core, we can adopt a declarative or an imperative approach. In a declarative authorization, you would typically use the [Authorize] attribute to restrict access to the resource. However, there are certain use cases (such as document editing) where declarative authorization using the [Authorize] attribute is not up to the task. For example, you cannot use declarative or attribute-based authorization for document editing, because the evaluation of authorization must occur after the document is retrieved from the data store.
In such use cases, we need to use a custom authorization method, otherwise known as an imperative approach. In this article, we’ll examine how we can implement an imperative approach to authorization using resource-based authorization in ASP.NET Core. Attribute-based authorization vs. resource-based authorization Typically, the built-in authorization middleware of ASP.NET Core reads the [Authorize] attribute you’ve specified on the action methods of your API controllers to see if the requested action can be authorized for the current user. However, there is a caveat here. The authorization middleware is executed before any action method or page handler is executed. As a result, the authorization middleware doesn’t have access to the data on which the requested action method is supposed to run. That said, there are several use cases in which you might want the resources to be loaded first. For example, only a document’s author or creator is authorized to edit or delete it, while other users can only view the document. In this case, we must determine if the logged-in user is the author or the creator of a particular document, and we will need the document to be loaded and available to do this. We cannot handle such use cases using the attribute-based authorization technique. Instead we need to use resource-based authorization. In resource-based authorization, access control policies for specific resources like files, databases, APIs, and even cloud services are attached directly to those resources. This approach identifies who (users, roles, or other services) can perform specific actions on the resource. For example, assume a scenario in which you have a file with sensitive data. If we want only specific users to have access to read the file, then a resource-based policy would need to be defined for the file. You might name this policy “ReadOnly” and use it to provide only read access to specific users. Thus resource-based authorization allows or denies access to particular resources based on specified requirements of those resources, i.e. policies, and the user’s permissions. Unlike role-based or claim-based authorization, which rely on the identity, roles, and claims of the user to grant access, resource-based authorization relies on requirements of the resource. It is implemented using a resource-based handler and a custom requirements class. In the next sections we’ll examine how we can implement resource-based authorization in ASP.NET Core. Let’s start by creating an ASP.NET Core Web API project. Create an ASP.NET Core Web API project in Visual Studio 2022 To create an ASP.NET Core Web API project in Visual Studio 2022, follow the steps outlined below. Launch the Visual Studio 2022 IDE. Click on “Create new project.” In the “Create new project” window, select “ASP.NET Core Web API” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Specify the “Solution name” for the project and optionally check the “Place solution and project in the same directory” check box, depending on your preferences. Click Next. In the “Additional Information” window shown next, select “.NET 9.0 (Standard Term Support)” as the framework version and check the check box that says “Use controllers,” as we’ll be using controllers instead of minimal APIs in this project. Elsewhere in the “Additional Information” window, leave the “Authentication Type” set to “None” (the default) and make sure the check boxes “Enable OpenAPI Support,” “Configure for HTTPS,” and “Enable Docker” remain unchecked. We won’t be using any of those features here. Click Create. We’ll use this ASP.NET Core Web API project to implement resource-based authorization in the sections below. Define the resource In REST (an acronym for Representational State Transfer), a resource is defined as a piece of data that can be accessed using a unique URI (Uniform Resource Identifier). Typically, the resource is described using a model object. In this example, our resource will be an instance of the Article class. In the project we just created, create a new file named Article.cs and write the following code in there to create our resource type. public class Article { public int Id { get; set; } public string Title { get; set; } public string Description { get; set; } internal readonly string Author; } Create a repository for the resource In an ASP.NET Core application a repository is used to provide access to the data store. In this example, we’ll create an article repository that consists of two types — the IArticleRepository interface and the ArticleRepository class that implements this interface. Create an interface named IArticleRepository in a file having the same name with a.cs extension and replace the default generated code with the following code. public interface IArticleRepository { public Article GetArticle(int id); public List GetArticles(); } Next create the ArticleRepository class. The ArticleRepository class implements the methods of the IArticleRepository interface as shown in the code snippet given below. public class ArticleRepository: IArticleRepository { public Article GetArticle(int id) { throw new NotImplementedException(); } public List GetArticles() { throw new NotImplementedException(); } } Register the repository in the Program.cs file You should now register the ArticleRepository class as a service using the following line of code in the Program.cs file. builder.Services.AddScoped(); By registering the article repository with the services collection, you can take advantage of dependency injection to build instances of this repository in the controller class. We will implement that later. Create an authorization handler An authorization handler is used to implement the logic that should be executed to determine if the user has access to a particular resource. In our example, the requirement for access to the resource will be the presence of a policy named EditPolicy. Create a class named ArticleRequirement and enter the following code. public class ArticleRequirement: IAuthorizationRequirement { } Next, create a class named ArticleAuthorizationHandler in a file having the same name with a.cs extension and write the following code in there. public class ArticleAuthorizationHandler: AuthorizationHandler { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorRequirement requirement, Article resource) { if (context.User.Identity?.Name == resource.Author) { context.Succeed(requirement); } return Task.CompletedTask; } } Register the authorization handler in the Program.cs file To register the authorization handler with the dependency injection container, you should include the following line of code in the Program.cs file. builder.Services.AddSingleton(); Define one or more authorization policies In ASP.NET Core, an authorization policy comprises a collection of requirements that the user or the resource must have for the user to be allowed to access the resource. We’ll now define a policy for an action in the controller. Write the following code snippet in the Program.cs file. builder.Services.AddAuthorization(options => { options.AddPolicy('EditPolicy', policy => policy.Requirements.Add(new ArticleRequirement())); }); In the code snippet above, we add a policy named EditPolicy to the shared resource. Whenever a user requests to edit the resource, we check if the policy is present and, if it is, we allow the user to proceed with modifying it. Create the controller In this implementation, we will create the AuthorController class, which represents the API that exposes action methods to access resources. Create a new class named ArticleController in a file with the same name and a.cs extension and replace the default generated code with the following code. [Route('api/[controller]')] [ApiController] public class ArticleController: ControllerBase { private readonly IAuthorizationService _authorizationService; private readonly IArticleRepository _articleRepository; public ArticleController(IAuthorizationService authorizationService, IArticleRepository documentRepository) { _authorizationService = authorizationService; _articleRepository = documentRepository; } } In the preceding code example, note how we have used dependency injection to create instances of type IAuthorizationService and IArticleRepository. The following code listing shows how we can create an action method in the ArticleController class that will allow only authorized users to edit an article. public async Task Edit(int id) { Article document = _articleRepository.GetArticle(id); if (document == null) { return NotFound(document); } var result = await _authorizationService.AuthorizeAsync(User, document, 'EditPolicy'); if (result.Succeeded) { return Ok(document); } return BadRequest('Access denied'); } In the preceding code listing, note how the instance of type IAuthorizationService has been used to validate if the user has access to edit the article. Key takeaways While declarative authorization should be good enough in most use cases, you may need to provide much more fine-grained access to the resources where a user must have the requisite permission to access the resource (view, edit, delete, etc.) before being authorized. In this article, I’ve given you a head start to implementing resource-based authorization in ASP.NET Core. For the sake of brevity, I’ve skipped the implementation of the repository methods and the remaining action methods in the ArticleController controller class. To complete this application, we would need to write the necessary source code to create users, assign roles, validate user credentials, etc.
https://www.infoworld.com/article/3806921/how-to-use-resource-based-authorization-in-asp-net-core.ht
Voir aussi |
56 sources (32 en français)
Date Actuelle
sam. 25 janv. - 05:26 CET
|