Após a versão 3 do .NET Core, houve diversos breaking changes. Muitos deles relacionados a Autenticação e Autorização. Veja abaixo como criar uma API ASP.NET Core 3.1. E proteger a API com tokens JWT emitidos através de um SSO IdentityServer4.

Framework OAuth2

O OAuth 2.0 é um framework de autorização. Dá recursos aos usuários para autorizar o acesso de aplicativos de terceiros (Clients). O aplicativo terceiro, pode ser tanto um app da sua própria empresa, como de outra empresa.

Quando autorizado, o aplicativo recebe um Bearer token. Atualmente o formato de Bearer mais utilizado é o JWT. Que serve como credencial de autenticação.

Isso tem dois principais benefícios de segurança:

  1. O aplicativo não precisa armazenar o nome de usuário e a senha do usuário.
  2. O OAuth2 provê recursos para restringir o escopo desse Bearer, por exemplo: acesso somente leitura.

Esses benefícios são particularmente importantes para garantir a segurança dos aplicativos na Web, tornando o OAuth 2 padrão predominante para autenticação de API.

O Fluxo

O OAuth 2.0 especifica o seguinte fluxo para válidar um Token Bearer emitido por um Auth Server :

  1. API irá receber um Bearer token através do Header Authorization
  2. A API inicialmente faz validações locais básicas no Bearer enviado.
  3. Em seguida busca as chaves públicas especificadas no endpoint jwks_uri.
  4. A API válida se a assinatura do Token é válida. Se estiver, a requisição é atendida.

SHOW ME THE CODE

Para fazer este demo será necessário:

  • ASP.NET Core 3.1
  • Docker
  • JP Project 3.1
  • Visual Studio 2019
  • Postman

Crie um novo projeto ASP.NET Core Web Application (File > New Project). Coloque o nome de SecureApi. Na tela seguinte escolha a opção Web Application (Model-View-Controller), conforme figuras abaixo:

novo-projeto
2
3

Agora pressione o botão direito no projeto e em seguida vá até a opção Manage Nuget Packages. Procure por IdentityServer4.AccessTokenValidation e instale o pacote.

Assim que terminar a instalação, abra o arquivo Startup.cs, e faça as seguintes alterações:

A configuração acima define as informações do SSO em AddIdentityServerAuthentication e também especifica que a API usará um Bearer token para validar as chamadas em AddAuthentication.

Pronto! Isso é tudo pe pe pessoal... Sua api ASP.NET Core 3.1 está integrada com um servidor OAuth 2.0.

Continue aqui no Tutorial

Claro, que se você estivesse num ambiente aonde já há um server OAuth2, você já teria feito a integração.

Esse demo será mais completo. Será feito a configuração do SSO.

Testando

Para fazer o teste, primeiro altere o arquivo WeatherForecastController.cs adicionando o atributo Authorize


    [Route("[controller]"), Authorize]
    public class WeatherForecastController : ControllerBase

Por fim, abra o arquivo launchSettings.json e troque a porta da SecureApi para 5020


    "SecureApi": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5020", // <-- Port
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }

Essa configuração protegeu uma rota e a porta 5000 foi alterada, pois será utilizada pelo SSO.

SSO

Para este demo iremos utilizar a versão SSO do JPProject. Para isso faça download do arquivo jpproject-docker.zip e descompacte em alguma pasta. Vá até essa pasta e execute o arquivo docker-run.bat.

Esse é um processo que pode levar até uns 5 minutos. Irá fazer o download das imagens, configurar o banco de dados e o SSO.

API

Após configurar o SSO é configurar a API, para que funcione a integração. Abra o painel admin no endereço http://localhost:4300, faça login e vá em Protected Resources > Add

Campo Valor
Name report-api
Display Name Report api demo
Description Demo securing an api

config

Clique em Save, assim que salvar vai abrir a lista de todas Api's. Abra a API que criamos acima. Clique no botão Api Secrets. Em Secret Type selecione a primeira opção > Shared Secret. Em secret value preencha console-secret. Clique em save.

secret

Configurar Client API

Se você chamar a URL http://localhost:5020/weatherforecast vai receber um erro 401 (Unauthorized).

Isso ocorre, pois agora é necessário enviar um Bearer token para a API. Esse token só pode ser emitido pelo servidor de autorização (SSO). E ele só é emitido através do intermédio de um client.

Identity Server 4

Para configurar um client para o postman. Abra o painel admin no endereço http://localhost:4300. Vá em Clients > Add.

Campo Valor
ClientId postman
Name Postman
Description Postman client
Client Uri
Logout Uri
Logo Uri (Https) https://assets.getpostman.com/common-share/postman-logo-horizontal-white.svg

Selecione a opção Server Resource Owner Password & Client Credentials flow. Clique em salvar. Em seguida vá em Settings > Client Secrets. Selecione o secret type como Shared Secret e o valor postman-secret.

postman

Salve, em seguida clique em Cancel ou Back. Vá em Settings e adicione o Scope report-api.

Testando Postman

No visual studio rode o projeto que criamos no primeiro passo. Não esqueça de alterar para o Kestrel:

secureapi

Abra o postman e vá até Create New > Request.

O nome da Request é Gerar Token. Crie uma collection chamada SSO Tests ou adicione em uma já criada.

Assim que abrir a request, aponte o endereço para http://localhost:5001/connect/token e altere para POST. Em Body selecione x-www-form-urlencoded. Selecione ao lado direito Bulk Edit e copie o seguinte conteúdo:

grant_type:client_credentials
client_id:postman
client_secret:postman-secret
scope:report-api

Esse é o body para gerar um access_token para um grant_type client_credentials.

O resultado será algo semelhante com este:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmOWU0Y2I0MDkxNzU2OTg2MWEzZGExOTE2YzYxM2I4IiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1NzYwMjI4MDAsImV4cCI6MTU3NjAyNjQwMCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAxIiwiYXVkIjoicmVwb3J0LWFwaSIsImNsaWVudF9pZCI6InBvc3RtYW4iLCJzY29wZSI6WyJyZXBvcnQtYXBpIl19.he2IGN0tsKTC-YoB8ogVy83-lK6e3ZN-M8zg--xeny-XLni--NvsRB6yNPRz0B1g2amlFKVbD9DcwAQFrQeQ5Uhcms5e-ExcE019Vl-31YTe3_oX8NAJH7HXReJ0fomHdGEs7Z_XHhllVYUJd3qsJfJ909iWS-JGy7c0HP2S6gscvT3WBytR6Mkp-aaajYDIZsqxTAj1XH2-zGiDaMULrIEflrXSa-ROTVVo4_moIkNeMxUCV9flPndz7w8272IWwfhZsHpcvPfZVgV-pA5qlyYZLzrQA2c3UzX3gc9a8qwFYhm9Nq3MaKgRWtEbRRBaZNeVBgkpFcm208OlvExPkw",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "report-api"
}

Adicione uma nova Request, será um GET na URL http://localhost:5020/weatherforecast. Na aba Authorization selecione o TYPE OAuth 2.0. No campo ao lado direito, copie e cole o access_token que você gerou na requisição anterior.

E clique em Send.

Pronto.

Revisando

A API que criamos está configurado para receber tokens Bearer. Toda vez que uma rota estiver marcada com [Authorize] a API sabe que haverá um Bearer token no Header Authorization. A API inicialmente faz validações básicas nesse Bearer. Após isso busca as chaves públicas no endpoint jwks_uri. Validando a assinatura do Token.

Se tudo estiver válido, a requisição é atendida.

Download

O código do projeto está disponível no meu GitHub

Conclusão

Apesar dos conceitos e do "trabalho" para montar o ambiente de testes. No dia a dia, quando um Auth Server já está configurado, o processo é bem simples.

Espero que tenham aprendido um pouco mais sobre OAuth 2.0.

Deixem os comentários!