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.

Features do Identity Server

Features do Identity Server

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:

Servidor IdentityServer4 configurado

Servidor IdentityServer4 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.

servidor identityserver4 rodando

servidor identityserver4 rodando

Cliente MVC

Cliente MVC

cliente mvc redirecionando para identityserver4 para login

cliente mvc redirecionando para identityserver4 para login

servidor identityserver4 exibindo tela de consent após login

servidor identityserver4 exibindo tela de consent após login

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.