Transformação de Claims

Ao autenticar um usuário, nós podemos além de armazenar no token o seu nome, algumas outras propriedades que o descrevem, tais como: e-mail, papéis (roles), etc. Com isso, nós teremos diversas outras características dele além de apenas o nome e os papéis que ele possui dentro da aplicação.

Como sabemos, essas informações são expressadas através de claims. Ao autenticar, nós podemos criar uma coleção de claims contendo todas as informações sobre o respectivo usuário. Como as claims estão em todo lugar, o ASP.NET fornece um recurso específico que permite a transformação de claims, ou seja, além de utilizar informações que temos do lado do servidor para descrever o usuário, para complementar extraindo dados da requisição e incluir na coleção de claims.

Para customizar o tranformador, devemos implementar a interface IClaimsTransformer, e através do método TransformAsync podemos incrementar mais informações sobre o usuário e mais tarde utiliza-las para autorização de algum recurso específico. No exemplo abaixo, estamos extraindo a cultura (via header Accept-Language) da requisição e incluindo no ClaimsPrincipal gerado:

public class CultureToClaimTransformer : IClaimsTransformer
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
    {
        var principal = context.Principal;

        if (principal.Identity.IsAuthenticated)
        {
            var culture = StringValues.Empty;

            if (context.Context.Request.Headers.TryGetValue(“Accept-Language”, out culture))
                ((ClaimsIdentity)principal.Identity).AddClaim(new Claim(“Culture”, culture.ToString()));
        }

        return Task.FromResult(principal);
    }
}

Só que a classe por si só não funciona. Precisamos incluir a mesma na execução, e para isso, recorremos ao método UseClaimsTransformation para indicar ao runtime do ASP.NET a classe que faz a transformação de claims. Depois do MVC devidamente configurado, estamos utilizando a autenticação baseada em cookies para o exemplo, indicamos a instância da classe CultureToClaimTransformer para a propriedade Transformer.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication();
        services.AddMvc();
    }

    
public void Configure(IApplicationBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            LoginPath = “/Aplicacao/Login”,
            ReturnUrlParameter = “ReturnUrl”,
            AutomaticAuthenticate = true,
            AutomaticChallenge = true
        });

        app.UseClaimsTransformation(
new ClaimsTransformationOptions()
        {
            Transformer = new CultureToClaimTransformer()
        });

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: “default”,
                template: “{controller=Aplicacao}/{action=Index}/{id?}”);
        });
    }
}

Depois de toda a configuração realizada, nós vamos codificar o nosso controller. Ele possui apenas dois métodos: um que exibe informações e o outro que onde de fato realizamos o login. O método que exibe as informações (Index) está decorado com o atributo AuthorizeAttribute, que não permitirá usuários não autenticados acessá-lo. Já o segundo método serve para autenticar o usuário; em uma aplicação real, este método deve receber as informações postadas em um formulário para validar primeiramente se o usuário existe (em uma base de dados, por exemplo), e caso verdadeiro, aí sim devemos proceder com a autenticação.

public class
AplicacaoController : Controller
{
    [Authorize]
    public IActionResult Index()
    {
        return View();
    }

    
public IActionResult Login()
    {
        HttpContext.Authentication.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(
                new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, “Israel Aece”) }, 
                CookieAuthenticationDefaults.AuthenticationScheme))).Wait();

        
return Redirect(Request.Query[“ReturnUrl”]);
    }
}

Por fim, ao rodar a aplicação e exibir a coleção de
claims do usuário logado, nós teremos duas: uma com o nome do usuário e a outra com a cultura que foi passada pelo navegador que o usuário está utilizando para acessar a aplicação: