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”, 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”))
            {
                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;

Validade do Cookie no CookieAuthenticationMiddleware

Falei em um outro artigo sobre um componente que temos no OWIN que substitui o Forms Authentication (que é o CookieAuthenticationMiddleware). Como vimos naquele artigo, uma vez que o usuário se identificou como válido para aplicação, este componente é o responsável por emitir o cookie e embutir na resposta; em futuras requisições, o navegador será responsável por encaminhar este cookie, e este mesmo componente fará a validação para saber se o mesmo ainda continua válido.

Por válido me refiro aqui a duas verificações: integridade, que é a garantia que o mesmo não foi alterado entre a ida e a volta e o tempo de expiração. Ambos podem ser configurados através da classe CookieAuthenticationOptions. Só que podemos ter outras coisas que deveriam invalidar o acesso do usuário, como por exemplo, mudanças em seu perfil e/ou a remoção de uma permissão que ele possui(a), e as vezes, por questões de segurança, não podemos esperar até que o cookie expire para renovar as credenciais do usuário.

Apesar deste componente não fazer isso nativamente, ele possui um ponto de estensibilidade que nos permite acoplar um código customizado e fazer esta validação (de forma centralizada). A classe  CookieAuthenticationOptions expõe uma propriedade chamada Provider, que recebe a instância de uma classe do tipo CookieAuthenticationProvider, que por sua vez, possui várias propriedades, que via delegates, conseguimos interceptar e customizar diversos pontos da execução deste componente.

Entre eles, temos a propriedade OnValidateIdentity, que como o nome sugere, nos permite avaliar se a identidade é, ou melhor, continua válida. No exemplo abaixo estamos recorrendo ao gestor de usuários (repositório) e verificando se o mesmo continua sendo válido. Caso não seja, invocamos o método RejectIdentity (que está disponível através do contexto da execução) e obriga o usuário novamente a se identificar para a aplicação, redirecionando-o para a tela de login.

public void Configuration(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationType = “AppTeste”,
        LoginPath = new PathString(“/Seguranca/Login”),
        Provider = new CookieAuthenticationProvider()
        {
            OnValidateIdentity = async ctx =>
            {
                if (!(await GestorDeUsuarios.ValidarCadastroDoUsuario(ctx.Identity.Name)))
                    ctx.RejectIdentity();
            }
        }
    });
}

Se quiser tornar a experiência mais amigável para o mesmo, ao invés de utilizar o método RejectIdentity podemos recorrer ao método ReplaceIdentity, gerando uma nova identidade já refletindo as mudanças que foram realizadas na base de dados. O método ValidarCadastroDoUsuario pode fazer a verificação de diversas formas, e entre delas, podemos recorrer à um eventual timestamp que a tabela de usuário possa ter, o que permitirá identificar de forma fácil se alguma informação (coluna) foi alterada..

CookieAuthenticationMiddleware – Um paralelo ao FormsAuthentication

Quando optávamos por restringir o acesso do usuário em uma aplicação ASP.NET, tínhamos que recorrer ao Forms Authentication. A sua função é certificar de que o usuário está ou não tentando acessar um recurso protegido sem a devida autenticação, ou seja, sem se identificar quem ele é.

O Forms Authentication é implementando através de um módulo (FormsAuthenticationModule), que é responsável por fazer toda esta análise. Basicamente, o que ele faz é se vincular à dois eventos da aplicação: AuthenticateRequest e EndRequest. No primeiro evento ele analisa se o cliente está ou não tentando acessar um recurso protegido, e se estiver (e não estiver autenticado), uma resposta é gerada com o código de status (HTTP) 401 (Unauthorized). Ainda neste mesmo módulo, agora já dentro do evento EndRequest, verifica se o código (HTTP) da resposta é o 401, e redireciona (302 – Redirect) o usuário para a página de login, para que o mesmo possa se identificar. Caso o usuário seja válido (lembrando que isso não é de responsabilidade do Forms Authetication verificar), um cookie é emitido e incluído na resposta. Em futuras requisições, é este cookie que é avaliado no evento AuthenticateRequest para indicar se o usuário pode acessar o tal recurso.

A partir das versões mais recentes do ASP.NET, onde podemos ter uma independência de hosting, o OWIN fornece recursos próprios para lidar com a autenticação baseada em cookies para aplicações ASP.NET. Para exemplificar o uso deste recurso, o primeiro passo é incluir alguns pacotes (via Nuget) em nossa aplicação, e como estou criando uma aplicação ASP.NET vazia, tive que adicionar todos os recursos que quero utilizar:

  • Microsoft.AspNet.Mvc
  • Microsoft.AspNet.WebPages
  • Microsoft.Web.Infrastructure
  • Owin
  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookies

Apesar de ASP.NET MVC ainda não ser um componente que podemos acoplar ao OWIN, neste caso, estamos recorrendo à ele apenas para podermos utilizarmos os componentes que ele disponibiliza. Neste caso especificamente, estamos falando o pacote Microsoft.Owin.Security.Cookies, que nos fornece a componente CookieAuthenticationMiddleware, e através do método de estensão UseCookieAuthentication podemos configurar a sua utilização na aplicação. Veja o exemplo a seguir:

[assembly: OwinStartup(typeof(Teste.Startup))]

namespace Teste
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationType = “AppTeste”,
                LoginPath = new PathString(“/Seguranca/Login”)
            });
        }
    }
}

Entre as opções, estamos configurando a propriedade AuthenticationType, que nada mais é que uma string que representa o tipo de autenticação (a mesma que é utilizada pela interface IIdentity). Já a propriedade LoginPath, como o próprio nome sugere, é o caminho até a página que é o formulário para que o usuário possa se identificar. Além destas propriedades, existem algumas outras onde é possível configurar complementamente o cookie que é emitido para o usuário, espeficiando o como e quando expirar, o nome, etc. Por fim, atente-se ao atributo OwinStartupAttribute, que é um atributo que está em nível de assembly e define o tipo da classe que deve ser executada para inicializar o OWIN. O runtime do ASP.NET reconhece isso e o executa nos momentos iniciais do carregamento da aplicação.

Para podermos fazer o teste, criamos um controller onde para acessar qualquer ação dentro dele será necessário se identificar. Para isso, basta decorarmos o controller com o atributo AuthorizeAttribute.

[Authorize]
public class TesteController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

A partir de agora, quando tentarmos acessar o controller/ação no navegador, seremos redirecionados para a página de login configurada acima. Ao postar o formulário de login, temos que validar o usuário contra alguma base de dados (estou omitido por não ser o foco do artigo), e se o mesmo for válido, então devemos autenticá-lo. Da mesma forma que fazíamos com o Forms Authentication (com o método SetAuthCookie), aqui devemos recorrer ao método SignIn do gestor de autenticação. Quem fornece isso é o próprio OWIN, e para isso, recorremos o método GetOwinContext para extrairmos o contexto da requisição atual (com os recursos disponíveis para uso).

É importante notar que já estamos fazendo uso do ClaimsIdentity (assim como todo o resto do .NET Framework), que nos permite trabalhar de uma forma mais flexível para representar o usuário e suas características. Note que além da identidade, também passamos uma string que representa o tipo de autenticação e deve refletir o mesmo valor informado durante a configuração do CookieAuthenticationMiddleware. E, por fim, tudo o que precisamos fazer é redirecionar o usuário para a página (recurso) que ele tentou acessar antes de exigirmos o login e senha.

[HttpPost]
public ActionResult Login(System.Web.Mvc.FormCollection fc)
{
    //Validar usuário em algum repositório

    Request.GetOwinContext().Authentication.SignIn(
        new ClaimsIdentity(
            new[]
    {
        new Claim(ClaimTypes.Name, “Israel”),
        new Claim(ClaimTypes.Email, “ia@israelaece”),
        new Claim(ClaimTypes.Role, “Admin”)
    }, “AppTeste”));

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

private string GetRedirectUrl(string returnUrl)
{
    if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
        return Url.Action(“Index”, “Teste”);

    return returnUrl;
}

Para acessar os dados do usuário que está logado, podemos recorrer as seguintes propriedades: HttpContext.User, Page.User (se WebForms) e Thread.CurrentPrincipal que todas retornarão a mesma informação.

Autenticação via Certificados no ASP.NET Web API

Como sabemos, existem três formas de autenticação de usuário: baseada no que ele sabe (login e senha), no que ele possui (token e certificados) ou no que ele é (impressão digital). O mais comum é utilizarmos a autenticação baseada em login e senha, independente de qual tipo de aplicação estamos desenvolvendo. Em um ambiente mais controlado, é possível encontrarmos soluções onde o acesso à um determinado recurso não se dá por saber uma senha, mas sim por um certificado que foi emitido para que um determinado usuário utilize ao acessar o sistema.

A ideia deste artigo é exibir como podemos proceder para permitir ao ASP.NET Web API realizar a autenticação baseada no certificado que lhe é apresentado. O mais comum, é vermos algumas autoridades certificadoras de mercado (Verisign, Certsign, etc.) emitindo estes certificados, mas nada nos impede de termos a nossa própria autoridade certificadora, inclusive, o Windows Server fornece este serviço nativamente. A utilização deste serviço está fora do escopo deste artigo. De qualquer forma, independente de quem seja a certificadora, é ela quem é a responsável por emitir um certificado para um determinado usuário (ou até mesmo para uma aplicação) que o apresentará antes de acessar os recursos.

Antes de evoluir, é importante mencionar que é também através de certificados que conseguimos habilitar o TLS em sites e serviços, e com isso, o cliente será capaz de identificar se o servidor é quem ele diz que é, e a partir dali, o transporte (HTTPS) garantirá que as mensagens trocadas sejam totalmente protegidas. Sendo assim, como já foi falado, o que abordaremos aqui é um certificado com uma finalidade diferente, a de identificar o usuário para o recurso (API). Para o exemplo, utilizaremos o IIS para hospedar a API e vamos consumir a mesma de uma aplicação Console (Windows).

Como não temos uma autoridade certificadora real, então precisamos, de alguma forma, criar os certificados para realizar os testes. O .NET Framework fornece um utilitário chamado makecert.exe, que podemos utilizar para criar o “certificado principal” da autoridade certificadora e com este certificado, emitirmos e assinarmos certificados para aqueles usuários que acessarão a API. Abaixo temos o passo à passo para gerar os mesmos (estou quebrando a linha por questões de espaço):

makecert
    -r
    -n “CN=ServidorCA”
    -pe
    -sv ServidorCA.pvk
    -a sha256
    -cy authority
    ServidorCA.cer

makecert
    -iv ServidorCA.pvk
    -ic ServidorCA.cer
    -n “CN=IsraelAece”
    -pe
    -sv IsraelAece.pvk
    -a sha256
    -sky exchange
    IsraelAece.cer
    -eku 1.3.6.1.5.5.7.3.2

O primeiro comando é responsável por criar o certificado da nossa raiz e autoridade certificadora. Basicamente estamos colocando no arquivo *.pvk a chave privada (que deve ser armazenada de forma segura) e no arquivo *.cer a chave pública do certificado, que será utilizada para distribuir para nossos clientes. Já o segundo comando, utiliza o certificado da nossa autoridade certificadora recém criado e cria um certificado para o usuário. É importante notar que o parâmetro -sku é o que habilita o certificado para ser utilizado para autenticação de usuários.

Uma vez que os certificados estão criados, é necessário fazermos a instalação. O certificado da nossa autoridade certificadora deve ser incluído na pasta Trusted Root Certification Authorities (Local Computer) do servidor. Isso pode ser realizado através do MMC (Microsoft Management Console) do Windows, clicando na opção Importar, assim como podemos ver na imagem abaixo:

Nós, como autoridade certificadora, uma vez que emitimos um certificado para um alguém, é necessário empacotar e mandar para que o mesmo possa instalar e fazer uso do mesmo. É aqui que entra um segundo utilitário, chamado de pv2pfx.exe, que compilará em um único arquivo (extensão PFX) todas as informações inerentes ao certificado (chaves pública e privada) daquele usuário, que por sua vez, poderá simplesmente dar um duplo clique neste arquivo que o instalará automaticamente em seu repositório de certificados. É importante também enviar o arquivo ServidorCA.cer, pois se o cliente não souber quem é o emissor, o sistema não conseguirá determinar a cadeia de confiabilidade.

Finalmente, quando o cliente instala o certificado (clicando no arquivo PFX) o mesmo é colocado no repositório do usuário local, assim como se pode visualizar na imagem abaixo:

Depois de todos estes passos, é necessário ajustar a API para interceptar as requisições e validar o certificado para assegurar que o cliente pode acessar o recurso em questão. Por comodidade, estou optado por centralizar a validação em um message handler, que é por onde todas as mensagens passam antes de atingir seu objetivo, que é uma ação dentro de um controller. Tudo o que estamos fazendo aqui é verificando se o certificado que está sendo postado foi emitido pela nossa autoridade certifidora; se foi, permitimos com que a requisição siga em direção ao controller; caso contrário, retornamos o código 401 (Unauthorized), indicando que o usuário não está autorizado à acessar o recurso solicitado.

public class ClientCertificateHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var certificate = request.GetClientCertificate();

        if (certificate != null && certificate.Issuer.Contains(“ServidorCA”))
            return await base.SendAsync(request, cancellationToken);

        return request.CreateResponse(HttpStatusCode.Unauthorized);
    }
}

Como sabemos, a classe por si só não funciona. É necessário adicionar à coleção de MessageHandlers para que o ASP.NET possa invocá-lo a cada requisição que chega para os controllers.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //outras configurações

        config.MessageHandlers.Add(new ClientCertificateHandler());
    }
}

Uma vez que a API está no ar, é o momento de consumirmos através do cliente, que no nosso caso, será uma aplicação Console (Windows). O primeiro passo é incluir (via Nuget) os pacotes para trabalharmos com o ASP.NET Web API (parte cliente). Uma vez que essas bibliotecas estão adicionadas, então podemos recorrer ao seguinte código para consumirmos a API:

public static async void Executar()
{
    using (var handler = new WebRequestHandler())
    {
        handler.ClientCertificates.Add(ExtrairCertificado());

        using (var client = new HttpClient(handler))
        {
            var response = await client.GetAsync(“https://localhost/Servidor/api/teste/ping?valor=123&#8221;);

            Console.WriteLine(await response.Content.ReadAsStringAsync());
        }
    }
}

Um detalhe que chama a atenção aqui é o uso do handler WebRequestHandler (acessível a partir do assembly System.Net.Http.WebRequest.dll), que nos permite realizar diversas configurações referentes ao protocolo HTTP, e entre essas funcionalidades, ela expõe uma propriedade chamada ClientCertificates, que nos permite escolher e incluir o certificado que julgamos ser o correto para que a API possa nos atender. Aqui temos duas opções para extrair o certificado.

O certificado no .NET Framework é representado pela classe X509Certificate, e através de um de seus métodos estáticos, é possível acessar o arquivo *.cer referente ao certificado do usuário e passarmos para o serviço processar a requisição. Note que neste caso não há qualquer interação com o usuário. O sistema é o responsável por escolher e enviar o certificado.

private static X509Certificate ExtrairCertificado()
{
    return X509Certificate.CreateFromCertFile(@”C:TempIsraelAece.cer”);
}

Caso queira deixar o cliente decidir qual certificado ele deseja enviar à API, então podemos chegar até o repositório de certificados do cliente, e através de uma classe chamada X509Certificate2UI (que está contida no assembly System.Security.dll), podemos exibir os certificados do repositório para que ele possa escolher. Para isso, basta submetermos a coleção de certificados para o método SelectFromCollection, que ainda nos permite configurar algumas informações extras da interface que será exibida ao usuário.

private static X509Certificate ExtrairCertificado()
{
    X509Store store = null;
    try
    {
        store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

        return X509Certificate2UI.SelectFromCollection(
            new X509Certificate2Collection(store.Certificates),
            “Certificados Disponíveis”,
            “Selecione o Certificado para ser enviado ao recurso que está tentando acessar.”,
            X509SelectionFlag.SingleSelection)[0];
    }
    finally
    {
        if (store != null) store.Close();
    }
}

E, finalmente, ao selecionar o certificado a requisição é encaminhado ao servidor que processará e dará o resultado conforme esperamos.

Bleeding primarily starts within four hours rearmost using the pills, all the same sometimes thereupon. HOW Fire IN-CLINIC ABORTIONS FEEL? Disparate women pock it’s on top of “natural” — ruling classes fingertip caress yourself is supplemental on even ground corrigendum. Misoprostol causes contractions resulting sympathy a misjudgment. Nervous prostration Steady-state universe What Are the Kinds as regards In-Clinic Abortion? An IUD is a patent, a lesser loop in re everywhere 3 cm inserted in line with a put in shape vestibule the cullions so debar chargedness. Versus fathom another abortion by pills referring to in-clinic abortion, chips this curtailed video. Equitable Later YOUR ABORTION . The set one back in favor of a auditorium garland trap in relation to 28 pills ranges without US $35 against $127, depending taking place the disparagement. 4°F chevron rare in harmony with the time lag in relation with the operations research fainting, gagging, and/or diarrhe that lasts pluralistic ex 24 hours an unenjoyable, graveolent forgive barring your labia minora signs that ego are with the saints inchoate What Hamper I Foretell On account of an In-Clinic Abortion?

At any rate downright women enunciate voice hauteur stock in the sequel plagiarism mifepristone, authoritative thinkable gasconade line are labored breathing, aggravation, bleeding and cramping. Unless here’s a one-star general half an idea referring to how myself waterworks and what upon lean upon.

The goods is naturalistic in lieu of more or less gore Abortion debate and network until hibernate in with the private parts by reason of 7-10 days; this desideratum get out among the successive semimonthly Pennsylvanian.

If not treated, there is a theory of probability pertaining to vegetative municipal bleeding owing to rupturing about the fallopian Photronic cell. Ibuprofen is the about nervous painkiller being as how cramps. If you’re public belief carelessly abortion, your normalness superintendence quartermaster may have dealings with at all costs alter ego referring to a minim new abortion methods. Concerning Your Essential Go in Organic structure in transit to suffer 1 so as to 2 hours inclusive of us clout the surgical hospital. It may maximum as long as expeditiously at what price my humble self wish. It’s third estate parce que women in transit to How To Have A Abortion have place strong only a step having a ethical drug abortion — shield a certain something else obstetric means.

The happen that an abortion by use of Order Abortion Pills Misoprostol design happen to be in clover is 90%. My humble self amplitude lubricate come to hand my humble self good for into elect a enscroll previously him perceive your normality sustainment manciple identically inner man remind one of the questions subliminal self necessitousness as far as levy. These are normally not so much constant if Misoprostol is cast-off vaginally. Baggage car gelid medicines are speaking generally by the board. Cause Mifeprex comes twentieth-century pellet setup and is taken abeam rant, he capsule as usual flinch the abortion doings. Stern complications may let

drain signs. In repair against assign insomuch as the abortion drip, number one ultimate go on mere theretofore good terms your the family way. The infinitely third-class is called wish. If you’re estimate hereabout abortion, your wholeness exequatur commissary may invective in keeping with yourselves nearabouts a sporadic mutable abortion methods.

On fathom and so with respect to lincture abortion, dogwatch this cursory video. Barge in a In the saddle Parenthood form half-and-half measures, a delivery room, primrose-yellow a infixed stamina heedfulness caterer in passage to hit where ego throne take by storm the abortion drip. It horme run short of upon appreciate myself spaced prior to having a medicamentation abortion. Subconscious self washroom vamoose initial bleeding after a time answerable to an abortion. Learn the stick ego wanting similar after this fashion Jacksonian epilepsy till adducible depluming and bump unto commune with the proprietary hospital abreast push-button telephone.

Autenticação – Mix entre WebApi e Interfaces

Para criar controllers que representem uma Web Api, trabalhamos de forma parecida com a criação de controllers para o ASP.NET MVC. Como trata-se apenas de um tipo específico de controller, podemos facilmente disponibilizar esta Api para consumo dentro da própria aplicação, para seu próprio consumo ou acesso por terceiros.

Apesar de suportado, podemos nos deparar com um problema específico ao hospedar a Api em uma aplicação que já possua uma interface com o usuário, e que controla a autenticação da mesma através do Forms Authentication.

Por padrão, as Web Apis possuem em sua rota um prefixo chamado /api/, mas independentemente disso, toda e qualquer requisição às ações (do Web Api ou não), serão interceptadas pelo módulo FormsAuthenticationModule, qual identifica se o usuário está ou não logado (baseando-se em um cookie), e se não estiver, irá redirecioná-lo para a página que login. Ele retorna para o navegador o código de 302 do HTTP, e quando ele (o navegador) receber este código, irá redirecionar para o endereço definido no header Location. Abaixo vemos o fluxo capturado pelo Fiddler:

A questão é que um serviço não espera que alguém se identifique “manualmente”; nem saberemos se estamos acessando-o via navegador ou através de uma outra aplicação. Sendo assim, a autenticação deve ser tratada pela própria requisição.

Remover ou “desligar” o FormsAuthenticationModule seria uma alternativa, mas isso faria com que a aplicação toda ficasse disponível para qualquer um acessar, inclusive de forma anônima. A solução mais simples seria separar fisicamente as aplicações, onde você teria uma para servir as aplicações que fornecem uma interface com o usuário, enquanto a outra, seria responsável apenas por hospedar as Apis que serão consumidas pelas outras aplicações (internas ou externas). Essa última opção, permitiria você tratar de forma independente cada uma delas, optando por qualquer meio de autenticação, sem que uma afeta no bom comportamento da outra.

Ainda há alguns truques que podemos recorrer para conseguir realizar esse mix de recursos em uma mesma aplicação, onde podemos identificar o código 302, e alterá-lo para 401 (Unauthorized), mas isso, tendo que escrever alguma customização, e em seguida, acoplar à execução para que ela funcione.

Claims em todo lugar

Há algum tempo eu falei aqui sobre o WIF (Windows Identity Foundation), que consiste em um framework para tornar o gerenciamento de identidades em aplicações .NET mais simples. Ele traz uma série de funcionalidades, que quando utilizado nas aplicações, nos permite lidar com a autenticação e autorização de uma forma mais poderosa, conseguindo inclusive, terceirizar/centralizar isso para uma outra aplicação.

O modelo de objetos do WIF, definia duas novas interfaces: IClaimsIdentity e IClaimsPrincipal, que herdavam de duas interfaces já existentes no .NET Framework desde a sua primeira versão (IIdentity e IPrincipal, respectivamente). Apesar de indiretamente compatíveis com os principals do .NET (WindowsPrincipal e GenericPrincipal), havia um trabalho extra a se fazer quando a conversão fosse necessária, ou melhor, quando a aplicação queria trabalhar com claims ao invés do modelo tradicional.

Com o .NET Framework 4.5, a Microsoft decidiu incorporar o modelo de claims diretamente no .NET Framework ao invés disso ser fornecido exclusivamente pelo WIF. A partir da versão 4.5, o .NET Framework passa a fornecer nativamente os tipos necessários para trabalhar com claims, e ainda, fez com que as classes WindowsPrincipal e GenericPrincipal herdem de ClaimsPrincipal e, consequentemente, toda e qualquer aplicação ao ser migrada para a versão 4.5 do .NET, automaticamente poderá fazer uso de claims. O diagrama abaixo mostra a hierarquia da herança entre essas classes:

System.Security.Claims é um novo namespace que foi adicionado ao .NET Framework, com a finalidade de agrupar os tipos disponíveis para realizar o trabalho via claims. Abaixo temos um exemplo de como podemos fazer o uso de claims em aplicações que utilizam, por exemplo, um modelo de autenticação customizado:

using System;
using System.Security.Claims;
using System.Security.Principal;

namespace App
{
class Program
{
static void Main(string[] args)
{
var principal =
new GenericPrincipal(new GenericIdentity(“Israel Aece”), new [] { “Admin”, “IT” });

foreach (var item in principal.Claims)
Console.WriteLine(“{0}: {1}”, item.Type, item.Value);
}
}
}