• Skip to content
  • Skip to primary sidebar
  • Skip to footer

R Andrade

Blog do Paulo Roberto - Desenvolvimento e arquitetura

Tokens de acesso: Primeiro passo para proteger WebApis

24 de junho de 2016 by Paulo Roberto Ramos de Andrade 11 Comments

Olá pessoal! Tudo bem? Depois de um pequeno debate sobre as vantagens teóricas de usarmos novas formas de autenticação com WebApis, vamos colocar a mão na massa. Neste artigo, vamos elencar as vantagens práticas de usar tokens de acesso e implementar uma WebApi que precisa de tokens de acesso para acessar recursos.

Todo o código fonte usado neste artigo está disponível no GitHub, fique a vontade para baixá-lo e estudá-lo.

Dentro os vários benefícios, eu destaco:

  • Baixíssimo acoplamento: Toda a lógica de autenticação estará na WebApi. Qualquer sistema que acesse seu back-end só precisa saber onde obter os tokens de acesso e como repassá-los para autorizar o usuário.

  • Baixo trânsito de informações: Todas as informações referentes ao usuário ficam no token. Se um usuário tem alguma classificação interna, ela está guardada no token de acesso. As informações ficam criptografadas e apenas a WebApi entende que informações adicionais são estas.

  • Não depende de cookies: WebApis com tokens são perfeitas para apps mobile, que podem guardar os tokens de acesso de ouras formas. Logicamente, sites que acessam estas WebApis podem usar cookies para guardar o token.

  • Prazo de validade bem definido: Se você configura o token para durar 60 minutos, ele totalmente a validade depois de 60 minutos. Não é possível usar um token vencido, que se torna completamente inútil.

  • Independe de como as informações serão validadas: Não importa se você tem um banco de dados, precisa acessar outra API para saber se o usuário é válido ou usa contas de usuário do Windows. A emissão de tokens de acesso independe da tecnologia de validação dos dados.

Atenção: A WebApi não pode ter nenhuma forma de autenticação atrelada a ela – é a tecnologia de tokens de acesso que fará este trabalho.

Adicionar o recurso de tokens de acesso numa WebApi não é exatamente complexo, mas você precisa primeiramente fazer dois procedimentos, já descritos aqui no blog:

  • Transformar a WebApi numa OWIN Application

  • Ativar o Cors na WebApi

Ambos os passos são necessários porque as bibliotecas de tokens de acesso rodam em aplicações OWIN e os endereços da WebApi agora serão acessados por outros serviços, em outros servidores – por isso a aplicação OWIN precisa ter suporte ao Cors.

Depois de seguir ambos os artigos, seu projeto WebApi deve ter estes três pacotes instalados:

Install-Package Microsoft.AspNet.WebApi.Owin
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.Owin.Cors

Vamos dar uma olhada na classe Startup depois de seguir os procedimentos de ambos os artigos.

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

        // configurando rotas
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        // ativando cors
        app.UseCors(CorsOptions.AllowAll);

        // ativando configuração WebApi
        app.UseWebApi(config);
    }
}

Como você pode ver, temos uma Owin Application devidamente configurada e com o Cors configurado para as páginas. Vamos então ativar o acesso usando tokens. Clique com o botão direito do mouse no projeto e escolha Manage NuGet Packages….

O pacote que precisamos instalar é o Microsoft.Owin.Security.OAuth.

Após a instalação, voltemos à classe Startup. Imediatamente antes de ativar de fato a OWIN Application com a configuração de WebApi, adicionemos a função AtivandoAccessToken, que recebe como padrão a variável app.

Obviamente precisamos criar o método – neste caso, logo abaixo de Configuration.

Neste método, vamos configurar e ativar o uso de tokens de acesso. Em primeiro lugar, vamos criar uma variável do tipo OAuthAuthorizationServerOptions, que, como o nome indica, agrupa as opções de configuração do fornecimento de tokens de acesso.

Mais ou menos assim:

var opcoesConfiguracaoToken = new OAuthAuthorizationServerOptions()
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromHours(1)
};

O que estamos configurando com isso:

  • Permitindo acesso ao endereço de fornecimento do token de acesso sem precisar de HTTPS (AllowInsecureHttp). Obviamente, num ambiente de produção, o valor deve ser false.

  • Configurando o endereço do fornecimento do token de acesso (TokenEndpointPath).

  • Configurando por quanto tempo um token de acesso já forncedido valerá (AccessTokenExpireTimeSpan).

Neste caso, o token fornecido valerá por duas horas e o endereço é servidor/token – esta é a parte que configuramos.

Vamos agora ativar o uso de tokens no projeto. Logo abaixo, vamos colocar este código:

app.UseOAuthAuthorizationServer(opcoesConfiguracaoToken);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

Estas duas linhas ativam o fornecimento de tokens de acesso numa WebApi. Mas percebeu que estamos esquecendo o principal? Como verificar usuário e senha para fornecer tokens de acesso? Precisamos configurar o Provider dos tokens. De volta à configuração, vamos adicionar o Provider:

var opcoesConfiguracaoToken = new OAuthAuthorizationServerOptions()
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
    Provider = new ProviderDeTokensDeAcesso()
};

Note que uma instância da classe ProviderDeTokensDeAcesso é o nosso Provider. Com isso, terminamos de configurar o uso de tokens de acesso dentro de Startup.

Agora precisamos criar a classe ProviderDeTokensDeAcesso, lembra? É ela que verifica se as informações do usuário e senha são válidas para fornecer um token de acesso. Crie a classe normalmente – ela deve herdar de OAuthAuthorizationServerProvider

public class ProviderDeTokensDeAcesso : OAuthAuthorizationServerProvider
{
}

Dentro da classe ProviderDeTokesDeAcesso, precisamos primeiramente implementar o método ValidateClientAuthetication, que é responsável por fazer validações extras quando o usuário se autentica com o token de acesso.

public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
    context.Validated();
}

O outro método que deve ser implementado – GrantResourceOwnerCredentials – é o responsável por fornecer o token de acesso com base no usuário e senha.

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
}

E vale a pena parar aqui para uma observação. Como o foco deste artigo é o funcionamento dos tokens de acesso sem depender de como os usuários serão verificados, o projeto tem alguns usuários cravados diretamente no código, para fins de simplificação mesmo.

No caso, esta é a base de usuários usada no projeto:

public static class BaseUsuarios
{
    public static IEnumerable<Usuario> Usuarios()
    {
        return new List<Usuario>
        {
            new Usuario { Nome = "Fulano", Senha = "1234" },
            new Usuario { Nome = "Beltrano", Senha = "5678" },
            new Usuario { Nome = "Sicrano", Senha = "0912" }
        };
    }
}

Voltemos ao ProviderDeTokesDeAcesso. Chegou a hora de verificar usuário e senha. Percebeu que o método GrantResourceOwnerCredentials recebe um context como parâmetro? Dentro deste context estão as informações passadas pelo usuário. O que nos interessa são os parâmetros UserName e Password.

Neste caso, eu já estou fazendo uma consulta à ‘base de usuários’ e se nenhum usuário foi encontrado, já retorno com um erro.

var usuario = BaseUsuarios
    .Usuarios()
    .FirstOrDefault(x => x.Nome == context.UserName && x.Senha == context.Password);
if (usuario == null)
{
    context.SetError("invalid_grant", "Usuário não encontrado um senha incorreta.");
    return;
}

Agora chegou a hora de criar o token que identifica o usuário.

var identidadeUsuario = new ClaimsIdentity(context.Options.AuthenticationType);
context.Validated(identidadeUsuario);

Ao final, o token é gerado através do método context.Validated(). Veja a classe ProviderDeTokensDeAcesso com todo o código adicionado:



Agora, como testamos nossa WebApi com tokens de acesso? No caso, eu gosto de usar o PostMan, extensão do Google Chrome que permite testar webservices RESTFul.

Em primeiro lugar, como identificar um usuário? Faça uma requisição do tipo POST para o endereço que você configurou como endereço de fornecimento de tokens – no caso, servidor/token. No corpo (Body) da mensagem, você deve passar o nome do usuário (username), a senha (password) e o tipo de autorização (grant_type), que deve ser a constante password. Assim:

E o resultado é um arquivo Json com o token de acesso (access_token) e o prazo de validade em segundos (expires_in)!

Se você passar algum usuário inválido, receberá no Json de resposta exatamente a mensagem de erro configurada no código.

Voltemos à WebApi por um momento. Eu fiz um Controller com um método bem simples, cujo acesso se dá através do endereço servidor/api/teste – lembrando, eu não mexi nas rotas. Mas note que o método foi decorado com o atributo [Authorize]. Isso significa que ele exige alguma forma de autenticação do usuário – no nosso acesso, o token de acesso.

De volta ao Postman, se você tentar fazer uma requisição sem autorização ao recurso, receberá como resposta um Json com uma mensagem de recurso não autorizado, o que faz sentido.

Para se identificar, envie no cabeçalho (Headers) da requisição a chave Authorization e o token de acesso como valor, obrigatoriamente precedimento pela palavra Bearer – ou seja, Bearer token – e você viu como o token de acesso é grande! E agora o método é acessado normalmente!

Com isso, conseguimos implementar tokens de acesso em nova WebApi! Ela agora está mais segura e totalmente compatível com diferentes formas de acesso – aplicações desktop, aplicações mobile e websites. Até a próxima!

[]’s
Paulo Roberto

Filed Under: ASP.NET Web Api, Autenticação e Autorização, C#, Cors, JavaScript, Mobile, OWIN, Segurança, Todas as postagens Tagged With: .net, autenticação, autorização, c#, cors, mobile, owin, tokens, webapi

Publicidade

Primary Sidebar

Quem sou eu

Meu nome é Paulo Roberto e tenho 32 anos, com 12 anos de experiência na área. Sou desenvolvedor, autodidata, iniciante nas artes da arquitetura de softwares, eterno interessado em aprender mais técnicas e tecnologias e também interessado em documentar e repassar o pouco que já sei.

Acompanhe o blog nas redes sociais

  • Email
  • Facebook
  • Github
  • Linkedin
  • Twitter

Publicidade

O que foi mais lido no último mês

  • Apagando dados com SQLite, C# e sqlite-net-pcl
  • Convertendo tabelas HTML em arquivos Excel no Front End
  • Trabalhando com o simulador do iOS
  • Tokens de acesso: Primeiro passo para proteger WebApis

Categorias

Arquitetura de Sistemas ASP.NET MVC ASP.NET Web Api Autenticação e Autorização C# Cors Dicas e Truques Entity Framework JavaScript Mobile N Camadas OWIN Pessoal Segurança Sites que ajudam Softwares Todas as postagens Unit Testing Virtualização Xamarin Xaml

Footer

Pesquisar

Arquivo do blog

Copyright © 2019 · Magazine Pro on Genesis Framework · WordPress · Log in