Em um mundo mais conectado, com cada vez mais aplicações sendo feitas para atender pequenas partes de um negócio muito maior, é cada vez mais comum que estas aplicações precisem estar conectadas entre si, e que essa conexão seja simples e também transparente. Nem sempre uma mesma empresa vai ter todas as suas aplicações feitas com uma mesma tecnologia, é comum que uma aplicação seja feita em WordPress, outra seja uma aplicação móvel feita com Cordova, outra em Xamarin, uma aplicação Windows Forms e outras em ASP.NET. Como conectar todas estas aplicações de maneira segura e simples? Como fazer algo que me permita autenticar com quaisquer formas necessárias como AD, Facebook, Google, Github, etc?
O IdentityServer4
IdentityServer4 é um framework .NET feito com base no OpenID Connect, garantindo que diferentes aplicações, em diferentes tecnologias, possam fazer uso do servidor de identidade rodando o IdentityServer. Com ele é possível oferecer informações de identidade através de OAuth, oferecer segurança para APIs, autenticação de aplicações móveis, e muito mais.
Tudo isso alinhado a um incrível poder de customização, fazem com que a utilização do IdentityServer seja a escolha perfeita para os cenários onde é necessária uma tecnologia do tipo.
Instalando o IdentityServer4
Sendo um framework, o IdentityServer4 é colocado dentro de nossas aplicações, que podem ser aplicações específicas para rodarem o servidor, ou podem ser aplicações que além de ter um servidor com IdentityServer, também servem à outros propósitos.
Com o IdentityServer podemos configurar nosso próprio mecanismo de autenticação, por exemplo verificando email e password no banco de dados. Mas também é possível plugar provedores externos como Facebook, Github, Google. Ou ainda conectar em um Active Directory no Azure, etc. Tudo isso através de Oauth. Desta forma qualquer aplicação que saiba se conectar Oauth poderá usar o seu servidor de autenticação – sem reinventar a roda, sem ter que implementar um servidor para isso, bastante apenas alguns pacotes Nuget.
Aqui vamos criar um projeto para demonstração da instalação do IdentityServer. Para que as coisas fiquem mais simples, vou criar 2 projetos – um será o servidor IdentityServer e o outro será um cliente MVC comum. O código fonte de ambos os projetos está no github: https://github.com/vquaiato/identityserver4-samples
Startup projeto Server:
public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddDeveloperIdentityServer() .AddInMemoryClients(Config.GetClients()) .AddInMemoryScopes(Config.GetScopes()); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); app.UseStaticFiles(); app.UseDeveloperExceptionPage(); app.UseIdentityServer(); app.UseMvcWithDefaultRoute(); } }
Esta é basicamente a configuração de nosso servidor IdentityServer. Esta é uma configuração para testes e desenvolvimento, mas no geral é bastante simples assim. O que estamos fazendo aqui é definindo alguns clientes em memória, adicionando alguns scopes (também em memória) e depois dizendo para nossa aplicação utilizar o IdentityServer. Se executarmos essa aplicação nada muito interessante vai aparecer na tela, no entanto podemos navegar para: http://localhost:5001/.well-known/openid-configuration veremos que nosso servidor está configurado:
Eu omiti a criação estática dos clientes e scopes, isso pode ser visualizado aqui: https://github.com/vquaiato/identityserver4-samples/blob/master/post1-setupis4/src/Server/Config.cs#L17
Configurando aplicação cliente para conectar no IdentityServer4
Nossa aplicação cliente será uma aplicação web ASP.NET MVC. Vamos precisar fazer algumas configurações, segue aqui o startup:
public class Startup { /*omitidos os métodos padrão */ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseStaticFiles(); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationScheme = "cookies", AutomaticAuthenticate = true }); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions { AuthenticationScheme = "oidc", SignInScheme = "cookies", Authority = "http://localhost:5001/", RequireHttpsMetadata = false, ClientId = "mvc", PostLogoutRedirectUri = "http://localhost:5000/", ResponseType = "id_token", Scope = { "openid", "profile" }, SaveTokens = true, }); app.UseMvcWithDefaultRoute(); } }
O ponto importante aqui é a definição de cookie de autenticação app.UseCookieAuthentication
e a na configuração do OpenId Authentication app.UseOpenIdConnectAuthentication
, é esta configuração que diz para nossa aplicação utilizar o IdentityServer4 no parâmetro Authority
(que está rodando na porta 5001) como nosso servidor de autenticação. Informamos alguns valores obrigatórios como o ClientId
, Scopes
, ResponseType
.
Além disso eu configurei uma action com o atributo Authorize
do ASP.NET, para que a aplicação saiba que é necessário solicitar um usuário autenticado.
Executando as aplicações
Ao executarmos as duas aplicações, e navegarmos para a action restrita (aquela que tem o atributo Authorize
) veremos que um erro 404 ocorre no nosso servidor IdentityServer4. Isso acontece por que não temos nenhuma view (nem controllers) de autenticação configurada nele, então o ASP.NET simplesmente retorna 404. Para resolver isso vamos utilizar um instalador do próprio time do IdentityServer4. Isso fará o download de controllers, viewmodels e algumas views necessárias para que o nosso servidor IdentityServer4 consiga apresentar as telas de login, consent, recuperação de senha, etc.
Abra um terminal Powershell e entre no diretório da aplicação Server, então execute:
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/dev/get.ps1'))
Feito isso você terá um servidor IDentityServer4 Configurado e pronto para seus testes locais.
Resumo
Primeiro: se você não conseguiu entender algo: por favor, pergunte nos comentários. Estou há muitos meses trabalhando com o IdentityServer3 e IdentityServer4, e possivelmente posso ajudá-lo 😉
Como podemos ver o IdentityServer é uma ferramenta bastante versátil e poderosa. Por ser um framework permite um elevadíssimo nível de customização, que com certeza atende às necessidades da maioria das aplicações, e com ele conseguimos autenticação unificada para diversos tipos de aplicativos, como se nossa aplicação fosse uma espécie de Facebook, com Oauth, sem ter que reimplementar tudo novamente.
Consulte o código completo aqui no github, assim você pode verificar tudo que foi feito, instalado e configurado https://github.com/vquaiato/identityserver4-samples.
Veremos nos posts futuros como integrar o IdentityServer com aplicações backend para a criação de clients, users, profiles, como customizar o processo de login, proteger APIs, como obter tokens de acesso, e muito mais. Veremos um pouco mais a fundo o que significam algumas das coisas que apareceram neste post mas que ainda não entendemos direito.
Link documentação IdentityServer4 https://identityserver4.readthedocs.io/en/dev/index.html
Se você precisa construir APIs, restringir ou liberar seu acesso com base em perfis, clientes e coisas do tipo, o IdentityServer pode te ajudar muito. Aqui na Lambda3 temos projetos entregues usando essa tecnologia e podemos auxiliar sua equipe e projeto.
Vinicius Quaiato