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.
Olá, parabéns pelos artigos.
Tenho uma dúvida: eu consigo utilizar esse recurso em um projeto asp.net mvc?
Gostaria de deixar a autenticação em uma API e verificar nos controllers do projeto mvc se o usuário está autenticado ou não.
Obrigado.
Boas Murilo, sim é possível delegar a autenticação do usuário para uma outra aplicação (STS).
Olá Israel, pode me enviar um exemplo de como fazer essa autenticação?
Hoje eu faço dessa forma a autenticação:
var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var ctx = HttpContext.Current.Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(id);
Gostaria de saber se tem como só adicionar o token gerador pelo webapi nesse código.
Obrigado pela atenção.
Boas Murilo,
Seria isso: https://israelaece.com/2015/09/29/emiss-o-de-tokens-no-asp-net-web-api/ ?
Já tentou dar uma olhada no IdentityServer4?