Autorização por token na WebApi

Hoje aprendi: Algumas alternativas com autorização por token na WebApi

O André Baltieri escreveu um artigo simples e bacana com a proposta de demonstrar como configurar uma WebAPI usando Bearer Authentication. Eu costumo usar esse artigo para pegar os pacotes que preciso instalar em um novo projeto WebApi que necessite de autorização via token. Enfim, no que refere-se a geração e utilização do token, entendo observo 4 abordagens. São elas:
  1. Sem nenhum tipo de restrição aos endpoints.
  2. Autorização com geração de token por usuário e senha.
  3. Autorização com geração de token por um "código de cliente"
  4. Autorização controlada por CORS.
1) Não preciso falar nada sobre a primeira abordagem, é basicamente um repositório de operações acessíveis por qualquer requisição, sem restrições. Exemplo: API de consulta de endereço por CEP.

2) A segunda possibilidade seria gerar um token através de um usuário e senha. Exemplo: Etapas de login em aplicativo móvel. Faço uma requisição de um token passando o usuário e senha que o usuário informou, se esses forem validos, gero um token que permite acesso a todos os métodos restritos da API para o aplicativo.

3) A terceira é bem parecida com a segunda, porém o cliente que está utilizando a API, não possui usuário e senha, por talvez não ter uma etapa de login, mas mesmo assim, quero garantir que apenas esse cliente vai usar minha API. Então eu gero um hash qualquer, coloco em algum lugar da aplicação (pode ser no arquivo de configuração) e quando o cliente solicitar o token, ao invés de pegar o usuário e senha, vou pegar o código do cliente (clientId usando a proposta no artigo do André Baltieri) e verificar no meu arquivo de configuração se o hash que estou recebendo no header é igual aos hashs que configurei para ter acesso. Caso o hash tenha acesso, ofereço o token e novamente os métodos restritos terão acesso quando a requisição possuir o token gerado no header.

4) A quarta possibilidade é bem simples também. Caso eu crie um API que será usada pelo domínio xpto.com.br, então basta configurar na própria API para permitir apenas esse domínio. Quando a restrição não é por domínio, geralmente usamos "*" para indicar que qualquer domínio pode ter acesso (e tratamos as restrições com as abordagens 2 e 3 mencionadas acima).


Certo, agora vem a pergunta: Não bastaria eu apenas verificar o usuário e senha ou no caso do código de cliente, comparar o que estou recebendo em cada requisição com o que está no meu arquivo de configuração ao invés de ter de gerar um token ?
A resposta: NÃO. Mas porque ???? :'(

É simples. Se o aplicativo ou site que vai usar minha API recebe um usuário e senha ou um código de cliente, significa que apenas ele deve possuir essa informação. Então, se eu passar esses dados em todas as requisições, ou pior, se esses dados são enviados por javascript por exemplo, estaremos entregando o código do cliente (hash) ou o usuário e senha para qualquer um que seja um pouco curioso (se é um site chamando uma operação via ajax, usando javascript, bastaria usar as ferramentas de desenvolvedor do browser e pronto, teriam acesso para usar a API). Agora, se eu entrego essas chaves, o site faz uma requisição do token (não faça isso via javascript, por favor, fatalmente você irá entregar seus dados. Faça isso no server) e obrigo a geração de token, eu garanto que todas as demais requisições serão autorizadas, e ainda manteremos os dados de usuário e senha ou código de cliente (hash) seguros mesmo quando usado em requisições do tipo GET, ou via javascript (por exemplo), pois o token é gerado de tempo em tempo, sempre muda. 

Vale lembrar que o token é configurado para expirar, então é importante sempre expirar o token pois se alguém, de alguma forma pegar esse token, ele não terá tempo de fazer alguma coisa com ele.

Enfim, é isso :)