Eine Desktop-App durch Scannen eines QR-Codes aktivieren
Einen 29-stelligen Lizenzschlüssel an einem Kiosk, einer TV-Box oder einem gesperrten Arbeitsplatz einzutippen ist fehleranfällig und mühsam. So baust du mit Keyright einen Geräte-Pairing-Aktivierungsfluss für eine .NET-Desktop-App: Die App zeigt einen QR-Code, der Nutzer bestätigt auf seinem Smartphone, und der Desktop fragt eine signierte Aktivierung ab, die er zwischenspeichert und offline validiert.
Ein Lizenzschlüssel ist ein gutes Berechtigungsmerkmal und eine schreckliche Sache zum Eintippen. An einem Arbeitsplatz mit Tastatur ist er ein leichtes Ärgernis; auf den Oberflächen, auf denen Desktop-Apps zunehmend leben – ein Empfangskiosk, ein Digital-Signage-Player, eine TV-artige App, die per Fernbedienung gesteuert wird, eine gesperrte Maschine, auf der die Richtlinie das Einfügen deaktiviert – ist er schlicht mühsam. Ein Keyright-Schlüssel ist gruppierte, mit Bindestrichen getrennte, groß-/kleinschreibungssensible Entropie, typischerweise 25 bis 29 Zeichen. Bitte jemanden, das mit einer Bildschirmtastatur und einem Steuerkreuz einzugeben, und du hast ein Support-Ticket entworfen.
Die Lösung ist kein kürzerer Schlüssel – das würde ihn schwächen. Die Lösung ist, die Schlüsseleingabe vollständig vom unhandlichen Gerät wegzunehmen. Die Desktop-App zeigt einen QR-Code an; der Nutzer scannt ihn mit dem Smartphone, das er ohnehin in der Tasche hat, gibt (oder fügt) den Schlüssel dort ein, wo Tippen leicht ist, bestätigt, und der Desktop erhält seine signierte Aktivierung über einen Rückkanal. Das ist dieselbe Form wie der OAuth-2.0-Device-Authorization-Grant, auf die Lizenzierung übertragen, und das .NET-SDK von Keyright liefert die beiden Aufrufe, die du zum Bauen brauchst.
Kernaussage: Pairen, nicht tippen. Lass die Desktop-App eine Geräteaktivierung starten, den zurückgegebenen Pairing-Code als QR rendern und abfragen. Der Nutzer bestätigt auf seinem Smartphone mit dem echten Schlüssel. Die signierte Lizenz kommt über den Rückkanal zurück zum Desktop – niemals im QR – und wird für ein Offline-Validate() bei jedem weiteren Start zwischengespeichert. Der QR trägt nur einen kurzlebigen, einmalig verwendbaren Pairing-Code, sodass ein abfotografierter Bildschirm nichts gewährt.
Der Ablauf auf einen Blick
Drei Parteien sind beteiligt: die Desktop-App, die lizenziert werden möchte, der ausstellende Dienst (deine selbst gehostete Keyright-Instanz) und das Smartphone, auf dem der Nutzer bestätigt. Der Desktop sieht niemals den Schlüssel; das Smartphone sieht niemals die signierte Lizenz. Jedes bleibt auf dem Kanal, in dem es gut ist.
Die entscheidende Eigenschaft steckt in Schritt 5: Was das Produkt tatsächlich freischaltet, wandert vom Dienst zum Desktop, über einen Kanal, den das Smartphone des Nutzers niemals berührt. Der QR in Schritt 1 enthält nur den Pairing-Code und die URL.
Schritt 1 – Aktivierung starten und den QR rendern
Der Desktop ruft BeginDeviceActivationAsync einmal auf, in dem Moment, in dem der Nutzer eine Aktivierung anfordert. Es gibt ein DeviceActivationRequest zurück: einen DeviceCode, den der Desktop zum Abfragen privat hält, einen kurzen, menschenlesbaren UserCode zur Anzeige als Ausweichlösung, eine VerificationUrl und eine fertige VerificationUrlComplete, die den Code in die URL einfaltet, sodass das Smartphone überhaupt nichts von Hand eingeben muss.
using Delta1Labs.Keyright;
static readonly KeyrightClient License = KeyrightClient.Initialize(new KeyrightOptions
{
Product = "lobby-kiosk",
PublicKeyBase64 = "MIIBIjANBgkq...", // verify-only public key, pinned
ServiceUrl = "https://keyright.example.com" // your self-hosted instance
});
DeviceActivationRequest req = await License.BeginDeviceActivationAsync(ct);
// Encode the *complete* verification URL (verify_url + user_code) as a QR.
// Anything that turns a string into a QBitmap works; QRCoder shown here.
using var gen = new QRCoder.QRCodeGenerator();
var data = gen.CreateQrCode(req.VerificationUrlComplete, QRCoder.QRCodeGenerator.ECCLevel.Q);
var png = new QRCoder.PngByteQRCode(data).GetGraphic(8);
ShowQrOnScreen(png);
// Always show the short code and URL as a fallback for a phone that can't scan.
ShowText($"On your phone, go to {req.VerificationUrl} and enter: {req.UserCode}");
Was in den QR kommt, ist genau VerificationUrlComplete – eine URL plus der Pairing-Code, nicht mehr. In diesem Bild gibt es keinen Lizenzschlüssel und kein signiertes Token. Der Pairing-Code ist einmalig verwendbar und läuft bei req.ExpiresAt ab (Minuten, nicht Stunden), sodass ein abfotografierter Bildschirm nur zu einer Bestätigungsseite führt, die weiterhin den echten Schlüssel verlangt, und auch nur, bis der Code verfällt.
Schritt 2 – die signierte Aktivierung abfragen
Während der QR auf dem Bildschirm ist, fragt der Desktop PollDeviceActivationAsync mit dem privaten DeviceCode ab. Das SDK berücksichtigt das Abfrageintervall des Servers und stellt ein kleines Status-Enum bereit, sodass du die Oberfläche steuern kannst, ohne für die gewöhnlichen „Noch nicht”-Zustände Ausnahmen abzufangen.
LicenseInfo? activated = null;
var deadline = req.ExpiresAt;
while (DateTimeOffset.UtcNow < deadline)
{
DeviceActivationPoll poll = await License.PollDeviceActivationAsync(req.DeviceCode, ct);
switch (poll.Status)
{
case DeviceActivationStatus.Pending: // user hasn't approved yet
await Task.Delay(poll.Interval, ct); // respect server backoff
continue;
case DeviceActivationStatus.SlowDown: // we're polling too fast
await Task.Delay(poll.Interval + TimeSpan.FromSeconds(5), ct);
continue;
case DeviceActivationStatus.Approved:
activated = poll.License; // signed license, already cached
break;
case DeviceActivationStatus.Denied:
case DeviceActivationStatus.Expired:
ShowError($"Activation {poll.Status}. Start over to try again.");
return;
}
if (activated is not null) break;
}
if (activated is { IsLicensed: true } info)
{
ShowLicensedUi(info.Tier);
logger.LogInformation("Activated {Tier}, bound to {Id}", info.Tier, info.MachineId);
}
Wenn der Status auf Approved umspringt, hat das SDK die signierte Lizenz bereits in seinen lokalen Cache geschrieben und die Aktivierung an den Fingerabdruck dieser Maschine gebunden (oder an eine MachineId, die du in KeyrightOptions angeheftet hast, falls du die Identität selbst verwaltest – nützlich für neu bespielte Kioske). Das LicenseInfo, das du zurückbekommst, ist dasselbe Objekt, das jeder andere Keyright-Pfad zurückgibt, sodass der Rest deiner App weder weiß noch sich darum kümmert, dass die Aktivierung per QR erfolgte.
Schritt 3 – was der Nutzer auf dem Smartphone tut
Die Smartphone-Seite ist bewusst langweilig, und genau das ist der Punkt. Der Nutzer scannt den QR, der die Verifizierungsseite öffnet. Er gibt den Lizenzschlüssel ein oder fügt ihn ein – auf einer echten Tastatur, mit normal funktionierendem Autovervollständigen und Einfügen – und bestätigt. Die Bestätigungsseite nennt das Produkt und die Maschine, die sie gleich lizenzieren wird, damit der Nutzer sieht, was er autorisiert.
Da der Schlüssel auf dem Smartphone eingegeben und die signierte Lizenz an den Desktop geliefert wird, passiert der Schlüssel niemals die Eingabe des Kiosks, seine Zwischenablage oder seinen Bildschirm. Für ein gemeinsam genutztes oder öffentliches Terminal ist das eine echte Sicherheitsverbesserung gegenüber dem Eintippen des Schlüssels in das Feld vor aller Augen.
Falls ein Smartphone nicht scannen kann – eine alte Kamera, ein Unternehmens-MDM, das den Scanner blockiert – sind der gedruckte UserCode und die VerificationUrl die Ausweichlösung. Ein gruppierter Nutzercode aus sechs bis acht Zeichen ist selbst auf einer schlechten Tastatur erträglich einzugeben, was genau der Grund ist, warum BeginDeviceActivationAsync einen kurzen Code zurückgibt, der sich vom langen Lizenzschlüssel unterscheidet.
Nach dem Pairing: offline validieren, für immer
Das Pairing ist ein einmaliger Online-Handshake. Alles danach ist der gewöhnliche Offline-Pfad von Keyright. Bei jedem Start ruft die App Validate() auf, das die zwischengespeicherte signierte Lizenz gegen den angehefteten öffentlichen Schlüssel prüft, ohne jeglichen Netzwerkaufruf – eine Signaturprüfung und eine Ablaufprüfung, nicht mehr.
LicenseInfo info = License.Validate(); // offline, no I/O, never throws
if (!info.IsLicensed)
{
// Cache missing or cleared (re-image, wiped profile). Re-pair with the QR flow.
StartDevicePairing();
return;
}
bool signage = info.Entitlements.IsEnabled("digital-signage");
int maxScreens = (int)info.Entitlements.GetLimit("screens", 1);
So besteht der gesamte Netzwerkaufwand aus einem Pairing pro Maschine. Ein Kiosk, der neu bespielt wird, leert den Cache und pairt sich einfach neu – ein dreißigsekündiger QR-Scan während der Bereitstellung, kein von einem Techniker eingetippter Schlüssel. Wenn du auch eine kostenlose Stufe lizenzierst, fällt eine ungepairte Maschine auf die Community Edition zurück, statt dunkel zu werden: Validate() gibt ein LicenseInfo der Edition Community zurück, dessen Berechtigungen du prüfst, und der QR-Fluss stuft es an Ort und Stelle hoch, wenn jemand einen bezahlten Schlüssel pairt.
Den Fluss härten
Ein paar Regeln halten das Geräte-Pairing ehrlich:
- Lege niemals etwas Signiertes in den QR. Der QR ist ein Pairing-Code und eine URL. Die Lizenz – das, was die Berechtigungen gewährt – kommt nur über den abgefragten Rückkanal zurück. Behandle einen durchgesickerten QR als wertlos durch Design, nicht durch Verschleierung.
- Halte den Pairing-Code kurzlebig und einmalig verwendbar.
ExpiresAtsollte im Minutenbereich liegen. Nach Bestätigung oder Ablauf darf derDeviceCodenie wieder aktivieren. Das SDK erzwingt dies serverseitig; zeige keinen veralteten QR erneut an. - Berücksichtige
SlowDown. Das Abfrageintervall wird vom Dienst gesetzt, um sich zu schützen. Das SDK stellt es bereit; drossle, wenn du dazu aufgefordert wirst, und höre beiExpiresAtauf abzufragen, statt für immer. - Zeige dem Nutzer, was er bestätigt. Die Bestätigungsseite, die Produkt und Maschine nennt, verhindert, dass ein Phishing-QR einen Schlüssel stillschweigend an das Gerät eines Angreifers bindet – der Nutzer sieht einen unbekannten Maschinennamen und lehnt ab.
- Hefte den öffentlichen Schlüssel an. Wie bei jeder Keyright-Integration ist
PublicKeyBase64ein nur zur Verifizierung dienender Schlüssel, der in die App kompiliert wird. Das Offline-Validate()ist nur so vertrauenswürdig wie diese Anheftung.
Zusammenfassung
Einen Lizenzschlüssel einzutippen ist die falsche Aufgabe für einen Kiosk, eine Signage-Box oder eine per Fernbedienung gesteuerte TV-artige App, also verlange es nicht vom Desktop. Starte eine Geräteaktivierung, rendere den zurückgegebenen Pairing-Code als QR und frage ab: Der Nutzer bestätigt auf dem Smartphone, auf dem er ohnehin bequem tippt, die signierte Lizenz wird über einen Rückkanal an den Desktop geliefert, den das Smartphone niemals berührt, und von da an validiert die App offline mit Validate() wie jede andere Keyright-Integration. Der QR enthält nur einen kurzlebigen, einmalig verwendbaren Pairing-Code, sodass ein abfotografierter Bildschirm nichts gewährt. Das Keyright-.NET-SDK gibt dir BeginDeviceActivationAsync und PollDeviceActivationAsync für den Handshake und dasselbe fail-closed LicenseInfo für alles danach, sodass du die eingabefeindlichste Oberfläche, die du auslieferst, mit einem dreißigsekündigen Scan lizenzieren kannst.
Nebula.NET testen
Härten Sie Ihren .NET-Code in wenigen Minuten — starten Sie mit der kostenlosen Edition.