Features
Every capability of the licensing platform, from token cryptography to self-service registration.
RSA-256 Signed Tokens
Every license key is a JWT signed with RS256. Keys can be managed locally via PEM file or remotely through Azure Key Vault where the private key never leaves the vault.
JWE Encryption
When a consuming application provides its RSA public key during activation, the server returns a JWE token (RSA-OAEP + A256CBC-HS512). Only the consumer can decrypt and read the claims.
License Issuance
Generate license keys against a product and pricing tier. Set expiry dates or mark as perpetual (100-year token lifetime). Each token carries tier, features, limits, and heartbeat policy.
Per-Machine Activation
Track activations by machine identifier and IP address. Activating a key auto-revokes sibling keys for the same customer and product, ensuring one active key per customer per product.
Seat Enforcement
MaxUsers is enforced at activation time. If the seat limit for a tier has been reached, activation is rejected. Deactivating a machine frees a seat for reuse.
Heartbeat Renewal
Consuming applications call /heartbeat with their ClientId. The server returns a fresh short-lived token (default 48h). No heartbeat means the token expires and the application stops working.
License Revocation
Revoke any license with a reason and timestamp. Revocation is checked during validation and heartbeat. Revoking a license instantly invalidates access for the consuming application.
Token Audit
The audit endpoint compares stored JWT claims against the expected state from the current database. Detects drift between what the token says and what it should say.
Token Regeneration
Regenerate a license token on demand without changing the license record. Useful when tier features change or token claims need to be refreshed.
Hierarchical Pricing Tiers
Tiers can inherit all features from a parent tier via IncludesTierId. Circular reference protection with a visited set guard. Each tier configures monthly/annual price, user/tenant limits, and billing periods.
Feature Flags in Tokens
Named feature keys (e.g., "sso", "passkeys", "multi_tenant") are embedded in JWT claims. Consuming applications read these at runtime to gate functionality without network calls.
Display-Only Features
Mark features as display-only so they appear in marketing and pricing pages but are excluded from the actual JWT token claims. Clean separation of marketing and enforcement.
License Lifecycle
> 1. Issue License
POST /license-keys
Product: Rdn.Identity
Tier: Enterprise
Customer: customer@example.com
Result: RSA-256 signed JWT
> 2. Validate Token
POST /license-keys/validate
Input: Raw keyToken
Returns: licenseId, decoded claims
> 3. Activate
POST /license-activations/activate
MachineId: HWID-ABC-123
PublicKey: RSA-2048 (optional)
Returns: JWE token + clientId
> 4. Heartbeat Loop
POST /license-keys/heartbeat
ClientId: guid
Interval: 60 minutes
Token TTL: 48 hours
No heartbeat: Token expires, app goes dark
> 5. Audit
POST /license-keys/:id/audit
Compares: Token claims vs. DB state
Detects: Drift, missing features
JWE: Consistent but encrypted
> 6. Revoke
POST /license-keys/:id/revoke
Reason: "Subscription cancelled"
Effect: Next heartbeat returns invalid
Domain Model
Product
ProductFeature
PricingTier
PricingTierFeature
Customer
LicenseKey
LicenseActivation
PendingLicenseClaim
Self-Service Registration
Register
Customer visits /register with product and tier in query params. A PendingLicenseClaim is created.
Identity Invite
The License API calls Rdn.Identity to create the user account and send an email invite.
Set Password
Customer receives the email, follows the link to Rdn.Identity, and sets their password.
Claim License
Customer logs in and calls /user/claim-license. The pending claim is fulfilled and a license key is issued.
Discovery Endpoints
> /.well-known/jwks.json
{
"keys": [{
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"kid": "rdn-lic-2025",
"n": "modulus...",
"e": "AQAB"
}]
}
> /.well-known/license-configuration
{
"issuer": "https://license.reidell.net",
"jwks_uri": ".../.well-known/jwks.json",
"validate_endpoint": ".../validate",
"activate_endpoint": ".../activate",
"heartbeat_endpoint": ".../heartbeat",
"signing_algorithms": ["RS256"],
"encryption_algorithms": ["RSA-OAEP"]
}