Cell CMS — Autenticando o Admin
Tags: csharp, azureactivedirectory, authentication, azure
Published: 2020-06-24 23:58:24

---
title: Cell CMS — Autenticando o Admin
published: true
date: 2020-03-17 14:46:02 UTC
tags: csharp,azureactivedirectory,authentication,azure
canonical_url: 
series: CellCms
---

### Cell CMS — Autenticando o Admin

![](https://cdn-images-1.medium.com/max/1024/0*hLL9R9ogrmbyECPY)<figcaption>Photo by <a href="https://unsplash.com/@chrispanas?utm_source=medium&amp;utm_medium=referral">chris panas</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption>

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](https://github.com/rodolphocastro/cell-cms). 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](https://portal.azure.com) e busque por “_Azure Active Directory_” na busca de recursos:

![](https://cdn-images-1.medium.com/max/989/1*0M9pcBZi2qSCNDqoBq5ziQ.png)<figcaption>Buscando pelo Azure AD</figcaption>

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

![](https://cdn-images-1.medium.com/max/802/1*S2YV4Kr_AR9FXbe-rk-K1g.png)<figcaption>Blade do Azure Active Directory</figcaption>

**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**.

![](https://cdn-images-1.medium.com/max/858/1*V3QYdXnkOhyYDcA7x2VJlg.png)<figcaption>Criando a aplicação</figcaption>

> A URL [**https://localhost:5001/oauth2-redirect.html**](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](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app))

- **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.

![](https://cdn-images-1.medium.com/max/770/1*reIwI8GFrUdhQnZkTbKyhA.png)<figcaption>Encontrando o ClientId e o TenantId</figcaption>

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.

![](https://cdn-images-1.medium.com/max/757/1*RmNlIm55hEBD1JDxB-b54g.png)<figcaption>Endpoints para anotar!</figcaption>

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:**

![](https://cdn-images-1.medium.com/max/555/1*vT7YkcZyp0op7szgfd323A.png)<figcaption>Habilitando o Implict Grant</figcaption>

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

![](https://cdn-images-1.medium.com/max/764/1*QKukP8o8jjbHQkZjwxI-WQ.png)<figcaption>No meu print a application Id está definida, para você ficará disponível para criar uma nova</figcaption>

![](https://cdn-images-1.medium.com/max/575/1*9YsGmBz7boR7mXmA4HfmRQ.png)<figcaption>Criando o scope para o nosso SwaggerUi</figcaption>

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** ”:

![](https://cdn-images-1.medium.com/max/918/1*gIVS24qu3RkebPFvDBrzRA.png)

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

![](https://cdn-images-1.medium.com/max/427/1*XojD-2UPs8O8q5GiqUIGIg.png)<figcaption>Anote aquela “url” api://… precisaremos dela futuramente!</figcaption>

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:

{% gist https://gist.github.com/rodolphocastro/1c36cc006bdf601070d4ad82de9df66d %}

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_

{% gist https://gist.github.com/rodolphocastro/01f4b9a8bb4228aa4f01d05ca2aa2516 %}

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:

![](https://cdn-images-1.medium.com/max/319/1*lIuBz9ihq5Jx1H_4cr_5UA.png)

![](https://cdn-images-1.medium.com/max/426/1*DH3ZdBMesdwOX7-dV8_IrQ.png)<figcaption>Note que só adicionamos o valor que não colocamos no appsettings!</figcaption>

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**

{% gist https://gist.github.com/rodolphocastro/847c14e4871fee45db4fddf09169baa6 %}

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:

{% gist https://gist.github.com/rodolphocastro/cffd3bdbe1d4f2bebe1667fca58c1d4d %}

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:

![](https://cdn-images-1.medium.com/max/1024/1*W9fccEgcdEo-GfcDF1tjDg.png)

Conseguirá fazer login através do **Authorize** :

![](https://cdn-images-1.medium.com/max/666/1*MJYl3dSp3j0TIY-N1eRsIA.png)

E, finalmente, conseguirá chamar o endpoint protegido:

![](https://cdn-images-1.medium.com/max/1024/1*i0SMSMnNCkUf5tScWDMCXA.png)<figcaption>Note que no Curl o nosso token fica exposto, podemos copia-lo e joga-lo em um <a href="https://jwt.io">https://jwt.io</a> para ver suas propriedades!</figcaption>

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](https://github.com/rodolphocastro/cell-cms/commit/885280dbeb881988c46914a39a735d595dfccf35). Obrigado por ler meu post e abraços!