ASP.NET Core - Autorização - I
 Hoje vamos lembrar os principais conceitos sobre a Autorização em aplicações ASP.NET Core.


A autorização na ASP.NET Core determina se um usuário pode acessar uma determinada rota, controlador, ação do controlador, recurso, etc, e , nesta série de artigos vamos abordando os fundamentos da autorização, como ela funciona e como usá-la no ASP.NET Core.
 


 


 

A autorização é o processo, que determina o que o usuário pode ou não fazer. É diferente da Autenticação, que determina quem é o usuário.

 

A autenticação sempre vem em primeiro lugar, antes da autorização, ou seja, você está autorizado somente se estiver autenticado.

Dessa forma a autorização depende da autenticação para identificar o usuário.

 

Na ASP.NET Core, adicionamos o pipeline Authentication ao Middleware usando o método UseAuthentication no arquivo Startup ou no arquivo Program:
 

...

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();


app.UseEndpoints(endpoints =>
{
     endpoints.MapRazorPages();
});
...
 

 

Geralmente adicionamos depois do UseRouting, para que o middleware de autenticação saiba sobre a URL que está sendo acessada pelo usuário.

A finalidade do middleware de autenticação é atualizar a propriedade HttpContext.User com as informações sobre o usuário obtida de ClaimsPrincipal.

 

A classe ClaimsPrincipal contém as declarações dos usuários e expõe uma coleção de identidades cada uma das quais e um tipo ClaimsIdentity, e, em geral esta coleção, que é acessada através da propriedade Identities, terá apenas um único elemento.  Assim um usuário é do tipo ClaimPrincipal e é composto por um ClaimsIdentity.


Nota:
ClaimsIdentity armazena informação sobre o usuário como o status de autenticação e as claims.

 

Todo o middleware, que precisa saber quem é o usuário (por exemplo, middleware de autorização) deve vir após o UseAuthentication.

 

O middleware de autorização lê o ClaimsPrincipal de HttpContext.User e o usa para verificar se o usuário está autorizado.

 

Estratégias de autorização

Podemos usar os serviços de autorização de várias maneiras para construir um sistema de autorização robusto. Vejamos a seguir os principais :

Autorização declarativa

Nesse modo, usamos o atributo Authorize para proteger uma página. O atributo Authorize descreve como a página precisa ser protegida e o middleware de autorização lerá o atributo e descobrirá como proteger a página.

Você pode configurar a Autorização Declarativa usando as seguintes formas :

  1. Autorização Simples

  2. Autorização baseada em claims (declarações)

  3. Autorização baseada em role (perfil/função)

  4. Autorização baseada em Policy (política)

1. Autorização Simples

Na Autorização Simples, aplicamos o atributo [Authorize] a um controlador, método Action ou Razor Page. Isso impedirá que os usuários não autenticados acessem a página.

 

[Authorize]
public class HomeController : Controller
{
    public ActionResult Login()
    {
    }
 
   public ActionResult Logout()
    {
    }
}

 

Autorização baseada em Claims (declarações)

Em uma estratégia de Autorização baseada em Claims, criamos uma Política de Autorização e a mapeamos para uma claim ou declaração (claims ou declarações) no método ConfigureServices da classe Startup ou na classe Program :
 

services.AddAuthorization(options =>
{
     options.AddPolicy("AdminOnly", policy => policy.RequireClaim("Admin"));
});
builder.Services.AddAuthorization(options =>
{
     options.AddPolicy("AdminOnly", policy => policy.RequireClaim("Admin"));
});

Nota: Uma Claim é uma declaração que uma entidade (um usuário ou outro aplicativo) faz sobre si mesma, é apenas uma declaração. Por exemplo, uma lista de claims pode ter o nome do usuário, o e-mail do usuário, a idade do usuário, a autorização do usuário para uma ação. Na segurança baseada em role ou função, um usuário apresenta as credenciais diretamente ao aplicativo.

Aplicamos a política a um controlador, Action ou Razor Page usando o atributo Authorize. Isso não apenas interromperá os usuários não autenticados, mas também os usuários autenticados se eles não carregarem a declaração Admin.

[Authorize(Policy = "AdminOnly")]
public class AdminController: Controller
{
   public ActionResult Login()
   {... }

   public ActionResult Logout()
   {...}
}


Observe que as Claims não podem ser usadas diretamente usando o atributo Authorize. Você precisa criar uma política para usá-las.


Autorização baseada em Role (função/perfil)

A autorização baseada em função é muito semelhante à autorização baseada em claims, exceto que usa as roles ou perfis em vez de claims ou declarações.

Outra diferença é que você pode usar as Roles diretamente usando o atributo Authorize.
 

[Authorize(Roles = "Admin")]
public class AdminController : Controller
{
}


Você também pode criar uma política usando o RequireRole na classe de inicialização. e usar a política em vez de Roles no Controlador :

 

builder.Services.AddAuthorization(options =>
{
      options.AddPolicy("AdminPolicy",
      policy => policy.RequireRole("Admin"));
});
[Authorize(Policy = "Admin")]
public class AdminController: Controlador
{
}
 


A autorização baseada em role existe devido à compatibilidade com versões anteriores. É melhor evitar usá-la, pois pode ser preterido em um futuro próximo.

 

Autorização baseada em Policy (política)

As autorizações baseadas em claims e as baseadas em roles usam a definição de uma Política nos bastidores. Mas se nos depararmos com situações complexas, precisamos criar um esquema de autorização personalizado baseado em políticas.

Os blocos de construção da autorização baseada na política são:  a política, o requisito e o manipulador de requisitos.

Autorização baseada em recursos usando políticas

O middleware Authorization, que usa o atributo Authorize para verificar as permissões, o executa muito antes da execução do manipulador de página ou do método Action. Portanto, ele não tem acesso aos dados ou recursos nos quais a página ou o método Action opera.

Por exemplo, pegue um documento que tenha um autor. Somente o Autor pode editar o documento. Os outros usuários só podem visualizar o documento. Para implementar a segurança acima, precisamos recuperar o documento do servidor, verificar seu autor e decidir se permite a edição ou não. A autorização declarativa com o atributo Authorize não pode lidar com essa situação.

Assim, escrevemos o código para validar o direito do usuário no próprio método, injetando o serviço de Autorização na página/controlador. Em seguida, usamos o método AuthorizeAsync para acionar manualmente uma autorização.

 

Funciona assim:

1- O UseRouting resolve as solicitações HTTP recebidas e constrói um Endpoint;
2- O middleware de autenticação constrói a ClaimsPrincipal dos cookies ou do token JWT e atualiza o HttpContext.User;
3- O request chega ao middleware de autorização. Verifica se permite o acesso ao URL para o usuário;
4- Se a autorização for bem-sucedida, o request prosseguirá normalmente para o middleware do endpoint e concluirá;
5- Se a autorização falhar, o middleware retornará um erro;

Se a autorização falhar, existe duas possibilidades : Ou o usuário não está autenticado ou está autenticado, mas não autorizado.


1. O usuário não está autenticado

Se o usuário não for autenticado, o middleware de autorização invoca o ChallengeResult no manipulador de autenticação.

Em um aplicativo Web, o manipulador redirecionará o usuário para a página de login. Em um aplicativo de API, ele retorna uma resposta de erro 401 não autorizado.

2. O usuário não está autorizado

Se o usuário for autenticado, mas não autorizado, o middleware de autorização invocará o ForbidResult no manipulador de autenticação.

Em um aplicativo Web, o manipulador redirecionará o usuário para a página da Web Acesso negado. Em um aplicativo API, ele retorna uma resposta de erro 403 Forbidden


E estamos conversados... 

 

"E é evidente que pela lei ninguém será justificado diante de Deus, porque o justo viverá pela fé."
Gálatas 3:11

Referências:


José Carlos Macoratti