Skip to content

Anwendungsfälle

Widerrufen, verlängern & Ablauf behandeln

Zugang beenden, eine Laufzeit ohne neuen Schlüssel verlängern und genau wissen, was die Anwendung beim Ablauf, während der Kulanzfrist und nach dem Widerruf sieht — und wie sich das von einer selbst gehosteten Instanz unterscheidet, die sich selbst lizenziert.

Ziel. Sie müssen den Zugang eines Kunden sofort beenden (eine Rückbuchung, Missbrauch, eine versehentliche Ausstellung), die Laufzeit eines zahlenden Kunden verlängern, ohne seinen Schlüssel neu auszustellen, und genau verstehen, was die laufende Anwendung anzeigt, während eine Laufzeit ausläuft.

Wann einsetzen

  • Nutzen Sie dies, wenn Sie befristete Lizenzen (Jahreslizenz/Abonnement) verkaufen und verlängern oder jemals einen Schlüssel widerrufen müssen.
  • Nutzen Sie dies, wenn Sie entscheiden, wie aggressiv der Ausfall sein soll — wie schnell ein Widerruf oder Ablauf eine Maschine erreicht, die gerade offline ist.
  • Nicht nutzen, wenn Sie nur unbefristete Lizenzen ausliefern, die nie ablaufen und nie widerrufen werden — dann ist diese Seite nur der Widerrufspfad für den Notfall. Einen Platz zwischen Maschinen zu verschieben ist Aktivierung & Deaktivierung, kein Widerruf.

Zwei Lebenszyklen teilen sich diese Seite und dürfen nicht verwechselt werden. Der Lebenszyklus der Kundenlizenz (die Schlüssel Ihrer Endnutzer) verhält sich gleich, egal ob Sie auf der Cloud oder selbst gehostet laufen. Der Lebenszyklus der selbst gehosteten Instanz ist etwas anderes — der eigene Schlüssel der Instanz, der ihr das Recht zum Betrieb gewährt — und wird am Ende sowie unter Lizenzierung & Editionen behandelt.

Aktiv — lizenziertläuft bald abAbgelaufen → FreeIsExpiringSoon()expiryUtcrenew → Ablauf verschiebengleicher Schlüssel · keine ReaktivierungWiderruf — jederzeitAnwendung fällt bei der nächsten Lease-Aktualisierung auf FreeWie schnell es wirkt = Lease-TTLonline bald; offline spätestens zum Ende der KulanzfristEine Kundenlaufzeit, vollständig aus LicenseInfo gelesenDaysRemaining zählt herunter · IsPaid wird bei Ablauf/Widerruf false · Status sagt warum
Eine befristete Lizenz über ihre Lebensdauer: aktiv, läuft bald ab, verlängert (gleicher Schlüssel) oder abgelaufen/widerrufen — und wie schnell eine Änderung das Gerät erreicht.

Was Sie tun (Anbieterseite)

Alle drei Aktionen signieren die Lizenz serverseitig neu; der Kunde behält den gleichen Schlüssel und aktiviert einfach erneut (in der Regel automatisch beim Start), um die Änderung zu übernehmen.

Widerrufen — einen Schlüssel sperren:

curl -X POST $BASE/admin/licenses/LIC-…/revoke -H "X-Admin-Token: $TOKEN"
# the dashboard's per-row Revoke action does the same. Many at once: POST /admin/licenses/bulk-revoke

Verlängern / Laufzeit erweitern — den Ablauf nach hinten verschieben (und optional die Plätze ändern), ohne neuen Schlüssel:

curl -X POST $BASE/admin/licenses/LIC-…/renew -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
  -d '{"expiryUtc":"2028-10-12T00:00:00Z"}'
# seats can be changed here too; a renewal re-signs the license in place. The key is unchanged.

Beides finden Sie auf der eigenen Seite der Lizenz: Renew sitzt in der Aktionszeile, Revoke in der Danger zone.

Die Lizenzseite von Stark Industries in Keyright: oben in der Aktionszeile eine Schaltfläche Renew (neben Add seats, License file und Send portal link) und unten rechts eine Karte Danger zone mit „Transfer ownership…“ und einer roten Schaltfläche „Revoke…“; die Karte Details zeigt die Edition pro, eine unbefristete Laufzeit und die gebundenen Geräte.
Renew (Aktionszeile) verlängert die Laufzeit an Ort und Stelle auf demselben Schlüssel; Revoke (Danger zone) sperrt ihn — beide signieren die Lizenz neu, und die Anwendung übernimmt die Änderung bei ihrer nächsten Lease-Aktualisierung.

Ablauf ist schlicht das Erreichen des expiryUtc der Lizenz ohne Verlängerung — Sie tun nichts; das unten beschriebene Verhalten setzt von selbst ein. (Eine Rückerstattung/Kündigung aus einem Shop-Webhook widerruft automatisch — siehe Schlüssel automatisch aus einem Shop ausstellen.)

Jeder Zustand dieses Lebenszyklus erscheint in der Liste Licenses, sodass Sie einen widerrufenen, abgelaufenen oder bald ablaufenden Schlüssel auf einen Blick erkennen:

Die Keyright-Liste Licenses mit gemischten Zuständen in der Spalte STATUS: „active“-Markierungen bei Stark Industries, Globex Corporation und Acme Inc.; eine rote „revoked“-Markierung bei Wayne Enterprises; eine graue „expired“-Markierung bei Umbrella Ltd (Ablauf 1. März 2026); und eine gelbe Warnung „in 10 days“ für baldigen Ablauf bei Initech LLC (Ablauf 22. Okt. 2026), mit Ablaufdaten und Platzanzahl pro Zeile.
Die Liste Licenses zeigt den gesamten Lebenszyklus auf einmal — active, revoked, expired und eine Warnung für baldigen Ablauf („in 10 days“) — dieselben Zustände, die Ihre Anwendung aus LicenseInfo.Status liest.

Wie schnell eine Änderung die Maschine erreicht

Ein Widerruf oder eine Verlängerung wird bei der nächsten Online-Prüfung des Geräts angewendet, denn zwischen den Prüfungen läuft die Anwendung offline gegen einen zwischengespeicherten Lease. Die Lease-TTL (Standard 14 Tage, KEYRIGHT_LEASE_TTL_DAYS) ist genau die Stellschraube: Eine verbundene Anwendung, die beim Start erneut aktiviert, übernimmt einen Widerruf innerhalb ihres Aktualisierungsrhythmus; eine Maschine, die offline war, sieht ihn erst, wenn sie wieder online ist — und spätestens dann, wenn die Kulanzfrist ihres Lease verstreicht und sie zur erneuten Prüfung gezwungen wird. Verkürzen Sie die TTL, damit Widerrufe und Platzänderungen schneller greifen, auf Kosten geringerer Offline-Toleranz. Für die Offline-Durchsetzung ganz ohne Netzwerk liefern Sie eine signierte Widerrufsliste mit Ihrem Build aus (RevocationListJson / RevocationListPath), damit auch eine rein offline laufende Anwendung einen Widerruf respektiert.

In Ihrem Code

Ihre Anwendung liest alles aus LicenseInfo — sie parst nie einen Schlüssel. Die relevanten Member, in jedem SDK und über reines HTTP:

.NET

LicenseInfo info = await License.ActivateAsync(key, ct);   // or License.Validate() offline; both fail closed

// Status is the single source of truth — branch on it.
switch (info.Status)
{
    case LicenseStatus.Valid:    break;                     // licensed; fall through to the badge below
    case LicenseStatus.Expired:  return ShowRenewPrompt(info.Message);   // term ended, or trial over
    case LicenseStatus.Revoked:  return ShowUnlicensed(info.Message);    // key was revoked
    default:                     return ShowUnlicensed(info.Message);    // NoLicense, SeatLimit, SignatureInvalid, …
}

// While valid, surface the countdown and nudge before renewal.
if (info.IsExpiringSoon())                                   // true inside the renewal window
    ShowRenewBanner($"{info.DaysRemaining} days left");      // DaysRemaining counts down to expiryUtc
string badge = info.ExpiryUtc is null
    ? "Licensed — perpetual"                                 // no expiry
    : $"Licensed — expires {info.ExpiryUtc:d}";

Node.js

const { info } = license.validate();                 // or: info = await license.activate(key)
switch (info.status) {
  case 'valid':    break;                                      // licensed
  case 'expired':  return showRenewPrompt(info.message);       // term ended, or trial over
  case 'revoked':  return showUnlicensed(info.message);        // key was revoked
  default:         return showUnlicensed(info.message);        // no_license, machine_mismatch, …
}
if (info.daysRemaining != null && info.daysRemaining <= 14)    // nudge before renewal
  showRenewBanner(`${info.daysRemaining} days left`);
const badge = info.expiryUtc ? `Licensed — expires ${info.expiryUtc.toLocaleDateString()}`
                             : 'Licensed — perpetual';

Python

info = license.validate_info()                       # or: info = license.activate(key)
if info.status == LicenseStatus.VALID:
    pass                                             # licensed
elif info.status == LicenseStatus.EXPIRED:
    return show_renew_prompt(info.message)           # term ended, or trial over
elif info.status == LicenseStatus.REVOKED:
    return show_unlicensed(info.message)             # key was revoked
else:
    return show_unlicensed(info.message)             # NO_LICENSE, MACHINE_MISMATCH, …
if info.days_remaining is not None and info.days_remaining <= 14:
    show_renew_banner(f"{info.days_remaining} days left")
badge = "Licensed — perpetual" if info.expiry_utc is None else f"Licensed — expires {info.expiry_utc:%x}"

Java

LicenseInfo info = client.validateInfo();            // or: info = client.activate(key)
switch (info.status) {
    case VALID:   break;                                   // licensed
    case EXPIRED: return showRenewPrompt(info.message);    // term ended, or trial over
    case REVOKED: return showUnlicensed(info.message);     // key was revoked
    default:      return showUnlicensed(info.message);     // NO_LICENSE, MACHINE_MISMATCH, …
}
if (info.isExpiringSoon(14))                               // nudge before renewal
    showRenewBanner(info.daysRemaining() + " days left");
String badge = info.expiryUtc == null ? "Licensed — perpetual"
                                      : "Licensed — expires " + info.expiryUtc;

Jede Sprache (reines HTTP)

curl -s -X POST "$BASE/v1/validate" -H "content-type: application/json" \
  -d '{"key":"LIC-…","machineId":"<stable-machine-id>","product":"acme-app"}'
# status "revoked" -> drop to Free; "expired" -> prompt to renew; "ok" -> verify the lease and read
# licenseExpiryUtc for the countdown. Fail closed on anything but a valid, in-date lease.

Was jede Variante anzeigt, während die Laufzeit ausläuft:

  • DaysRemaining zählt bis expiryUtc herunter; IsExpiringSoon() wird innerhalb des Verlängerungsfensters wahr, sodass Sie den Nutzer ansprechen können, bevor der Zugang endet.
  • Beim Ablauf oder nach einem Widerruf wird IsPaid false, und die Anwendung fällt in ihren Free-/unlizenzierten Zustand zurück — Keyright verhält sich fail-closed, es wirft keine Ausnahme. Status sagt Ihnen, was zutrifft (Expired oder Revoked), damit Sie die Meldung passend formulieren können („verlängern“ vs. „kontaktieren Sie uns“).
  • Nach einer Verlängerung liefert das nächste ActivateAsync/Validate() das spätere ExpiryUtc — keine erneute Schlüsseleingabe, kein Reaktivierungsdialog.

Es gibt keine In-App-„Kulanzfrist“ für eine befristete Lizenz: Sobald expiryUtc überschritten ist (und die Maschine das nächste Mal validiert), ist die Anwendung Expired. Das 14-Tage-Fenster des Lease ist ein Konnektivitäts-Puffer — es lässt eine Maschine offline gegen eine noch gültige Laufzeit laufen — und keine zusätzliche Kulanz nach Ende der bezahlten Laufzeit. Wenn ältere Versionen nach dem Auslaufen eines Abonnements weiterlaufen sollen, ist das das Abonnement mit Fallback der Release-Abdeckung, keine Ablaufkulanz.

Nutzer von reinem HTTP sehen denselben Lebenszyklus über das Feld status von /v1/validate (revoked, expired) und das licenseExpiryUtc des Lease — verifizieren Sie den Lease und verhalten Sie sich fail-closed bei allem außer einem gültigen, nicht abgelaufenen Lease, wie unter Die HTTP-API direkt nutzen beschrieben.

Lebenszyklus der Kundenlizenz vs. Lebenszyklus der selbst gehosteten Instanz

Das sind zwei getrennte Schlüssel mit unterschiedlichen Regeln. Halten Sie sie auseinander:

Kundenlizenz (Ihre Endnutzer)Lizenz der selbst gehosteten Instanz (Ihr eigener Schlüssel)
WessenDie Schlüssel Ihrer Kunden, von Ihnen ausgestelltDas Betriebsrecht Ihrer Instanz, von Delta1 ausgestellt
Gilt fürCloud und Self-Hosting gleichermaßenNur Self-Hosting
Kulanz beim AblaufKeine — Expired, sobald die Laufzeit verstrichen istBezahlt: 15 Tage Nur-Lese-Kulanzfrist nach dem Ablauf; Testversion: keine
Beim StoppAnwendung fällt fail-closed auf Free zurückInstanz sperrt — 402 auf den meisten Pfaden; Status-Endpunkte bleiben erreichbar
Steuerung über/revoke, /renew, expiryUtcKEYRIGHT_SELF_LICENSE tauschen + Neustart

Alles oberhalb der Tabelle ist der Kunden-Lebenszyklus — identisch auf der Cloud und bei Self-Hosting. Der eigene Schlüssel der Instanz ist eine andere Geschichte: Ein selbst gehostetes Deployment lizenziert sich selbst, eine bezahlte Instanz erhält nach ihrem eigenen Ablauf eine 15-tägige Nur-Lese-Kulanzfrist, bevor sie sperrt, und eine Testinstanz stoppt in dem Moment, in dem sie abläuft. Dieser Lebenszyklus — Installation, Verlängerung, das Feld phase auf /admin/self-license und was „gesperrt“ bedeutet — wird vollständig unter Lizenzierung & Editionen behandelt. Verwechseln Sie nicht das Auslaufen des Abonnements eines Kunden (seine Anwendung geht auf Free) mit dem Auslaufen der Lizenz Ihrer Instanz (Ihr gesamter Issuing-Service wird nur-lesend und stoppt dann).

Cloud vs. Self-Hosting

  • $BASE / $TOKEN. Cloud: https://keyright.delta1labs.com + ein Sitzungs-Token. Self-Hosting: die URL Ihrer Instanz + KEYRIGHT_ADMIN_TOKEN.
  • Widerruf, Verlängerung und Ablauf von Kunden-Lizenzen sind in beiden Betriebsarten identisch — gleiche Endpunkte, gleiches SDK-Verhalten.
  • Die Lease-TTL können Sie auf einer selbst gehosteten Instanz selbst einstellen (KEYRIGHT_LEASE_TTL_DAYS); auf der Cloud gilt der Standardwert des Service.
  • Der Instanz-Lebenszyklus existiert nur bei Self-Hosting (siehe oben).

Prüfen

  1. Stellen Sie sich selbst einen befristeten Schlüssel aus, der in ein, zwei Tagen abläuft; aktivieren Sie ihn. Das Badge zeigt den Ablauf und DaysRemaining.
  2. Widerrufen Sie ihn, verbinden Sie sich erneut und lassen Sie den Lease aktualisieren (oder rufen Sie ActivateAsync auf): Die Anwendung fällt mit Status == Revoked auf Free zurück.
  3. Stellen Sie einen frischen Schlüssel aus, aktivieren Sie ihn, verlängern Sie ihn dann auf ein späteres Datum; aktivieren Sie erneut — ExpiryUtc verschiebt sich nach hinten, gleicher Schlüssel, kein Dialog.
  4. Lassen Sie einen kurzfristigen Schlüssel ablaufen und validieren Sie erneut: Status == Expired, IsPaid == false, die Verlängerungsaufforderung erscheint.
  5. Offline-Timing: Widerrufen Sie einen Schlüssel, während diese Maschine offline ist — bestätigen Sie, dass sie weiterläuft, bis sie sich wieder verbindet (oder ihr Lease-Fenster endet), und dann auf Free zurückfällt. Verkürzen Sie KEYRIGHT_LEASE_TTL_DAYS, wenn das zu langsam ist.

Siehe auch