BTW.KeycloakJwtGenerator 1.0.0

dotnet add package BTW.KeycloakJwtGenerator --version 1.0.0
                    
NuGet\Install-Package BTW.KeycloakJwtGenerator -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BTW.KeycloakJwtGenerator" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BTW.KeycloakJwtGenerator" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="BTW.KeycloakJwtGenerator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BTW.KeycloakJwtGenerator --version 1.0.0
                    
#r "nuget: BTW.KeycloakJwtGenerator, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BTW.KeycloakJwtGenerator@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BTW.KeycloakJwtGenerator&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=BTW.KeycloakJwtGenerator&version=1.0.0
                    
Install as a Cake Tool

📦 BTW.KeycloakJwtGenerator

NuGet

License

.NET

Librería .NET para generar JWT centralizados usando Keycloak como Identity Provider. Permite que sistemas con autenticación propia (LDAP, Base de Datos, Active Directory, etc.) generen tokens JWT estandarizados con claims personalizados.

🎯 ¿Para Qué Sirve?

Tu Sistema (auth propia) → BTW.KeycloakJwtGenerator → Keycloak → JWT con tus claims
  • ✅ Tu sistema mantiene su mecanismo de autenticación (BD, LDAP, AD)
  • ✅ Keycloak genera JWT estandarizados
  • ✅ Incluye los claims personalizados que necesites
  • ✅ Todos tus sistemas validan el mismo JWT

📦 Instalación

dotnet add package BTW.KeycloakJwtGenerator

⚡ Requisitos

  • .NET 6.0 o superior
  • .NET 7.0 o superior
  • .NET 8.0 o superior

La librería es compatible con las versiones .NET 6, .NET 7 y .NET 8.

🚀 Uso Rápido

1. Configurar en appsettings.json

{
  "KeycloakJwt": {
    "BaseUrl": "http://localhost:8080",
    "Realm": "mi-realm",
    "ClientId": "mi-sistema",
    "ClientSecret": "mi-secret",
    "SystemName": "Sistema A"
  }
}

2. Registrar en Program.cs

// Opción 1: Desde appsettings.json
builder.Services.AddKeycloakJwtGenerator(builder.Configuration);

// Opción 2: Configuración fluida
builder.Services
    .AddKeycloakJwt()
    .WithBaseUrl("http://localhost:8080")
    .WithRealm("mi-realm")
    .WithClient("mi-cliente", "mi-secret")
    .WithSystemName("Sistema A")
    .Build();

// Opción 3: Con Action
builder.Services.AddKeycloakJwtGenerator(options =>
{
    options.BaseUrl = "http://localhost:8080";
    options.Realm = "mi-realm";
    options.ClientId = "mi-cliente";
    options.ClientSecret = "mi-secret";
    options.SystemName = "Sistema A";
});

3. Usar en tu código

public class AuthController : ControllerBase
{
    private readonly IKeycloakJwtGenerator _jwtGenerator;

    public AuthController(IKeycloakJwtGenerator jwtGenerator)
    {
        _jwtGenerator = jwtGenerator;
    }

    [HttpPost("login")]
    public async Task<IActionResult> Login(LoginRequest request)
    {
        // 1. Tu autenticación local (BD, LDAP, etc.)
        var user = await _myAuthService.ValidateAsync(request.Username, request.Password);
        
        if (user == null)
            return Unauthorized();

        // 2. Definir claims personalizados
        var claims = new Dictionary<string, object>
        {
            ["departamento"] = user.Departamento,
            ["nivel_acceso"] = user.NivelAcceso,
            ["permisos"] = user.Permisos,        // Array
            ["sucursal"] = user.Sucursal,
            ["metadata"] = new {                  // Objeto anidado
                zona = user.Zona,
                codigo = user.Codigo
            }
        };

        // 3. Generar JWT con Keycloak
        var token = await _jwtGenerator.GenerateTokenAsync(request.Username, claims);

        return Ok(new
        {
            accessToken = token.AccessToken,
            refreshToken = token.RefreshToken,
            expiresIn = token.ExpiresIn
        });
    }
}

📋 API Completa

Generar Token (Simple)

var token = await _jwtGenerator.GenerateTokenAsync(
    "usuario",
    new Dictionary<string, object>
    {
        ["departamento"] = "ventas",
        ["permisos"] = new[] { "leer", "escribir" }
    });

Generar Token (Request Completo)

var token = await _jwtGenerator.GenerateTokenAsync(new GenerateTokenRequest
{
    Username = "usuario",
    Email = "usuario@empresa.com",
    FirstName = "Juan",
    LastName = "Pérez",
    Roles = new List<string> { "user", "admin" },
    Claims = new Dictionary<string, object>
    {
        ["departamento"] = "ventas"
    }
});

Refrescar Token

var newToken = await _jwtGenerator.RefreshTokenAsync(refreshToken);

Validar Token

bool isValid = await _jwtGenerator.ValidateTokenAsync(accessToken);

Revocar Token (Logout)

await _jwtGenerator.RevokeTokenAsync(refreshToken);

🔐 Validar JWT en Otros Sistemas

Para sistemas que solo necesitan validar tokens (no generarlos):

// Solo agrega validación de JWT
builder.Services.AddKeycloakJwtValidation(builder.Configuration);

// O ambos (generar y validar)
builder.Services.AddKeycloakJwtFull(builder.Configuration);

Luego usa [Authorize] normalmente:

[Authorize]
[HttpGet("protected")]
public IActionResult Protected()
{
    var departamento = User.FindFirst("departamento")?.Value;
    return Ok(new { departamento });
}

⚙️ Configuración Completa

{
  "KeycloakJwt": {
    "BaseUrl": "http://localhost:8080",
    "Realm": "mi-realm",
    "ClientId": "mi-sistema",
    "ClientSecret": "secret",
    "SystemName": "Sistema A",
    "TimeoutSeconds": 30,
    "EnableAdminTokenCache": true,
    "AdminTokenCacheMinutes": 4,
    "UseTokenExchange": true,
    "MaxRetries": 3
  }
}
Opción Descripción Default
BaseUrl URL de Keycloak http://localhost:8080
Realm Nombre del Realm master
ClientId Client ID del service account -
ClientSecret Client Secret -
SystemName Nombre del sistema (claim) null
TimeoutSeconds Timeout HTTP 30
EnableAdminTokenCache Cachear token admin true
AdminTokenCacheMinutes Tiempo de caché 4
UseTokenExchange Usar Token Exchange true
MaxRetries Reintentos en fallo 3

🛠️ Configuración de Keycloak

1. Crear Client (Service Account)

Clients → Create client
├── Client ID: "mi-sistema"
├── Client authentication: ON
├── Service accounts roles: ✅
└── Save

2. Asignar Roles al Service Account

Client → Service account roles → Assign role
├── manage-users
├── view-users
└── impersonation (para Token Exchange)

3. Crear Protocol Mappers

Client → Client scopes → Dedicated scope → Mappers
├── Mapper type: "User Attribute"
├── User Attribute: "departamento"
├── Token Claim Name: "departamento"
├── Add to access token: ✅
└── Save

4. Habilitar Token Exchange (opcional)

Si estás ejecutando Keycloak con Docker, agrega esta configuración para habilitar Token Exchange:

# docker-compose.yml (configuración de Keycloak, no de tu aplicación)
services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    environment:
      KC_FEATURES: token-exchange
      # ... otras configuraciones

Nota: Esta configuración es solo para Keycloak. Si Keycloak ya tiene Token Exchange habilitado o usas otra forma de instalación, puedes omitir este paso.

📄 Licencia

MIT License - ver LICENSE


Desarrollado con ❤️ por By The Wave (BTW)

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 402 12/10/2025