Activer une application de bureau en scannant un QR code
Saisir une clé de licence de 29 caractères sur une borne, un boîtier TV ou un poste verrouillé est source d'erreurs et pénible. Voici comment construire un flux d'activation par appairage d'appareils pour une application de bureau .NET avec Keyright : l'app affiche un QR code, l'utilisateur approuve sur son téléphone, et le bureau interroge une activation signée qu'il met en cache et valide hors ligne.
Une clé de licence est un bon justificatif et une très mauvaise chose à saisir. Sur un poste doté d’un clavier, c’est une gêne mineure ; sur les surfaces où vivent de plus en plus les applications de bureau — une borne d’accueil, un lecteur d’affichage dynamique, une application de type TV pilotée par une télécommande, une machine verrouillée où la politique désactive le collage — c’est franchement pénible. Une clé Keyright est de l’entropie groupée, séparée par des tirets et sensible à la casse, généralement de 25 à 29 caractères. Demandez à quelqu’un de la saisir avec un clavier à l’écran et une croix directionnelle et vous aurez conçu un ticket de support.
La solution n’est pas une clé plus courte — cela l’affaiblirait. La solution est de sortir entièrement la saisie de la clé de l’appareil incommode. L’application de bureau affiche un QR code ; l’utilisateur le scanne avec le téléphone déjà dans sa poche, saisit (ou colle) la clé là où taper est facile, approuve, et le bureau reçoit son activation signée par un canal retour. C’est la même forme que l’octroi d’autorisation d’appareil d’OAuth 2.0, adapté à la gestion de licences, et le SDK .NET de Keyright fournit les deux appels dont vous avez besoin pour la construire.
À retenir : appairez, ne saisissez pas. Faites en sorte que l’application de bureau démarre une activation d’appareil, affiche le code d’appairage renvoyé sous forme de QR, et interroge le service. L’utilisateur approuve sur son téléphone avec la vraie clé. La licence signée revient au bureau par le canal retour — jamais à l’intérieur du QR — et est mise en cache pour un Validate() hors ligne à chaque lancement suivant. Le QR ne porte qu’un code d’appairage de courte durée et à usage unique, donc un écran photographié n’accorde rien.
Le flux en un coup d’œil
Trois parties participent : l’application de bureau qui veut être licenciée, le service émetteur (votre instance Keyright auto-hébergée) et le téléphone sur lequel l’utilisateur approuve. Le bureau ne voit jamais la clé ; le téléphone ne voit jamais la licence signée. Chacun reste sur le canal où il excelle.
La propriété critique se trouve à l’étape 5 : ce qui débloque réellement le produit voyage du service au bureau, par un canal que le téléphone de l’utilisateur ne touche jamais. Le QR de l’étape 1 ne contient que le code d’appairage et l’URL.
Étape 1 — démarrer l’activation et afficher le QR
Le bureau appelle BeginDeviceActivationAsync une fois, au moment où l’utilisateur demande à activer. Il renvoie un DeviceActivationRequest : un DeviceCode que le bureau garde privé pour l’interrogation, un UserCode court et lisible à afficher en secours, une VerificationUrl et une VerificationUrlComplete prête à l’emploi qui intègre le code dans l’URL afin que le téléphone n’ait rien à saisir à la main.
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}");
Ce qui entre dans le QR est exactement VerificationUrlComplete — une URL plus le code d’appairage, rien de plus. Il n’y a aucune clé de licence ni aucun jeton signé dans cette image. Le code d’appairage est à usage unique et expire à req.ExpiresAt (des minutes, pas des heures), donc un écran photographié ne mène qu’à une page d’approbation qui exige toujours la vraie clé, et seulement jusqu’à ce que le code expire.
Étape 2 — interroger l’activation signée
Pendant que le QR est à l’écran, le bureau interroge PollDeviceActivationAsync avec le DeviceCode privé. Le SDK respecte l’intervalle d’interrogation du serveur et expose une petite énumération d’état pour piloter l’interface sans intercepter d’exceptions pour les états ordinaires de « pas encore ».
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);
}
Lorsque l’état passe à Approved, le SDK a déjà écrit la licence signée dans son cache local et lié l’activation à l’empreinte de cette machine (ou à un MachineId que vous avez épinglé dans KeyrightOptions, si vous gérez l’identité vous-même — utile pour des bornes ré-imagées). Le LicenseInfo que vous récupérez est le même objet que renvoie tout autre chemin de Keyright, donc le reste de votre app ne sait ni ne se soucie que l’activation se soit faite par QR.
Étape 3 — ce que l’utilisateur fait sur le téléphone
Le côté téléphone est délibérément ennuyeux, et c’est précisément le but. L’utilisateur scanne le QR, qui ouvre la page de vérification. Il saisit ou colle la clé de licence — sur un vrai clavier, avec l’autocomplétion et le collage qui fonctionnent normalement — et approuve. La page d’approbation confirme le produit et la machine qu’elle est sur le point de licencier pour que l’utilisateur voie ce qu’il autorise.
Comme la clé est saisie sur le téléphone et que la licence signée est livrée au bureau, la clé ne transite jamais par l’entrée de la borne, son presse-papiers ni son écran. Pour un terminal partagé ou public, c’est une réelle amélioration de sécurité par rapport à la saisie de la clé dans le champ sous les yeux de tout le monde.
Si un téléphone ne peut pas scanner — une vieille caméra, un MDM d’entreprise qui bloque le scanner — le UserCode et la VerificationUrl imprimés sont le secours. Un code utilisateur groupé de six à huit caractères est tolérable à saisir même sur un mauvais clavier, ce qui est précisément la raison pour laquelle BeginDeviceActivationAsync renvoie un code court distinct de la longue clé de licence.
Après l’appairage : valider hors ligne, pour toujours
L’appairage est une poignée de main en ligne unique. Tout ce qui suit est le chemin hors ligne habituel de Keyright. À chaque lancement, l’app appelle Validate(), qui vérifie la licence signée mise en cache contre la clé publique épinglée sans aucun appel réseau — une vérification de signature et un contrôle d’expiration, rien de plus.
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);
Ainsi, le coût total du réseau est d’un appairage par machine. Une borne qui est ré-imagée vide le cache et se ré-appaire simplement — un scan de QR de trente secondes lors du provisionnement, pas une clé saisie par un technicien. Si vous licenciez aussi un palier gratuit, une machine non appairée retombe sur Community Edition au lieu de s’éteindre : Validate() renvoie un LicenseInfo d’édition Community dont vous contrôlez les droits, et le flux QR le met à niveau sur place quand quelqu’un appaire une clé payante.
Durcir le flux
Quelques règles maintiennent l’appairage d’appareils honnête :
- Ne mettez jamais rien de signé dans le QR. Le QR est un code d’appairage et une URL. La licence — ce qui accorde les droits — revient uniquement par le canal retour interrogé. Traitez un QR divulgué comme inutile par conception, pas par obscurité.
- Gardez le code d’appairage de courte durée et à usage unique.
ExpiresAtdevrait être de l’ordre de minutes. Une fois approuvé ou expiré, leDeviceCodene doit plus jamais activer. Le SDK l’impose côté serveur ; ne réaffichez pas un QR périmé. - Respectez
SlowDown. L’intervalle d’interrogation est fixé par le service pour se protéger. Le SDK l’expose ; ralentissez quand on vous le dit, et arrêtez d’interroger àExpiresAtplutôt que pour toujours. - Montrez à l’utilisateur ce qu’il approuve. La page d’approbation qui nomme le produit et la machine est ce qui empêche un QR d’hameçonnage de lier silencieusement une clé à l’appareil d’un attaquant — l’utilisateur voit un nom de machine inconnu et refuse.
- Épinglez la clé publique. Comme dans toute intégration Keyright,
PublicKeyBase64est une clé de vérification seule compilée dans l’app. LeValidate()hors ligne n’est fiable que dans la mesure de cet épinglage.
Résumé
Saisir une clé de licence est la mauvaise tâche pour une borne, un boîtier d’affichage ou une application de type TV pilotée par une télécommande, alors ne demandez pas au bureau de le faire. Démarrez une activation d’appareil, affichez le code d’appairage renvoyé sous forme de QR, et interrogez le service : l’utilisateur approuve sur le téléphone sur lequel il tape déjà confortablement, la licence signée est livrée au bureau par un canal retour que le téléphone ne touche jamais, et à partir de là l’app valide hors ligne avec Validate() comme toute autre intégration Keyright. Le QR ne contient qu’un code d’appairage de courte durée et à usage unique, donc un écran photographié n’accorde rien. Le SDK .NET de Keyright vous donne BeginDeviceActivationAsync et PollDeviceActivationAsync pour la poignée de main et le même LicenseInfo en échec fermé pour tout ce qui suit, afin que vous puissiez licencier la surface la plus hostile à la saisie que vous livriez avec un scan de trente secondes.
Essayez Nebula.NET
Renforcez votre code .NET en quelques minutes — commencez avec l'édition gratuite.