Ofuscando Dados com DataMask

Quando a nossa aplicação lida com dados sigilosos, precisamos nos atentar em como ela armazena isso fisicamente. Se alguém não autorizado tem acesso à base de dados, ele poderá visualizar todos os dados que estão lá. Uma opção que temos é armazenar os dados criptografados, mas nesta situação,  temos que nos preocupar como a chave de criptografia se quisermos reverter o valor para utilizá-lo novamente.

Imagine que o cliente faça uma compra no site, e depois que ele informa o cartão de crédito, queremos armazenar ele para melhor a experiência sua usuário, e assim, na próxima compra, o cartão já estará armazenado, não precisando informar novamente. Por mais que a aplicação não exponha diretamente o número do cartão de crédito em suas páginas/telas, se houver alguma vulnerabilidade, é possível ter acesso à tabela e, consequentemente, ao número de todos os cartões que estiverem lá.

O SQL Server 2016 possui um recurso chamado data mask, que como o próprio nome sugere, permite ofuscar a informação de uma determinada coluna para um determinado login, e por mais que se explore a vulnerabilidade, o SELECT sempre retornará o dado aplicando a mascará que você configurou. No script abaixo, alteramos a coluna CartaoDeCredito para exibir apenas os dois primeiros e os dois últimos números do cartão. Há ainda outras funções predefinidas, que retornam o valor padrão do tipo de dado da coluna, uma que substitui o endereço de e-mail por asteriscos, entre outras.

ALTER TABLE Cliente
    ALTER COLUMN CartaoDeCredito 
        ADD MASKED WITH (FUNCTION = 'partial(2, "**-****-****-**", 2)')
GO

Para o exemplo, criei um login limitado chamado WebUser, concedendo a permissão para realizar SELECT na tabela de clientes. Agora note que abaixo estamos utilizado ADO.NET para extrair o número do cartão de crédito para apresentar na tela. Quando utilizamos a string de conexão com acesso irrestrito, o cartão de crédito é exibido integralmente; se utilizarmos a string de conexão com o usuário WebUser, o cartão é apresentado com uma porção de asteriscos.

static void Main(string[] args)
{
    const string conexao1 = "Data Source=.;Initial Catalog=DB;user id=WebUser;password=123";
    const string conexao2 = "Data Source=.;Initial Catalog=DB;Integrated Security=True";

    Exibir(conexao1);
    Exibir(conexao2);
}

private static void Exibir(string connString)
{
    using (var conn = new SqlConnection(connString))
    {
        using (var cmd = new SqlCommand("SELECT CartaoDeCredito FROM Cliente", conn))
        {
            conn.Open();

            using (var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                if (dr.Read())
                    Console.WriteLine(dr.GetString(0));
        }
    }
}

E o resultado é:

12-****-****-78
1234-5678-1234-5678

Anúncios

HTTPS no Kestrel

Sempre quando pensamos em hospedar uma aplicação desenvolvida em ASP.NET logo nos vem a mente o IIS. Apesar de uma infinidade de recursos que ele possui, o novo ASP.NET traz nativamente uma forma de hospedar as aplicações em um processo fora do IIS (self-hosting), chamado de Kestrel, qual foi construído com a finalidade de ser multi-plataforma e vem ganhando bastante evidência com alguns testes que demonstram grandes resultados em termos de performance.

Aos poucos a Microsoft vem adicionado nele algumas funcionalidades para que ele incorpore tudo que é necessário para utilizarmos em ambientes de produção. A finalidade deste artigo é demonstrar como configurar a aplicação para suportar o uso do protocolo HTTPS e, consequentemente, proteger os recursos que serão expostos pela aplicação.

Como sabemos, independentemente da tecnologia ou servidor que utilizamos para as nossas aplicações, para o uso do HTTPS se faz necessário a compra de um certificado de alguma entidade publicamente conhecida, para que possamos instalar em nosso servidor e configurar a nossa aplicação para utiliza-lo para estabelecer um túnel seguro de comunicação entre o cliente e o servidor e vice-versa. Como o foco é demonstrar a configuração, vou utilizar um certificado de testes emitido por uma ferramenta, sem valor para uso em ambiente de produção.

O primeiro passa em nossa aplicação é indicar ao runtime que o hosting a ser utilizado é o Kestrel, e para isso, recorremos ao método UseKestrel. Em um dos seus overloads é possível acessar algumas configurações e entre elas a possibilidade de indicar que queremos que o HTTPS seja utilizado, que é expressado através do método de estensão UseHttps. Para fazer uso deste método é necessário a instalação de um pacote NUGET chamado Microsoft.AspNetCore.Server.Kestrel.Https.

Uma vez que o certificado está criado e armazenado em um arquivo PFX (que inclui a sua chave privada) e o pacote acima mencionado esteja instalado na aplicação, utilizamos o código abaixo para indicar o local onde o arquivo PFX referente ao certificado está localizado no disco; note também que o “12345” é a senha para que o ASP.NET possa acessar o certificado.

public class Program
{
    public static void Main(string[] args)
    {
        new WebHostBuilder()
            .UseKestrel(opts => opts.UseHttps(@”C:tempAppTesteMeuWebSite.pfx”, “12345”))
            .UseUrls(“http://localhost:5000/”, “https://localhost:5001/”)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .Build()
            .Run();
    }
}

Ao rodar, a aplicação estará disponível para acesso tanto através do HTTP quanto HTTPS, porém em portas diferentes.

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:

Utilizando o HSTS

Quando falamos em proteger a comunicação entre a aplicação web e os clientes que a consomem, logo pensamos em HTTPS. Este protocolo tem a finalidade de criar um túnel entre as partes, garantindo com que as informações trafeguem entre os dois pontos mantendo a confidencialidade (ninguém além dos dois consegue visualizar) e a integridade (ninguém consegue alterar).

Quando habilitamos este protocolo na nossa aplicação e também no hosting que hospeda a mesma, não é 100% garantido que a aplicação será acessada através de HTTPS, colocando em risco a segurança, pois alguém no meio do caminho pode interceptar a requisição e explorar todo o seu conteúdo, e o pior, começar a direcionar o usuário para sites maliciosos.

Para um teste simples, considere o site do Banco Itaú. Muitas vezes as pessoas não se atentam em acessar o site digitando o https:// no navegador. Se monitorarmos a requisição para o endereço http://www.itau.com.br, nós veremos que o navegador recebe como resposta o código 301 (Moved Permanently), obrigando o navegador a encaminhar o cliente para o endereço seguro, que é o https://www.itau.com.br.

Ao receber este tipo de resposta e houver alguém interceptando a comunicação, ele pode substituir o endereço do redirecionamento e, consequentemente, nos mandar para um site malicioso, que simula a aparência do banco, e rouba todos os nossos dados. Para evitar isso, um novo recurso chamado HTTP Strict Transport Security (ou apenas HSTS) foi criado e permite à uma aplicação web indicar que ela somente pode ser acessada através do protocolo HTTPS, e em conjunto com o navegador, assegurarão que independentemente do que se tente fazer, a requisição sempre será feita (e as vezes até modificada para realizar) através do protocolo seguro. Para o servidor indicar ao navegador a obrigatoriedade da utilização do HTTPS, ele deve incluir no cabeçalho da resposta o item (chave) Strict-Transport-Security, indicando o tempo (em segundos) em que o cabeçalho será mantido do lado do cliente.

A especificação também contempla um parâmetro neste cabeçalho chamado includeSubDomains, que como o próprio nome indica, subdomínios deste site deverão ter a garantia de que também serão acessíveis somente através do HTTPS.

No ASP.NET 5, que é independente de hosting, podemos incluir este cabeçalho através de um middleware. É importante dizer que segundo a especificação, este cabeçalho só deve ser enviado ao cliente quando ele já estiver dentro de uma conexão protegida. E esta validação pode ser feita através da propriedade IsHttps que é exposta pelo objeto que representa a requisição.

public class HstsMiddleware
{
    private readonly RequestDelegate next;
    private readonly TimeSpan maxAge;

    public HstsMiddleware(RequestDelegate next, TimeSpan maxAge)
    {
        this.next = next;
        this.maxAge = maxAge;
    }

    public async Task Invoke(HttpContext context)
    {
        if (maxAge > TimeSpan.Zero && context.Request.IsHttps)
            context.Response.Headers.Append(
                “Strict-Transport-Security”, $”max-age={maxAge.TotalSeconds}”);

        await next(context);
    }
}

public static class HstsMiddlewareExtensions
{
    public static IApplicationBuilder UseHsts(this IApplicationBuilder builder, TimeSpan maxAge) => 
        builder.UseMiddleware<HstsMiddleware>(maxAge);
}

Alternativamente você também pode recorrer ao IIS para realizar a configuração do HSTS, e permitir com que os recursos que são disponibilizados por ele também sejam protegidos por HTTPS. A solução foi proposta pelo Doug Wilson e consiste em criar uma regra para sobrescrever o protocolo HTTP para HTTPS utilizando o arquivo de configuração da aplicação ou do servidor.

<?xml version=”1.0″ encoding=”UTF-8″?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name=”HTTP to HTTPS redirect” stopProcessing=”true”>
                    <match url=”(.*)” />
                    <conditions>
                        <add input=”{HTTPS}” pattern=”off” ignoreCase=”true” />
                    </conditions>
                    <action type=”Redirect” url=”https://{HTTP_HOST}/{R:1}”
                        redirectType=”Permanent” />
                </rule>
            </rules>
            <outboundRules>
                <rule name=”Add Strict-Transport-Security when HTTPS” enabled=”true”>
                    <match serverVariable=”RESPONSE_Strict_Transport_Security”
                        pattern=”.*” />
                    <conditions>
                        <add input=”{HTTPS}” pattern=”on” ignoreCase=”true” />
                    </conditions>
                    <action type=”Rewrite” value=”max-age=31536000″ />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

Preload List

Apesar de garantir que todos os recursos da aplicação serão acessados através do HTTPS, o primeiro problema ainda persiste, ou seja, a requisição inicial para o site do banco pode continuar sendo feita através de HTTP, e a possibilidade de interceptação continua. Para evitar isso, o Google mantém um site (HSTS Preload List) em que podemos adicionar URLs que emitem este cabeçalho, e obviamente, possuem um certificado válido. Isso permitirá ao navegador antes de fazer a requisição para o site avaliar se ele está contido na lista, e se estiver, já transformará a primeira requisição em HTTPS.

Depois da primeira requisição feita, o navegador já é capaz de detectar a necessidade de acessar a aplicação através de HTTPS, e ao acessa-lo via HTTP, o próprio navegador faz um redirecionamento interno (307 – Internal Redirect) e já faz a requisição com HTTPS. É possível ver esse comportamento na imagem abaixo.

Protegendo Configurações no ASP.NET

Quando construímos uma aplicação, temos diversos itens para realizar a configuração. Entre estes itens, estão configurações que guiam a execução da aplicação, o gerenciamento de algum recurso que foi incorporado a ela ou simplesmente valores que são necessários para o negócio para qual a mesma está sendo construída.

Entre estas configurações, temos strings de conexões com base de dados, endereços de servidor SMTP para envio de e-mails, chave de identificação para serviços de autenticação (Google, Facebook, etc.), etc. Não é comum manter estes valores em hard-code, pois pode mudar a qualquer momento e variar de ambiente para ambiente, e precisamos ter a flexibilidade de alterar sem a necessidade de recompilar a aplicação.

Isso nos obriga a manter a chave em um arquivo de configuração. Até então trabalhamos com o arquivo chamado web.config, que serve justamente para incluir diversas configurações da aplicação. A nova versão do ASP.NET (5) muda isso, disponibilizando um novo sistema de configuração mais simples e não menos poderoso. Apesar de continuar dando suporte ao formato XML, a versão mais recente adotou como padrão o formato JSON.

O problema desse modelo é a exposição das configurações. Quando trabalhamos com projetos e que podemos expor o repositório do código publicamente (através do GitHub ou qualquer outro gerenciador de código fonte), deixar armazenado neste arquivo informações sigilosas e, consequentemente, torna-las públicas, é algo que nem sempre desejamos. O ASP.NET 5 resolve isso através de um recurso chamado de User Secrets.

Esta funcionalidade permite externalizar certas configurações em um arquivo que fica de fora do controle de versão do código fonte. Sendo assim, para as chaves que são colocadas no arquivo de configuração da aplicação (config.json) e que precisam ser protegidas, podemos recorrer à este recurso, que basicamente consiste em criar um novo arquivo (chamado de secrets.json) e que será armazenado, no Windows, no seguinte endereço: %APPDATA%microsoftUserSecrets<userSecretsId>secrets.json.

É importante dizer que o local deste arquivo varia de acordo com o sistema operacional onde a aplicação está sendo desenvolvida, e não é aconselhável tornar a aplicação dependente dele; futuramente a Microsoft se dá o direito de mudar (como, por exemplo, criptografar o seu conteúdo), e a aplicação corre o risco de parar de funcionar. O <userSecretsId> é substituído pela chave que é colocada no arquivo project.json, e dentro deste diretório teremos o arquivo secrets.json, conforme comentado acima. É importante notar também que precisamos adicionar a dependência para usar este recurso, e para isso, devemos incluir o pacote chamado Microsoft.Framework.Configuration.UserSecrets:

{
  “commands”: {
    “web”: “Microsoft.AspNet.Hosting –config hosting.ini”
  },
  “dependencies”: {
    “Microsoft.AspNet.Server.IIS”: “1.0.0-beta5”,
    “Microsoft.AspNet.Server.WebListener”: “1.0.0-beta5”,
    “Microsoft.Framework.Configuration.UserSecrets”: “1.0.0-beta5”
  },
  “userSecretsId”: “WebApplication1-12345”,
  “version”: “1.0.0-*”,
  “webroot”: “wwwroot”
}

Com essa configuração realizada, podemos adicionar no arquivo config.json todas as configurações necessárias para o funcionamento da aplicação e incluir no arquivo secrets.json somente as configurações que queremos proteger.

[config.json]
{
  “Data”: {
    “DefaultConnection”: {
      “ConnectionString”: “Server=(localdb)\MSSQLLocalDB;Database=Teste;Trusted_Connection=True;”
    }
  },
  “Certificado”:  “123”
}

[secrets.json]
{
  “Certificado”:  “128372478278473248378”
}

Opcionalmente você pode recorrer à uma opção que existe se clicar com o botão direito sobre o projeto e, em seguida, em “Manage User Secrets“, e assim ter acesso ao arquivo secrets.json sem a necessidade de saber onde o Visual Studio está armazenando-o. Mas isso não basta para o ASP.NET entender que ele deve, também, considerar a busca no arquivo secrets.json. Para isso precisamos indicar que à ele que vamos utilizar o recurso de User Secrets, conforme podemos ver abaixo:

public class Startup
{
    public void Configure(IApplicationBuilder app, IApplicationEnvironment appEnv)
    {
        this.Configuration =
            new ConfigurationBuilder(appEnv.ApplicationBasePath)
                .AddJsonFile(“config.json”)
                .AddUserSecrets()
                .Build();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(this.Configuration[“Certificado”]);
        });
    }

    public IConfiguration Configuration { get; set; }
}

A ordem em que invocamos o método é importante, ou seja, neste caso se ele encontrar a chave “Certificado” no arquivo secrets.json o seu valor será apresentado. Caso o valor não exista, então ele extrairá o valor do arquivo config.json.

Externalizando a Emissão de Tokens

No artigo anterior eu mostrei como emitir tokens para aplicações que consomem APIs. Como podemos notar naquele artigo, o mesmo projeto e, consequentemente, a mesma aplicação, é responsável por gerenciar, validar e autenticar os usuários. Enquanto isso é o suficiente para aplicações pequenas, pode não ser muito produtivo e de fácil gerenciamento quando temos outras aplicações que também precisam de autenticação.

Se for analisar mais friamente, talvez até quando temos uma pequena aplicação, seja mais viável manter uma segunda aplicação que seria responsável por todo o processo de autenticação, e a medida em que novos serviços são criadas, eles confiariam neste autenticador que já está pronto.

O que faremos neste artigo é separar o código que é responsável por validar e emitir os tokens da aplicação (API) que consome o token e libera o acesso aos recursos mediante a validade do mesmo. A imagem abaixo ilustra o fluxo que será executado a partir de agora:

Note que o Autenticador é responsável por validar e emitir o token para o usuário que se identifica para ele; o Serviço é onde está hospedada a aplicação que irá consumir o token. Basicamente temos que dividir aquele código do outro artigo em dois projetos, ou seja, não há necessidade nem de por nem tirar qualquer linha de código. O serviço passa a ter apenas o código que pluga no pipeline de execução a validação do token:

public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();

    ConfigureOAuth(app);
WebApiConfig.Register(config);

    app.UseWebApi(config);
}

private static void ConfigureOAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

O restante do código, que é onde configuramos a validação do usuário, é movido para a aplicação chamada de Autenticador. A aplicação cliente passa a apontar para os endereços, agora em diferentes locais, para emitir o token em um deles, e passar o token gerado para a aplicação.

using (var client = new HttpClient())
{
using (var tokenResponse = await
client.PostAsync(“http://www.autenticador.com.br:81/issuer/token“, CreateContent()))
{

        using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, “http://www.servico.com.br:82/api/Test/GetData“))
{

}
}
}

Por fim, se rodarmos ele não irá funcionar. O motivo é que o token é protegido utilizando as chaves que estão no elemento machineKey dentro do arquivo Web.config. Se as aplicações (Autenticador e Serviço) tiverem chaves diferentes, então o token gerado pelo Autenticador não será possível ser consumido pelo Serviço. O que precisamos fazer aqui é gerar uma chave e copiar a mesma para as duas aplicações. Para gerar essas chaves, podemos recorrer à um recurso que temos no próprio IIS (mais detalhes aqui). Abaixo tem o arquivo Web.config já com esta configuração realizada. Vale lembrar que o tamanho das chaves foi reduzido por questões de espaço.

validationKey=”D2E9D0907…47BC9F8A598″
decryptionKey=”7278E7F93…658B70DE07E21CF”
validation=”SHA1″
decryption=”AES” />

Depois desta informação espelhada em ambas as aplicações, já é possível uma das aplicações gerar o token e a outra consumi-lo.

Emissão de Tokens no ASP.NET Web API

Em aplicações Web é comum o cliente precisar se autenticar para ter acesso à determinados recurso da aplicação. Quando o usuário se identifica para a aplicação, e se ela validar o mesmo, gravamos um cookie no navegador para que ele possa manter a autenticação válida durante a sua navegação (e enquanto o mesmo não expirar), evitando assim que ele tenha que se (re)autenticar toda cada vez que quer acessar um recurso protegido.

Quando estamos trabalhando com serviços, onde são outros sistemas que os consomem, precisamos autenticar a aplicação/usuário para que ele possa acessar os recursos que eles disponibilizam. Enquanto aplicações Web (que possuem uma interface) mantém um cookie, os serviços lidam de uma forma diferente, ou seja, recorrem à tokens para autenticar e identificar o chamador, e a partir deste momento, o mesmo deverá apresentar o token a cada vez que deseja acessar algum dos recursos expostos pelo serviço.

Ao invés de termos controllers e actions que servirão para esse tipo de atividade, podemos (e devemos) recorrer à alguns recursos que a própria tecnologia nos oferece. Quando optamos por hospedar e executar o ASP.NET Web API no OWIN, ele já traz alguns middlewares para autenticação, e entre eles, a possibilidade de utilizar o a tecnologia OAuth2 para guiar todo o processo de autenticação. O primeiro passo é instalar os seguintes pacotes (via Nuget): Microsoft.Owin.Host.SystemWeb, Microsoft.AspNet.WebApi.Owin e Microsoft.Owin.Security.OAuth.

Esses pacotes irão disponibilizar um conjunto de classes para trabalharmos com o OWIN dentro do ASP.NET Web API. O primeiro passo é realizar duas configurações dentro da classe Startup (exigência do OWIN): um middleware que será responsável pela geração de tokens e o outro que terá o papel de validar os tokens apresentados para o serviço antes deles serem executados.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        ConfigureAuthentication(app);
        WebApiConfig.Register(config);
        app.UseWebApi(config);
    }

    private static void ConfigureAuthentication(IAppBuilder app)
    {
        app.UseOAuthAuthorizationServer
        (
            new OAuthAuthorizationServerOptions()
            {
                AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString(“/issuer/token”),
                Provider = new OAuthAuthorizationServerProvider()
                {
                    OnValidateClientAuthentication = async ctx =>
                    {
                        await Task.Run(() => ctx.Validated());
                    },
                    OnGrantResourceOwnerCredentials = async ctx =>
                    {
                        await Task.Run(() =>
                        {
                            if (ctx.UserName != “Israel” || ctx.Password != “12345”)
                            {
                                ctx.Rejected();
                                return;
                            }

                            var identity = new ClaimsIdentity(
                                new[] {
                                        new Claim(ClaimTypes.Name, ctx.UserName),
                                        new Claim(ClaimTypes.Role, “Admin”)},
                                ctx.Options.AuthenticationType);

                            ctx.Validated(identity);
                        });
                    }
                }
            }
        );

        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Através do método UseOAuthAuthorizationServer realizamos as configurações do emissor de tokens. As propriedades expostas pela classe OAuthAuthorizationServerOptions nos permite customizar diversas informações críticas para o processo de emissão. Entre elas temos o endpoint em que os clientes deverão visitar para gerar o token, o tempo de expiração para cada token e, por fim, e não menos importante, o provider. É o provider que podemos customizar a validação do usuário, verificando se ele é ou não um usuário válido. Para essa customização, basta herdar da classe OAuthAuthorizationServerProvider e sobrescrever (se assim desejar) diversos métodos para controlar todos os eventos gerados pelo protocolo OAuth2.

Para o exemplo estou optando por definir a propriedade AllowInsecureHttp como true, evitando a necessidade de expor o serviço sobre HTTPS, mas é importante que isso seja reavaliado antes de colocar em produção. Outro detalhe é que estou definindo, em hard-code, o nome e senha válidos; em um cenário real, é neste momento que deveríamos recorrer à algum repositório de usuários e validar se ele existe lá.

Depois de configurado o emissor de tokens, o middleware que habilitamos através do método UseOAuthBearerAuthentication é o responsável por validar os tokens que são enviados nas futuras requisições e identificar se eles são ou não válidos.

O fluxo necessário para a geração do token e para envio subsequente em novas requisições é bastante simples. Basta realizar um post para o endereço configurado na propriedade TokenEndpointPath, passando no corpo da mensagem três parâmetros: grant_type, username e password. Esses parâmetros serão utilizados pelo protocolo OAuth para validar o usuário e gerar o token caso ele seja válido. O parâmetro grant_type indica ao OAuth o tipo de autenticação que queremos fazer; neste caso o valor deverá ser “password”. Já os parâmetros username e password são autoexplicativos.

Se o usuário for válido, então o resultado será devolvido através do corpo da mensagem de resposta, formatado em JSON. Abaixo está um exemplo da resposta, mas o token foi reduzido por questões de espaço. O seu tamanho é muito maior que isso.

{
    “access_token”:”CPIA6Ha-9Bg2Yh8PZD-7Terzl9At…..UBp-WlpkNYn5ioD85U”,
    “token_type”:”bearer”,
    “expires_in”:3599
}

Agora compete à aplicação que consome este serviço armazenar o token e embutir nas futuras requisições. A exigência do protocolo é que o token seja incluído através do header Authorization na requisição, especificando além do token, também o seu tipo, que neste caso é bearer, e ele também é devolvido pelo emissor do token.

Para realizarmos os testes, vamos criar um controller e expor um método para que seja consumido apenas por usuários que estejam devidamente autenticados. Para isso, basta decorar o controller ou a ação com o atributo AuthorizeAttribute, conforme podemos visualizar no código abaixo:

public class TestController : ApiController
{
    [HttpGet]
    [Authorize]
    public string GetData()
    {
        return “Testing…”;
    }
}

Para exemplificar o consumo por parte do cliente, estou utilizando uma aplicação console para solicitar a emissão do token, e na sequência invocamos o método GetData da API passando o token como header, conforme o fluxo que foi explicado acima.

private async static void Invoke()
{
    using (var client = new HttpClient())
    {
        using (var tokenResponse = await client.PostAsync(“http://localhost:1195/issuer/token&#8221;, CreateContent()))
        {
            var tokenBody = await tokenResponse.Content.ReadAsStringAsync();
            dynamic parsedTokenBody = JsonConvert.DeserializeObject(tokenBody);

            using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, “http://localhost:1195/api/Test/GetData&#8221;))
            {
                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue(
                        parsedTokenBody.token_type.ToString(),
                        parsedTokenBody.access_token.ToString());

                using (var responseMessage = await client.SendAsync(requestMessage))
                {
                    var responseBody = await responseMessage.Content.ReadAsStringAsync();

                    Console.WriteLine(responseBody);
                }
            }
        }
    }
}

private static FormUrlEncodedContent CreateContent()
{
    return new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>(“grant_type”, “password”),
        new KeyValuePair<string, string>(“username”, “Israel”),
        new KeyValuePair<string, string>(“password”, “12345”)
    });
}

Um detalhe importante é que dentro do controller, podemos fazer o (down)casting da propriedade User e chegar na instância da classe ClaimsPrincipal e, consequentemente, acessar o conjunto de claims que foi gerada pelo emissor do token para este usuário. Como disse anteriormente, claims estão em todo lugar.

((ClaimsPrincipal)this.User).Claims.First().Value;