Linbik.JwtAuthManager 1.1.0

dotnet add package Linbik.JwtAuthManager --version 1.1.0
                    
NuGet\Install-Package Linbik.JwtAuthManager -Version 1.1.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="Linbik.JwtAuthManager" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Linbik.JwtAuthManager" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Linbik.JwtAuthManager" />
                    
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 Linbik.JwtAuthManager --version 1.1.0
                    
#r "nuget: Linbik.JwtAuthManager, 1.1.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 Linbik.JwtAuthManager@1.1.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=Linbik.JwtAuthManager&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Linbik.JwtAuthManager&version=1.1.0
                    
Install as a Cake Tool

Linbik.JwtAuthManager

JWT Authentication Manager with RSA-256 signing support for Linbik Framework.

🚀 Features

Authorization Code Support (v2.0+)

  • RSA-256 JWT Signing - Industry-standard asymmetric cryptography
  • Per-Service Key Pairs - Each service uses its own private/public keys
  • Multi-Service Token Generation - Issue multiple JWTs in single response
  • PKCS#8 & X.509 Support - Standard PEM key formats
  • Token Validation - Verify JWT signatures with public keys
  • Claims Extraction - Parse and validate JWT claims

Legacy Features (Deprecated)

  • Symmetric key JWT signing (HS256) - Use RSA-256 instead
  • Single-key authentication - Use per-service keys

📦 Installation

dotnet add package Linbik.JwtAuthManager

🔧 Configuration

Basic Setup

services.AddLinbikJwtAuth(options =>
{
    options.Issuer = "linbik";
    options.DefaultAudience = "my-service";
    options.AccessTokenLifetimeMinutes = 60;
    options.RefreshTokenLifetimeDays = 30;
    options.ClockSkewMinutes = 1;
});
// In Program.cs

// 1. Add services
builder.Services.AddLinbik(builder.Configuration);
builder.Services.AddLinbikJwtAuth();

// 2. Map endpoints
app.MapLinbikEndpoints();  // Maps /linbik/login, /linbik/logout, /linbik/refresh

Endpoints: | Path | Method | Description | |------|--------|-------------| | /linbik/login | GET | Exchange auth code for tokens | | /linbik/logout | POST | Clear all auth cookies | | /linbik/refresh | POST | Refresh tokens |

RSA Key Configuration

// For each service that needs to issue tokens
options.ServiceKeyPairs.Add(new ServiceKeyPair
{
    ServiceId = Guid.Parse("service-guid"),
    PrivateKeyPem = "-----BEGIN PRIVATE KEY-----\n...",  // PKCS#8
    PublicKeyPem = "-----BEGIN PUBLIC KEY-----\n..."     // X.509 SPKI
});

💻 Usage

Create JWT Token

public class TokenService
{
    private readonly IJwtHelper _jwtHelper;

    public TokenService(IJwtHelper jwtHelper)
    {
        _jwtHelper = jwtHelper;
    }

    public async Task<string> CreateAccessTokenAsync(User user, Service service)
    {
        var claims = new[]
        {
            new Claim("userId", user.Id.ToString()),
            new Claim("userName", user.UserName),
            new Claim("nickName", user.NickName)
        };

        return await _jwtHelper.CreateTokenAsync(
            claims: claims,
            privateKey: service.PrivateKey,      // PKCS#8 PEM
            audience: service.Id.ToString(),
            expirationMinutes: 60
        );
    }
}

Validate JWT Token

public async Task<bool> ValidateTokenAsync(string token, Service service)
{
    return await _jwtHelper.ValidateTokenAsync(
        token: token,
        publicKey: service.PublicKey,            // X.509 SPKI PEM
        expectedAudience: service.Id.ToString(),
        expectedIssuer: "linbik"
    );
}

Extract Claims

public Dictionary<string, string> GetUserInfoFromToken(string token)
{
    var claims = _jwtHelper.GetTokenClaims(token);
    
    // claims["userId"], claims["userName"], claims["exp"], etc.
    return claims;
}

🏗️ Architecture

JwtHelperService Implementation

Token Creation Flow:
1. Parse claims array
2. Import RSA private key (PKCS#8 PEM)
3. Create token descriptor with RS256 algorithm
4. Sign token with RSA key
5. Return base64-encoded JWT string

Token Validation Flow:
1. Import RSA public key (X.509 SPKI PEM)
2. Configure validation parameters (issuer, audience, lifetime)
3. Validate signature with RSA key
4. Verify claims (exp, iss, aud)
5. Return true/false

Key Format Support

Private Key (PKCS#8 PEM):

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
-----END PRIVATE KEY-----

Public Key (X.509 SPKI PEM):

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8zN...
-----END PUBLIC KEY-----

📋 Repository Interface

ILinbikRepository

public interface ILinbikRepository
{
    // Authorization Methods (v2.0+)
    Task<ServiceData?> GetServiceByApiKeyAsync(string apiKey);
    Task<ServiceData?> GetServiceByIdAsync(Guid serviceId);
    Task<List<ServiceData>> GetGrantedIntegrationServicesAsync(Guid userId, Guid mainServiceId);
    
    // Legacy Methods (Deprecated)
    [Obsolete("Use GetServiceByIdAsync")]
    Task<AppModel?> GetAppByIdAsync(Guid appId);
}

InMemoryLinbikRepository

In-memory implementation for testing:

services.AddSingleton<ILinbikRepository, InMemoryLinbikRepository>();

// Pre-populate with test data
var repo = serviceProvider.GetRequiredService<InMemoryLinbikRepository>();
repo.AddService(new ServiceData
{
    Id = Guid.NewGuid(),
    PackageName = "test-service",
    ApiKey = "linbik_test123",
    PrivateKey = "-----BEGIN PRIVATE KEY-----...",
    PublicKey = "-----BEGIN PUBLIC KEY-----...",
    IsIntegrationService = true
});

🔒 Security Features

RSA-256 (RS256)

  • Asymmetric Cryptography: Private key signs, public key verifies
  • 2048-bit Keys: Industry-standard key length
  • No Shared Secrets: Public keys can be distributed safely
  • Per-Service Keys: Each service has unique key pair

Token Validation

  • Signature Verification: RSA signature check
  • Issuer Validation: Verify token issuer claim
  • Audience Validation: Verify intended recipient
  • Expiration Check: Enforce token lifetime
  • Clock Skew Tolerance: 1-minute default tolerance

🔄 Migration from v1.x

// ❌ Old way (v1.x - Symmetric key)
var token = _jwtHelper.CreateToken(claims, sharedSecret);

// ✅ New way (v2.0+ - Asymmetric RSA)
var token = await _jwtHelper.CreateTokenAsync(
    claims, 
    service.PrivateKey, 
    audience: service.Id.ToString()
);

Legacy methods still work but are marked [Obsolete]:

  • CreateToken(claims, sharedSecret) → Use CreateTokenAsync with RSA key
  • ValidateToken(token, sharedSecret) → Use ValidateTokenAsync with public key
  • GetAppByIdAsync(appId) → Use GetServiceByIdAsync(serviceId)

📖 Documentation

📄 License

This library is currently a work in progress and is not ready for production use.

Contact: info@linbik.com


Version: 2.0.0 (RSA-256 Support)
Last Updated: 1 Kasım 2025

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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.1.0 371 12/5/2025
1.0.1 208 12/14/2025
0.46.0 348 11/30/2025
0.45.12 343 11/30/2025
0.45.7 229 8/31/2025
0.45.6 200 8/31/2025
0.45.5 219 8/27/2025
0.44.0 238 8/24/2025
0.42.0 100 8/23/2025
0.41.0 109 8/15/2025
0.40.0 187 8/14/2025
0.39.0 182 8/14/2025
0.38.0 181 8/14/2025
0.37.0 369 7/25/2025
0.36.0 576 7/22/2025
0.1.0 529 7/21/2025
0.1.0-ci0025 559 7/22/2025
0.0.1 369 6/16/2025