Rdn.License
License Management

License Keys, Cryptographically Sealed

A full-stack licensing platform with RSA-256 signed JWT tokens, optional JWE encryption, per-machine activation with seat enforcement, heartbeat-based renewal, hierarchical pricing tiers with feature inheritance, and OpenID-style discovery for consuming applications.

8

Domain Entities

12

API Controllers

45

MediatR Handlers

38

Permissions

36

Components

30

Web Pages

32

API Routes

26

Test Files

Key Capabilities

Everything you need to issue, activate, enforce, and manage software licenses at scale.

JWT License Tokens

RSA-256 signed JWTs with optional JWE encryption (RSA-OAEP + A256CBC-HS512). Feature flags, tier info, and enforcement policy embedded directly in claims.

Per-Machine Activation

Track activations by machine identifier and IP address. Enforce seat limits with MaxUsers. Sibling key auto-revocation ensures one active key per customer per product.

Heartbeat Renewal

Consuming applications call /heartbeat periodically. The server returns a fresh token with configurable TTL (default 48h). No heartbeat means the token expires and the application goes dark.

Pricing Tier Hierarchy

Tiers inherit features from parent tiers via IncludesTierId with circular reference protection. Configure monthly/annual pricing, user limits, tenant limits, and billing periods per tier.

Feature Gating

Named feature keys embedded in JWT claims. Consuming applications read these at runtime to gate functionality without a network call. Display-only features for marketing pages.

Token Discovery

OpenID-style /.well-known/jwks.json and /.well-known/license-configuration endpoints. Consuming apps verify tokens locally using the published RSA public keys.

Three-Panel Web Dashboard

A Next.js 16 application with 30 pages across three distinct route groups, each serving a different audience.

Public Catalog

(site) route group

  • Product catalog with pricing tiers
  • Monthly/annual pricing toggle
  • Feature comparison across tiers
  • Self-service registration flow
  • Privacy policy and terms pages

User Portal

(dashboard) route group

  • My Licenses with credentials display
  • Client ID and Token copy-to-clipboard
  • License claiming for free tiers
  • Profile management (name, company)
  • Product browsing and subscriptions
  • Discord integration and support

Admin Panel

(admin) route group

  • Dashboard with stats and recent licenses
  • Product CRUD with logo and audience
  • Pricing tier management with feature assignment
  • License generation with cascading form
  • Revoke, regenerate, audit license actions
  • Customer management and pending claims
  • System logs with log level control

Full-Stack Architecture

A .NET 10 backend API with CQRS and a Next.js 16 dashboard, connected via OIDC.

Backend API

.NET 10 / ASP.NET Core

  • CQRS with MediatR 14 — 45 command/query handlers
  • Entity Framework Core 10 + Dapper for raw queries
  • RSA-256 JWT signing with Azure Key Vault support
  • Dual auth: JWT Bearer + API Key (X-Api-Key)
  • Data Protection encryption of stored tokens
  • FluentValidation 12 with assembly-scanned validators
  • AutoMapper 16 for entity/DTO projection
  • API versioning with Swagger documentation
  • Rate limiting and HSTS with preload
  • Serilog structured logging (console + file + SQL)

Web Dashboard

Next.js 16 / React 19

  • NextAuth.js v5 with OIDC via Rdn.Identity
  • Three route groups: (site), (dashboard), (admin)
  • 36 components across 30 pages
  • License generation with cascading product/tier selects
  • Feature checklist with sticky sidebar
  • Sortable lists with drag-and-drop (@dnd-kit)
  • DataGrid pagination, sorting, and search
  • Copy-to-clipboard for credentials display
  • Tailwind CSS 4 responsive design
  • TypeScript 5.9 with App Router

Cryptographic Token Security

License tokens are built on industry-standard JWT cryptography with multiple layers of protection.

token-security

> Token Signing

Algorithm: RS256

Key Size: RSA 2048-bit

Key Source: Azure Key Vault / Local PEM

Discovery: /.well-known/jwks.json

> Token Encryption (Optional)

Algorithm: RSA-OAEP

Encryption: A256CBC-HS512

Consumer Key: Provided at activation

> Storage Protection

Encryption: ASP.NET Data Protection

Attribute: [Protected]

Scope: LicenseKey.KeyToken

Converter: Custom EF Core value converter

> Key Vault Integration

Provider: Azure Key Vault

Signing: Remote (key never leaves vault)

Rotation: Configurable refresh interval

Fallback: Local PEM for development

Signed Tokens

Every license token is RSA-256 signed. Consuming applications verify signatures against the published JWKS endpoint without contacting the license server.

Encrypted Tokens

When a consumer provides an RSA public key during activation, the server returns a JWE token (RSA-OAEP + A256CBC-HS512). Only the consumer can decrypt and read the license claims.

At-Rest Encryption

Stored license tokens are encrypted using ASP.NET Core Data Protection. The [Protected] attribute triggers automatic encryption via a custom EF Core value converter.

Comprehensive REST API

12 controllers with 45 handlers covering every aspect of license management, from product catalogs to token validation.

api/v1.0

# Products

GET /products

GET /products/catalog

GET /products/:id

POST /products

PUT /products/:id

DEL /products/:id

# Pricing Tiers

GET /pricing-tiers

GET /pricing-tiers/:id

POST /pricing-tiers

PUT /pricing-tiers/:id

DEL /pricing-tiers/:id

# Product Features

GET /product-features

GET /product-features/:id

POST /product-features

PUT /product-features/:id

DEL /product-features/:id

# Discovery

GET /.well-known/jwks.json

GET /.well-known/license-configuration

# License Keys

GET /license-keys

GET /license-keys/:id

GET /license-keys/by-customer/:id

POST /license-keys

POST /license-keys/validate

POST /license-keys/heartbeat

POST /license-keys/:id/revoke

POST /license-keys/:id/regenerate

GET /license-keys/:id/audit

DEL /license-keys/:id

# Activations

GET /license-activations

GET /license-activations/by-license/:id

POST /license-activations/activate

POST /license-activations/:id/deactivate

# Customers & Users

GET /customers

GET /customers/:id

POST /user/customer

GET /user/licenses

POST /user/licenses

PUT /user/profile

# Pending Claims

GET /pending-claims

POST /pending-claims/:id/resend-invite

DEL /pending-claims/:id