DEV Community

Cover image for Autenticação e Autorização de uma ASP .NET Web API com Keycloak
Anastácio Gomes
Anastácio Gomes

Posted on

Autenticação e Autorização de uma ASP .NET Web API com Keycloak

Olá pessoal!

No meu primeiro artigo eu gostaria de falar um pouco sobre autenticação, autorização e como podemos realiza-los de uma maneira muito prática e performática utilizando Keycloak.

O que é autorização e autenticação?

Esses dois conceitos são utilizados frequentemente quando estamos falando de segurança de aplicações, mas se referem a aspectos distintos no gerenciamento de acesso a recursos.

  • Autenticação: É a verificação da identidade do usuário. O primeiro processo quando você tenta acessar alguma aplicação, e nesse processo, é verificado se você é realmente quem você diz quem é e se a aplicação o conhece. Usualmente é feito por algum tipo de "segredo", como uma senha, uma assinatura digital ou uma impressão digital.
  • Autorização : Após verificado a identidade do usuário com sucesso, e o usuário já se encontra dentro da aplicação, é necessário limitar quais recursos aquele usuário pode acessar ou não pode acessar. Aqui entra a autorização: é a definição de quais açoes, operaçoes ou recursos um usuário ou um grupo tem acesso.

Introdução ao Keycloak

De maneira sucinta, o Keycloak é um gerenciador de identidade e acesso open source, que adiciona autenticação a suas aplicações e evita a necessidade de armazenar ou autenticar usuários.
Entre suas principais funcionalidades, é interessante ser destacado que o keycloak:

  • Realiza SSO nas suas aplicações (Single-Sign-on)
  • Gerencia seus usuários
  • Gerencia funcionalidades por meio de UI interativa
  • Realiza isolamento de Tenants ( no Keycloak são os realms que achei super legal )
  • Reliza federação de usuários
  • Conta com provedores externos de identidade (como GitHub, Instagram, Facebook etc)
  • Possui diversos serviços de autenticação como OpenID, oAuth 2.0 e SAML 2.0.

Demonstração

Para demonstrar a facilidade de realizar a autenticação e autorização em uma aplicação, irei demonstrar passo a passo como podemos:
1) Iniciar o KeyCloak via Docker;
2) Criar um novo realm;
3) Criar usuários;
4) Criar uma web-api e configurar o Keycloak;
5) Testar endpoints protegidas
6) Criar grupos, roles e associar grupos, usuários e roles;
7) Testar novamente os endpoints;

  • Requisitos:
    • Docker
    • .NET 6.0
    • Postman ou Insomnia

Iniciando o Keycloak via Docker

  • Para esse passo, é necessário que você tenha o Docker instalado. Se não tiver, é só seguir o passo a passo na própria documentação (https://www.docker.com/get-started/)
  • Abra um terminal e digite o seguinte comando: ```bash

docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:22.0.1 start-dev

> Aqui, estamos expondo a porta 8080 e configurando as chaves de ambiente para acesso ao Console de Administrador e iniciando o Keycloak em modo de desenvolvimento com o start-dev.

Vamos para o console administrador via http://localhost:8080/admin/master/console/ e podemos acessar pelas credenciais cadastradas acima.

![img](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cdv0wscmhpwumo8qqne9.png)

## Criação de um novo Realm
Vamos realizar a criação de um novo realm para nossa aplicação
Clique no dropdown embaixo de KeyCloak e clique em Create Realm

![createrealm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mcmxoqoko9emnx852mue.png)
Dê um nome para o seu realm, no caso estarei nomeando o meu como **mordor**

![mordorrealm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9ebyhlv2seq5fr7pttz.png)
Feito isso, o realm já estará ativo e selecionado e podemos passar para o próximo passo.

## Criação de usuários.
Dentro do realm que acabamos de criar, podemos realizar a criação de usuários clicando em Users no painel lateral e depois em Add User


![users](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv9suxqfr0xphmjx8slr.png)

Irei criar inicialmente três usuários: Sam, Frodo e Sauron. Todos eles com apenas username e name.
Ao criar um usuário, precisamos definir a sua senha. Clique em um usuário e na aba Credentials, clique em Set Password e desmarque senha temporária apenas para testes.


![pass](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jm54ur423zsslx0z1qb9.png)

Feito isso, já temos nossos tres usuários criados e podemos partir para a criação de nossa web-api para realizarmos nossos primeiros testes de autenticação! 

## Criação da web-api e configuração do Keycloak 
Crie uma nova aplicação do tipo web-api. Pode ser feito via UI pelo Visual Studio ou pelo comando:
```bash


dotnet new webapi -n NomeDoProjeto


Enter fullscreen mode Exit fullscreen mode

Instale as bibliotecas do KeyCloak necessárias via NuGet



dotnet add package Keycloak.AuthServices.Authorization
dotnet add package Keycloak.AuthServices.Authentication


Enter fullscreen mode Exit fullscreen mode

Para verificar se foi instalado corretamente, podemos abrir o csproj do nosso projeto. Deverá estar assim:

img

Precisamos fazer com que o KeyCloak identifique nossa aplicação, isso significa que precisaremos criar um Client pelo Console de Administrador.

No painel lateral, clique em Client e depois em Create Client. O meu Client ID será mordor-api e clique em Next.

img

Iremos marcar Client authentication e Authorization e clicar em Next

img

No Login Settings, podemos definir qual a Home URL e as URL de redirecionamento, ou URL após realizar o Logout. Como estamos fazendo uma demonstração simples de uma web-api, não iremos preencher nenhum desses campos, mas é interessante notar que esses campos precisam ser preenchidos quando temos uma tela de login, e precisamos realizar o redirecionamento para nossa home page após a autenticação de um usuário.

Criado nosso primeiro Client, iremos definir agora o Client Scope, que se refere a um conjunto de permissões, atributos ou funcionalidades que são concedidos a um aplicativo durante a autenticação e autorização. No painel lateral, vamos clicar em Client scopes e depois em Create client scope.

img

Dê um nome ao seu escopo, selecione o Type como Default e o prococolo sendo OpenID Connect.

img

Após criado o escopo, iremos definir alguns Mappers, que serão certos campos que serão mapeados dentro do token.

img

Primeiro, iremos adicionar um mapper pre-definido para adicionar as roles de um client dentro do token.

img

Iremos adicionar um novo mapper configurado, para adicionar o campo de Audience no token. Clique em AddMapper e depois em ByConfiguration e depois em Audience.

img

img

Nosso escopo deverá ter dois mappers:

img

Precisamos adicionar o scope criado ao nosso client. Na aba Clients, clique no client que você criou e depois disso na aba superior Client scopes e Add client scope.

img

img
Iremos extrair as configurações necessárias do nosso Client, para configurar nossa web-api. Ainda no menu Clients, clique no dropdown Action no canto superior direito e depois em Download Adapter config.

img

img
Altere o campo "ssl-required": "external" para "ssl-required": "none", visto que não iremos utilizar nenhum tipo de certificado.
Copie todo esse JSON, e no appsettings.Development.json coloque a chave como sendo "Keycloak". Suas configurações deverão ficar assim:

img

Agora, precisamos adicionar a autenticação e autorização no nosso Program.cs.
Adicione as seguintes linhas de código ao seu Program.cs:



var authenticationOptions = builder
                            .Configuration
                            .GetSection(KeycloakAuthenticationOptions.Section)
                            .Get<KeycloakAuthenticationOptions>();

builder.Services.AddKeycloakAuthentication(authenticationOptions);

var authorizationOptions = builder
                            .Configuration
                            .GetSection(KeycloakProtectionClientOptions.Section)
                            .Get<KeycloakProtectionClientOptions>();

builder.Services.AddKeycloakAuthorization(authorizationOptions);


Enter fullscreen mode Exit fullscreen mode

É importante notar que a Section no appsettings.json deverá ser exatamente Keycloak, visto que o KeycloakAuthenticationOptions.Section é o padrão da biblioteca. Dessa maneira, o KeycloakAuthenticationOptions será bindado corretamente com as informações obtidas pelo adapter, que extraimos do console de administrador.
Ah, não se esqueça também de adicionar:



app.UseAuthentication();

app.UseAuthorization();


Enter fullscreen mode Exit fullscreen mode

Feito isso, crie um Controller e alguns endpoints para efetuar testes. Criei dois endpoints assim:



[HttpGet]
[Authorize]
public ActionResult CreateRing()
{
    return Ok("Ash nazg durbatulûk, ash nazg gimbatul, ash nazg thrakatulûk, agh burzum-ishi krimpatul");
}

[HttpDelete]
[Authorize]
public ActionResult DestroyRing()
{
    return NoContent();
}


Enter fullscreen mode Exit fullscreen mode

Testando os endpoints protegidos

Com o Postman, podemos obter o acess_token enviando um request do tipo POST para http://localhost:8080/realms/mordor/protocol/openid-connect/token.
No Body da requisição, iremos realizar o grant_type do acess_token por meio da senha configurada para o usuário

img
Se tudo estiver correto, como resposta iremos receber uma resposta assim:

img

Podemos colar o access_token no site https://jwt.io/ para verificar quais foram os campos que vieram no nosso JWT!

img

Iremos testar um dos nossos endpoints protegidos sem estarmos autorizados:

img
Podemos observar que o Status foi 401 Unauthorized. Agora, nos autorizarmos colando o access_token no Bearer Token obtemos um Status 200.

img

Criação de grupos e roles e associação de usuários e grupos.

Voltando ao Console de Administrador do KeyCloak, podemos realizar a criação de grupos no painel lateral. Irei criar apenas um grupo chamado FellowshipOfTheRing

img
Agora iremos criar uma role para o nosso Client. Na aba Client, selecione o client que criamos para realizar a demonstração e na aba Roles, crie uma nova Role. Criei duas roles como indicado abaixo.

img
Vamos colocar Frodo e Sam (os usuários que criei) dentro do grupo FellowshipOfTheRing. Clique na aba groups e depois clique em Members e AddMember

img
Mapearemos apenas uma role para nosso grupo. Clique na aba Role mapping e depois em Assign Role. Filtramos por Clients (isso significa que podemos ver as roles que criamos no nosso client) e atribuimos a role DestroyRing para nosso grupo.

img
Agora, no painel lateral, em Users, iremos atribuir a role CreateRing para o usuario Sauron.

img

Testar novamente os endpoints.

Feitas as novas configuraçoes de acesso aos nossos recursos, podemos configurar nossas endpoints de acordo com essas configuraçoes de Roles. No Controller, irei mudar as rotas inserindo o parametro que irá verificar as Roles que o usuário possui.



[HttpGet]
[Authorize(Roles ="CreateRing")]
public ActionResult CreateRing()
{
    return Ok("Ash nazg durbatulûk, ash nazg gimbatul, ash nazg thrakatulûk, agh burzum-ishi krimpatul");
}

[HttpDelete]
[Authorize(Roles ="DestroyRing")]
public ActionResult DestroyRing()
{
    return NoContent();
}


Enter fullscreen mode Exit fullscreen mode

No Postman, vamos receber o access_token como Sauron, e tentar acessar o endpoint DestroyRing.

img

Podemos perceber que o Status Code foi 403 Forbidden, visto que Sauron não possui a Role DestroyRing atribuida a ele. Agora se formos acessar a rota CreateRing obtemos o StatusCode 200, visto que o usuário Sauron possui a role necessária para o acesso ao endpoint.

img
Se solicitarmos o access_token como Frodo ou como Sam, será que podemos acessar a endpoint CreateRing visto que atribuimos a role apenas para o grupo? A resposta é sim! Uma role atribuida a um grupo é repassada para os usuários que estão atribuidos a este grupo!
Obtendo o access_token e verificando o token no https://jwt.io/ verificamos a Role que atribuimos ao grupo FellowshipOfTheRing e podemos realizar normalmente a requisição para o endpoint.

img

img

Conclusão

Podemos perceber que as funcionalidades do Keycloak são inúmeras, e facilitam a nossa vida como desenvolvedor. As documentações são bastante claras e apresentam diversas explicações de como podemos implementar as features que o Keycloak oferecem em nossos projetos e em empresas.

Espero que tenham gostado desse passo-a-passo! Pretendo aprofundar um pouco mais no tópico e irei trazer mais novidades por aqui!

Segue o repositório da demonstração

GitHub logo gloinho / mordor-api

Exemplo para demonstração de autenticação e autorização utilizando Keycloak

mordor-api




Até a proxima!

Top comments (6)

Collapse
 
felipe_mattioli_f28508b3a profile image
Felipe Mattioli • Edited

Sencional o artigo, me ajudou bastante!!!
Pra quem quer fazer essas configs ai no .net8, as configs mudaram um pouco pois o pacote utilizado está na versão 2.5.0 (atualmente, 06/06/2024), então pra resolve é preciso fazer isso:

Config na program.cs

builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddKeycloakWebApi(builder.Configuration);
builder.Services
.AddAuthorization()
.AddKeycloakAuthorization()
.AddAuthorizationBuilder()
.AddPolicy(
"RequireWritedataRole",
policy => policy.RequireResourceRolesForClient(
"receipts-commandhandler-api", // client conforme configurado no Keycloak
["writedata"] // Roles necessárias (Nome da role definida lá no Keycloak)
)
);

Config na controller

[HttpPost]
[Authorize(Policy = "RequireWritedataRole")]
public async Task<IActionResult> AddCategory([FromBody] CategoryInputModel categoryInputModel, CancellationToken cancellationToken)
{
var categoryId = await _mediator.Send(new AddCategoryRequestCommand(categoryInputModel), cancellationToken);
return Created("/addCategory", categoryId);
}

Fiquei umas boas horas quebrando a cabeça pra conseguir entender essa configuração kkk.
Basicamente é preciso configurar uma Policy e depois por a role nessa policy...

Documentação: nikiforovall.github.io/keycloak-au...

Collapse
 
mva99 profile image
Matheus Victor Almeida

Cara, me salvou.

Muito obrigado tava desistindo de roles já kkkk.

Collapse
 
phenriquesousa profile image
Pedro Henrique

Obrigado por compartilhar, primo <3

Collapse
 
zoldyzdk profile image
Hewerton Soares

Congrats, primo!

Collapse
 
fernandoandrade profile image
Fernando Andrade

Ótimo artigo primo, desconhecia esse tipo de autorização, estava mais acostumado com identityserver.

Collapse
 
adrielavelar profile image
adrielavelar

muito bom! parabéns pelo artigo!