Cell CMS — Autenticando o Admin

Rodolpho Alves
6 min readMar 17, 2020

--

Photo by chris panas on Unsplash

Uma vez, durante um projeto, levei o maior esporro de um amigo por jogar para sprints tardios a parte de autenticação. Ele dizia que:

“Fazer isso é jogar algo de muito valor para o usuário pro canto, vai gerar a maior dor de cabeça para amarrar todos os Models, Services e Rotinas. Isso deveria ter sido uma das primeiras coisas a serem entregues!”

Ele estava tremendamente certo! Eu, de fato, adiava a parte de autenticação pois era, na época, era receoso com fazer a implementação disso do zero. Lição aprendida arduamente, agora todo projeto já começo pensando em como irei autenticar e autorizar os usuários.

Antes de começarmos o post de hoje, deixo aqui o link para o código fonte. Não colocarei todos os refactors e ajustes nos posts, porém tentarei manter todos os commits atômicos, para que seja prático consultar exatamente o que foi feito entre cada feature/post!

Vamos começar preparando o nosso Tenant no Azure. Caso você não tenha uma conta no Azure crie-a (existem até promoções para novas contas, como créditos extras ou até mais funcionalidades gratuítas). O Recurso que vamos utilizar é gratuíto para o uso simples, apenas se quisermos algumas funcionalidade “empresariais” que teriamos de realizar um upgrade para versões pagas.

Criada a sua conta, acesse https://portal.azure.com e busque por “Azure Active Directory” na busca de recursos:

Buscando pelo Azure AD

Dentro do blade do Azure AD procure por “App registrations”, entre nela e clique em “New registration”:

Blade do Azure Active Directory

Escolha um nome para sua aplicação (no nosso caso “Cell CMS”), que tipo de contas podem utilizar sua aplicação e adicione a URL “https://localhost:5001/oauth2-redirect.html” como uma Web Redirect URI.

Criando a aplicação

A URL https://localhost:5001/oauth2-redirect.html é o padrão do Swashbuckle.AspnetCore.SwaggerUi. Ela pode ser alterada, via código, porém costumamos utilizar ela em seu valor default

Uma breve explicação sobre os tipos de contas (maiores detalhes podem ser encontrados na documentação)

  • Accounts in this organizational directory only: O nível mais restrito, apenas pessoas que já estiverem cadastradas em nosso Azure poderão fazer login no nosso app
  • Accounts in any organizational directory: O nível intermediária, apenas pessoas com contas de trabalho ou educacionais poderão utilizar o App. Por exemplo uma pessoa com a conta aluno@universidade.onmicrosoft.com poderia fazer login no nosso app.
  • Accounts in any organizational directory and personal Microsoft Accounts: O nível mais amplo, todos os tipos de contas da Microsoft (pessoais, empresariais, educacionais, xbox, skype, etc etc etc) poderão fazer login no nosso app.

Criado o app anote os seguintes valores que são exibidos na tela, os utilizaremos mais tarde:

  • Application (client) id: É um ID que identifica nosso app, será utilizado para identificar “quem” está pedindo autenticação no Azure AD
  • Directory (tenant) id: É um ID que identifica nosso tenant (ou seja, nosso Azure AD), poderemos utilizar este no futuro para diferenciar tenants.
Encontrando o ClientId e o TenantId

Em seguida, clique em “Endpoints” e anote os seguintes endpoints:

  • OAuth 2.0 Authorization endpoint (v2): É o endpoint que vai permitir que os usuários do Azure AD “autorizem” nosso app a ver quem eles são
  • OAuth 2.0 token endpoints (v2): É o endpoint que vai emitir tokens, desde que autorizados pelo usuário, que identificam o usuário do Azure AD
  • OpenID Connect metadata document: É um json que possui todas as configurações necessárias para clients (por exemplo nosso futuro frontend) saberem “conversar” com o Azure AD.
Endpoints para anotar!

Agora precisamos habilitar o Implicit Flow para que o SwaggerUI e o nosso futuro frontend possam utilizar este fluxo de autenticação. Futuramente farei um post explicando cada fluxo em detalhes, por hora acesse a aba “Authentication” e habilite os dois checks para o Implicit Grant:

Habilitando o Implict Grant

Finalmente, vamos à aba Expose an API, defina um applicationId para a sua API e crie um novo Scope, conforme:

No meu print a application Id está definida, para você ficará disponível para criar uma nova
Criando o scope para o nosso SwaggerUi

A ideia aqui é criar um Scope que permitirá que apenas alguns usuários possam utilizar nosso SwaggerUi. Criado o Scope, navegue à aba “Api Permissions” e escolha a opção “Add a Permission”, aba “My APIs” e selecione “Cell CMS”:

Agora selecione o Scope que criamos anteriormente e clique em Add Permissions:

Anote aquela “url” api://… precisaremos dela futuramente!

Vamos voltar à api! Para quem quiser acompanhar direto pelos commits é só procurar os commits relacionadas ao branch feature/azure-ad-auth.

Nossa primeira preocupação vai ser trazer, para a API, as configurações! Lembram os campos que anotamos? Precisamos deles na API. Para isso, vamos criar uma interface IAzureAdSettings que será implementada pela classe AzureAdSettings:

A constante SettingsKey está ali para facilitar nossa vida ao buscar estes dados na IConfiguration do DotNet Core. Vamos editar nosso appsettings.json para armazenar estes valores. Substitua apenas o valor para o ClientId pelo criado em seu Azure Active Directory

Observe a falta do ClientId.

Para definirmos o ClientId de maneira mais segura, clique com o botão direito no projeto da API e escolha Manage User Settings, alterando o json que ele abrir no Visual Studio para conter o AzureAd__ClientId:

Note que só adicionamos o valor que não colocamos no appsettings!

Finalizado nossos preparativos, vamos utilizar estas configurações! Vamos adicionar, já, um novo NuGet que precisaremos para lidar com JWT: Microsoft.AspNetCore.Authentication.JwtBearer. Adicionado o NuGet, vamos voltar ao Startup.cs e planejar nossas alterações:

  1. Precisamos buscar as Configurações do Azure AD através do nosso IConfiguration
  2. Com estas configurações vamos adicionar e configurar os serviços de autenticação
  3. Vamos, finalmente, utilizar o Middleware de autenticação

Agora precisamos informar ao Swagger.json que nossa API suporta autenticação e configurar para que o SwaggerUI consiga realizar a autenticação em nosso nome. Para atingir nosso objetivo vamos:

  1. Criar um filtro para que o Swashbuckle.Swagger saiba quais endpoints requerem autenticação
  2. Aplicar este filtro na geração do Swagger.json
  3. Definir, na API, os Scopes que configuramos para a aplicação
  4. Adicionar à geração do Swagger.json informações sobre nossos endpoints de autenticação
  5. Adicionar ao SwaggerUi o ClientId

O código abaixo já está considerando um refactor que realizei no branch feature/refactor-swagger-config, que move a configuração do Swagger para Extension Methods, deixando nosso Startup.cs mais limpo:

Finalmente, para testarmos toda essa configuração, vamos ao WeatherForecastController adicionar o attribute [Authorize] ao método Get(). Feito isso, basta executar sua API, você será recepcionado pelo seguinte SwaggerUi:

Conseguirá fazer login através do Authorize:

E, finalmente, conseguirá chamar o endpoint protegido:

Note que no Curl o nosso token fica exposto, podemos copia-lo e joga-lo em um https://jwt.io para ver suas propriedades!

Finalizaremos por aqui este post! No próximo post partiremos para a implementação inicial da Pesistência, utilizando EntityFrameworkCore e Sqlite! Caso queria ver o resultado final no GitHub basta acessar este merge commit. Obrigado por ler meu post e abraços!

--

--

Rodolpho Alves

Brazilian, solution architect, tech enthusiast, always looking forward to improve myself, my projects and OSS. Find me on https://github.com/rodolphocastro