Usar Keycloak como provedor de identidade no ASP.NET Core 6
- TL;DR
- Introdução ao Keycloak
- Ideias por trás do Keycloak.AuthServices.Authentication
- Demo
- Bônus - Adicionando Autorização
- Resumo
TL;DR
Saiba como usar o Keycloak no ASP.NET Core 6 usando Keycloak.AuthServices.Authentication.
Código fonte: https://github.com/NikiforovAll/keycloak-authorization-services-dotnet/blob/main/samples/AuthGettingStarted/Program.cs
Introdução ao Keycloak
Keycloak - Gerenciamento de Identidade e Acesso de Código Aberto. Adicione autenticação a aplicativos e serviços seguros com o mínimo de esforço. Não há necessidade de lidar com o armazenamento de usuários ou autenticação de usuários. O Keycloak fornece federação de usuários, autenticação forte, gerenciamento de usuários, autorização refinada e muito mais.
Pessoalmente, sou um grande fã do Keycloak porque é um sistema de gerenciamento de identidade e acesso maduro e completo. Ele contém tudo o que você pode precisar para a maioria dos cenários. Ao contrário do IdentityServer, é fácil de usar pronto para uso, sem necessidade de código para fazer as coisas funcionarem. Se o Azure Active Directory não for uma opção por algum motivo, eu definitivamente considero o Keycloak como uma opção de código aberto viável que poderia ser instalada no prem.
Caraterísticas:
- Logon único
- Corretagem de Identidade e Login Social
- Federação de Usuários
- Console de administração
- Console de Gerenciamento de Contas
- Serviços de Autorização
Veja: https://www.keycloak.org/
Ideias por trás do Keycloak.AuthServices.Authentication
Keycloak é OAuth2 + OpenID Connect provedor compatível, por isso deve ser fácil de usá-lo. Embora, leva algum tempo para que os conceitos e a configuração do Keycloak possam ASP.NET modelo de configuração da Autenticação Principal. Foi assim que preparei uma biblioteca de conveniência para acelerar o processo de integração e tornar o uso do Keycloak no mundo .NET mais agradável.
Basicamente, usamos para registrar e configurar o esquema de autenticação e fornecer .AddKeycloakAuthentication
JwtBearerDefaults.AuthenticationScheme
KeycloakAuthenticationOptions
/// <summary>
/// Adds keycloak authentication services.
/// </summary>
public static AuthenticationBuilder AddKeycloakAuthentication(
this IServiceCollection services,
KeycloakAuthenticationOptions keycloakOptions,
Action<JwtBearerOptions>? configureOptions = default) {/*...*/}
A estrutura geral do projeto tem esta aparência:
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
services.AddKeycloakAuthentication(authenticationOptions);
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", (ClaimsPrincipal user) =>
{
app.Logger.LogInformation(user.Identity.Name);
}).RequireAuthorization();
app.Run();
Configurar KeycloakAuthenticationOptions
As são várias maneiras de configurar a autenticação Keycloak. Mais tarde, mostrarei como usar o adaptador de cliente Keycloak OIDC perfeitamente.
1️⃣ Construir objeto
var authenticationOptions = new KeycloakAuthenticationOptions
{
AuthServerUrl = "http://localhost:8088/",
Realm = "Test",
Resource = "test-client",
};
services.AddKeycloakAuthentication(authenticationOptions);
2️⃣ Ler manualmente a partir da configuração
var configuration = builder.Configuration;
var authenticationOptions = configuration
.GetSection(KeycloakAuthenticationOptions.Section)
.Get<KeycloakAuthenticationOptions>();
services.AddKeycloakAuthentication(authenticationOptions);
3️⃣ A partir da configuração
var configuration = builder.Configuration;
services.AddKeycloakAuthentication(configuration, KeycloakAuthenticationOptions.Section);
// section is optional KeycloakAuthenticationOptions.Section = "Keycloak"
services.AddKeycloakAuthentication(configuration);
4️⃣ A partir do arquivo de configuração
keycloak.json usado pelo adaptador de cliente Keycloak OIDC para configurar clientes. Você também pode querer ajustar este arquivo depois de baixá-lo.
var configuration = builder.Configuration;
var host = builder.Host;
host.ConfigureKeycloakConfigurationSource("keycloak.json"); // file name is optional
services.AddKeycloakAuthentication(configuration);
Demo
Antes de começarmos a integrar, precisamos executar uma instância do Keycloak em uma máquina de desenvolvimento.
Consulte https://www.keycloak.org/getting-started/getting-started-docker para obter mais detalhes.
Vamos criar nosso primeiro reino.
- Abra o Keycloak Admin Console
- Passe o mouse sobre a lista suspensa no canto superior esquerdo, onde diz Mestre, e clique em Adicionar reino
- Preencha o formulário com os seguintes valores:
- Nome: Teste
- Clique
Create
Criar um usuário
Inicialmente, não há usuários em um novo território, então vamos criar um:
- Abra o Keycloak Admin Console
- Clique (menu à esquerda)
Users
- Clique (canto superior direito da tabela)
Add user
- Preencha o formulário com os seguintes valores:
- Nome do usuário: test@test.com
- Primeiro Nome: Seu primeiro nome
- Sobrenome: Seu sobrenome
- Clique
Save
Vamos tentar garantir nossa primeira aplicação. O primeiro passo é registrar este aplicativo com sua instância Keycloak:
- Abra o Keycloak Admin Console
- Clique (menu à esquerda)
Clients
- Preencha o formulário com os seguintes valores:
- Tipo de cliente: “OpenID Connect”
- ID do cliente: test-client
- Clique
Save
Como mencionado acima, Keycloak tem um conceito de configuração do adaptador. Ele nos permite copiar configurações essenciais. é deliberadamente projetado para agilizar o processo de instalação, de modo que o imita a estrutura da configuração do adaptador.Keycloak.AuthServices.Authentication
KeycloakAuthenticationOptions
Navegue pelo cliente recém-criado (canto superior direito) e clique em “Ação>Baixar configuração do adaptador”
Aqui está o que parece:
{
"realm": "Test",
"auth-server-url": "http://localhost:8080/",
"ssl-required": "external",
"resource": "test-client",
"public-client": true,
"verify-token-audience": true,
"use-resource-role-mappings": true,
"confidential-port": 0
}
💡 Geralmente, você deseja usar o mapeador de protocolo para configurar o público necessário (“recurso” na configuração acima). Para simplificar a demonstração, podemos simplesmente desativar a validação de público. Alterar “verify-token-audience”: false. Consulte https://dbp-demo.tugraz.at/handbook/relay/keycloak/keycloak_audience/ e https://stackoverflow.com/a/53627747/8168625 para obter mais detalhes.
💡 Os tokens devem ser trocados com base em HTTPS, mas para o ambiente do desenvolvedor, você pode usar HTTP. Alterar “ssl-required”: “nenhum”
Agora, podemos criar keycloak.json ou estender appsettings.json.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Keycloak": {
"realm": "Test",
"auth-server-url": "http://localhost:8080/",
"ssl-required": "none",
"resource": "test-client",
"verify-token-audience": false
"confidential-port": 0
}
}
Para usar a configuração fornecida, basta se registrar AddKeycloakAuthentication
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
var host = builder.Host;
host.ConfigureLogger();
services.AddEndpointsApiExplorer().AddSwagger();
services.AddKeycloakAuthentication(configuration);
var app = builder.Build();
appv.UseSwagger().UseSwaggerUI();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", (ClaimsPrincipal user) =>
{
app.Logger.LogInformation(user.Identity.Name);
}).RequireAuthorization();
app.Run();
Agora precisamos obter um token de acesso e fazer uma chamada via swagger-ui. Existem várias maneiras de fazê-lo. No meu caso, abri o “cliente de teste” e o tornei confidencial, e habilitei “Concessões de acesso direto”. Desta forma, podemos usar um nome de usuário e senha. Certifique-se de entender como configurar o OAuth 2.0 e o OpenId Connect antes de passar para a produção. No meu caso, é fácil de demonstrar.
curl --data "grant_type=password&client_id=test-client&username=test&password=test&client_secret=Tgx4lvbyhho7oNFmiIupDRVA8ioQY7PW" \
localhost:8080/realms/Test/protocol/openid-connect/token
Now, we can navigate swagger and make an authentication request by providing an access token.[https://localhost:5001/swagger](https://localhost:5001/swagger)
Vamos ver como podemos usar para criar políticas básicas com reconhecimento de Keycloak. Consulte: AuthorizationPolicyKeycloak.AuthServices.Authorization
💡 Keycloak tem um conceito de papéis. Adicionei funções de domínio e recursos nos bastidores. Sugiro que você descubra por conta própria como um exercício 😛.
No exemplo abaixo, exigimos que um usuário tenha a função de realm “admin” e a função de recurso “r-admin” usando e respectivamente. Observe que as funções de recurso são mapeadas automaticamente para funções, portanto, é igual ao .RequireRealmRoles
RequireResourceRoles
Microsoft.AspNetCore.Authorization
b.RequireResourceRoles("r-admin")
b.RequireRole("r-admin")
⚠ O de é usado como uma Audiência e como a chave para o mapeamento de função.resource
KeycloakAuthenticationOptions
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
var host = builder.Host;
host.ConfigureLogger();
services.AddEndpointsApiExplorer().AddSwagger();
services.AddKeycloakAuthentication(configuration);
services.AddAuthorization(o => o.AddPolicy("IsAdmin", b =>
{
b.RequireRealmRoles("admin");
b.RequireResourceRoles("r-admin"); // stands for "resource admin"
// resource roles are mapped to ASP.NET Core Identity roles
b.RequireRole("r-admin");
}));
services.AddKeycloakAuthorization(configuration);
var app = builder.Build();
app.UseSwagger().UseSwaggerUI();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", (ClaimsPrincipal user) =>
{
app.Logger.LogInformation(user.Identity.Name);
}).RequireAuthorization("IsAdmin");
app.Run();
Aqui está a aparência dos logs após uma solicitação HTTP GET “/” bem-sucedida.
Resumo
Você pode usar Keycloak.AuthServices para integrar com Keycloak. Keycloak tem toneladas de grandes recursos e, felizmente, podemos nos beneficiar do mundo de código aberto Java como desenvolvedores .NET.