ASP .NET Core 3.1 - Usando o Identity de cabo a rabo - XXVI


Hoje vamos concluir a série de artigos mostrando como usar o ASP .NET Core Identiy na versão 3.1 da ASP .NET .Core e do EF Core.

Continuando a vigésima quinta parte do artigo vamos fazer algumas considerações sobre a autorização baseada em roles e a autorização baseada em claims.

Autorização baseada em roles e/ou em claims

A autorização é processo de determinar o que o usuário logado pode e não pode fazer, e,  baseado nos requerimentos de autorização da nossa aplicação podemos definir a autorização usando Roles ou Claims ou uma combinação dos dois.

Veremos a seguir um resumo das principais características deste dois tipos de autorização,

Autorização baseada em Roles ou Roled Based Access Control

Imagine que em uma empresa existam os seguintes perfis ou roles definidos:

  1. Admin
  2. Gerente
  3. Funcionario

Dependendo da role ou  das roles as quais um usuário autenticado pertença, você pode ou não autorizar o acesso a determinados recursos na sua aplicação.

Desde que estamos usando Roles para fazer a verificação da autorização este processo é chamado Autorização baseada em Roles ou Role Based Authorization.

Para implementar este tipo de autorização na ASP .NET Core usamos o atributo Authorize com o parâmetro Roles:

 [Authorize(Roles = "Admin")]
 public class AdministrationController : Controller
 {
    //...
 }

Podemos especificar mais de uma role na definição do parâmetro Roles separando-as por vírgula :

 [Authorize(Roles = "Admin, Gerente")]
 public class AdministrationController : Controller
 {
    //...
 }

No exemplo acima, para acessar o controlador o usuário terá que pertencer ás roles Admin e Gerente.

Podemos também definir a autorização via Roles a nível de métodos Action usando também o atributo AllowAnonymous:

 [Authorize(Roles = "Admin, Gerente")]
 public class AdministrationController : Controller
 {
  
  public ActionResult Metodo1()
     {
     }

     [Authorize(Roles = "Admin")]
      public ActionResult Metodo2()
     {
     }

      [AllowAnonymous]
      public ActionResult Liberado()
      {
      }
 }

Neste exemplo os membros da role Admin ou da role Gerente podem acessar o controlador e o método Action Metodo1, mas somente os membros da role Admin pode acessar o método Action Metodo2.

O método Action Liberado pode ser acessado por qualquer usuário não autenticado pois esta decorado com o atributo AllowAnonymous.

Embora a autorização baseada em roles seja fácil de implementar na ASP.NET Core, ela tem um escopo limitado. Como exemplo, imagine que você precisa validar um usuário com base na data de ingresso ou no ID do departamento. Você não pode ter roles para cada uma dessas variações - isso não é uma boa solução.

Aqui é onde você pode tirar proveito da autorização baseada em claims - podendo validar a identidade de um usuário com base nas declarações ou claims atribuídas a ele.

Autorização baseada em Claims ou Claims Based Access Control

Antes de detalhar a autorização baseada em claims vamos revisar o conceito de Claim.

O que é uma Claim ?

Uma claim é uma informação sobre o usuário que é representada por um par nome-valor. Não é uma declaração do que o usuário pode e não pode fazer, é apenas uma declaração, como por exemplo, o nome de usuário, o email, a idade, o sexo, etc,.

Assim, essas declarações podem ser usadas para verificar a autorização do usuário em sua aplicação com base nos requisitos de negócios e autorização do aplicativo.

Por exemplo, se você estiver criando um portal para funcionários, poderá permitir que o usuário conectado solicite uma licença de maternidade se o valor da claim de gênero for feminino. Da mesma forma, se você estiver criando um aplicativo de comércio eletrônico, poderá permitir que o usuário conectado envie um pedido se o valor da claim de idade for maior ou igual a 18.

Como já escrevi, as claims são baseadas em políticas, e, criamos uma política e incluímos uma ou mais reivindicações nessa política. A política é então usada junto com o parâmetro policy do atributo Authorize para implementar a autorização baseada em declarações.

A sintaxe usada é a seguinte:

 [Authorize(Policy = "DeleteRolePolicy")]
 public async Task<IActionResult> DeleteRole(string id)
 {
    //...
 }

Dessa forma podemos entender que na ASP .NET Core uma role é apenas uma claim com o tipo Role.

Como já vimos que as claims são baseadas em políticas, e, desde que uma role é também uma claim do tipo role, podemos usar uma role com a sintaxe policy.

Usando claims nós criamos uma política e incluímos uma ou mais claims neste política, e, podemos fazer a mesma coisa com as roles também, criando uma política e incluindo uma ou mais roles nesta política.

Podemos fazer isso no método ConfigureServices:

  public void ConfigureServices(IServiceCollection services)
  {
       services.AddAuthorization(options =>
       {
           options.AddPolicy("AdminRolePolicy", policy => policy.RequireRole("Admin"));
        });
   } 

E se você quiser incluir mais de uma role na política basta separá-las por vírgulas:

  public void ConfigureServices(IServiceCollection services)
  {
       services.AddAuthorization(options =>
       {
           options.AddPolicy("AdminRolePolicy", policy => 
                                          policy.RequireRole("Admin","Gerente","Funcionario"));
        });
   } 

De forma alternativa podemos também criar uma política usando a classe AuthorizationPolicyBuilder, onde você pode especificar os nomes das roles usando o método RequireRole :

  ...
   var policy = new AuthorizationPolicyBuilder()
                            .RequireAuthenticatedUser()
                            .RequireRole("Admin")
                            .Build();

Após isso a política pode ser usada no controlador ou no método Action:

1- Controller

   [Authorize(Policy = "RequireAdminOnly")]
   public class SecurityController: Controller
   {
       //Métodos Action
   }

2 - Método Action

  [HttpPost]
  [Authorize(Policy = "SuperAdminPolicy")]
   public async Task<IActionResult> DeleteRole(string id)   
   {
        // Deleta Role
   } 

Você também pode aplicar várias políticas a um controlador ou a um método Action :

[Authorize(Policy = "Funcionario")]
public class SecurityController : Controller
{
    [Authorize(Policy = "Admin")]
    public ActionResult DeleteUser()
    {
        //código
    }
}

No exemplo de código acima, você pode ver duas políticas aplicadas - uma no nível do controlador e a outra no nível de método Action.

O método Action pode ser executado apenas por usuários que satisfazem ambas as políticas, a saber 'Funcionario' e 'Admin',  ou seja, para chamar o método DeleteUser, a autorização do usuário deverá deve cumprir as duas políticas definidas.

Conclusão

Nas versões anteriores da ASP .NET, não existia a Autorização Baseada em Claims, existia apenas a Autorização Baseada em Role.

A Autorização Baseada em Claims é relativamente nova e é a abordagem recomendada a ser usada. Com isso, também podemos usar claims ou declarações de provedores de identidade externos como Facebook, Google, Twitter etc.

A Autorização Baseada em Role ainda é suportada na ASP .NET Core para compatibilidade com versões anteriores. Embora a autorização baseada em claims seja a abordagem recomendada, dependendo dos requisitos de autorização do aplicativo, você pode usar autorização baseada em role, a autorização baseada em claims ou uma combinação de ambas.

Concluímos assim essa série de 26 artigos mostrando como gerenciar users, roles e outros recursos do Identity.

(Porque a vida foi manifestada, e nós a vimos, e testificamos dela, e vos anunciamos a vida eterna, que estava com o Pai, e nos foi manifestada);
1 João 1:2

Referências:


José Carlos Macoratti