Skip to content
← Tous les articles
· Delta1 Labs LicensingGuide

Que doit faire votre app quand le serveur de licences est en panne

Une vérification de licence qui échoue brutalement dès que le serveur est injoignable transforme votre panne — ou le Wi-Fi capricieux du client — en la leur. Voici comment concevoir des fenêtres de grâce, choisir fail-open vs fail-closed par niveau, et empêcher qu'une coupure réseau passagère ne verrouille des clients payants.

Toute vérification de licence en ligne a un mode d”échec que la plupart des équipes ne conçoivent pas : le serveur n”est tout simplement pas joignable. Peut-être que votre service de licences a une mauvaise journée ; peut-être que le proxy d”entreprise du client a avalé la requête ; peut-être que son portable est dans un train. Si votre vérification traite « je n”ai pas pu joindre le serveur » comme « le serveur a dit que cette licence est invalide », alors votre panne devient la panne de votre client — et un blip réseau de trente secondes verrouille un utilisateur payant hors d”un logiciel qu”il possède. Le remède est de concevoir explicitement pour l”injoignabilité, avec des fenêtres de grâce et une politique délibérée de fail-open/fail-closed.

« Non » et « je ne sais pas » sont des réponses différentes

La distinction la plus importante en licensing résilient est entre deux résultats très différents d”un check-in :

  • Un négatif autoritatif — vous avez joint le serveur et il a dit que cette licence est expirée, révoquée ou au-delà de son nombre de sièges. C”est un « non » réel, et il doit prendre effet.
  • Un résultat non concluant — vous n”avez pas pu joindre le serveur du tout : échec DNS, timeout, 503, erreur TLS. Ce n”est pas un « non ». C”est « je ne sais pas pour l”instant ».

Une vérification naïve fusionne les deux en « non valide → arrête ». C”est le bug. La cause de loin la plus probable d”un résultat non concluant est un problème réseau passager, pas un client qui a piraté votre logiciel en pleine session. Traiter le silence comme un refus punit la majorité honnête pour incommoder un attaquant qui a de toute façon des options bien plus faciles (il peut simplement tourner hors ligne). Le licensing résilient garde les deux cas séparés et répond à chacun comme il convient.

Le lease en cache est ce sur quoi vous vous repliez

La résilience repose sur un lease signé que l”app détient déjà de son dernier check-in réussi — la même primitive de validation hors ligne décrite dans validation de licence hors ligne. Le lease est une déclaration signée par le serveur, « cette licence est valide jusqu”au temps T », que l”app peut vérifier localement avec une clé publique embarquée, sans réseau. Sa fenêtre de validité est la colonne vertébrale de la grâce : entre les check-ins l”app fait confiance au lease, et quand un check-in ne peut pas aboutir, elle continue de faire confiance au lease jusqu”à ce que cette fenêtre — plus une période de grâce explicite — s”épuise.

Le paramètre de conception clé est de rendre la fenêtre du lease confortablement plus longue que l”intervalle de check-in. Si vous faites un check-in quotidien mais émettez un lease de 7 jours, un client peut être hors ligne (ou votre serveur en panne) la majeure partie d”une semaine avant que quoi que ce soit ne se dégrade. Un check-in, alors, n”est pas une barrière qui doit passer à chaque lancement ; c”est un rafraîchissement opportuniste qui prolonge la piste :

async Task<LicenseState> EvaluateAsync(CachedLease lease, DateTime now)
{
    try
    {
        var fresh = await _server.CheckInAsync(lease.Key);   // reach the server
        if (fresh.Status == Status.Revoked || fresh.Status == Status.Expired)
            return LicenseState.Denied(fresh.Status);        // authoritative NO — act on it
        _store.Save(fresh.Lease);                            // refresh: extend the runway
        return LicenseState.Active(fresh.Lease);
    }
    catch (Exception)        // timeout, DNS, 5xx, TLS — INCONCLUSIVE, not a denial
    {
        return EvaluateOffline(lease, now);                  // fall back to the cached lease
    }
}

LicenseState EvaluateOffline(CachedLease lease, DateTime now)
{
    if (now <= lease.ValidThroughUtc)
        return LicenseState.Active(lease);                   // still inside the lease window
    if (now <= lease.ValidThroughUtc + GracePeriod)
        return LicenseState.Grace(lease, until: lease.ValidThroughUtc + GracePeriod);
    return LicenseState.NeedsReconnect();                    // runway exhausted — degrade, don't crash
}

Remarquez l”asymétrie : une réponse Revoked/Expired termine la session, mais toute exception se replie sur le lease. L”erreur réseau ne refuse jamais ; seul le serveur refuse.

lease validetourne normalementpériode de grâcetourne encoreaprès la grâcedégrader / reconnexionlease ValidThrough (T)T + grâce

Échouez en ouvert, puis dégradez — rarement verrouillez en dur

Les deux cas séparés, la politique s”écrit d”elle-même pour la plupart des produits :

  1. Dans la fenêtre du lease : tournez normalement. Rien à décider.
  2. Après le lease, dans la grâce : tournez normalement, mais commencez à alerter — un discret bandeau « nous n”avons pas pu vérifier votre licence ; nous continuerons d”essayer ». Réessayez en arrière-plan avec un backoff exponentiel (ne martelez pas un serveur qui souffre peut-être déjà).
  3. Après la grâce : dégradez, ne plantez pas. Passez en lecture seule, désactivez les fonctions payantes, ou bloquez le travail nouveau en laissant l”utilisateur sauvegarder et exporter ce qu”il a. Un message clair « reconnectez-vous pour continuer » transforme une impasse en un problème résoluble.

Le principe directeur est que votre licensing doit échouer sûr pour le client, pas échouer agressif. Le coût de verrouiller par erreur un client payant pendant votre propre panne — tickets de support, remboursements, attrition, réputation — éclipse le coût d”un pirate déterminé obtenant quelques jours supplémentaires de grâce qu”il aurait de toute façon pu obtenir en restant hors ligne. Les produits cadrés par droits se dégradent particulièrement bien : vous pouvez désactiver les drapeaux premium tout en laissant l”app centrale utilisable.

Quand le fail-closed est le bon choix

Fail-open-dans-la-grâce est le bon défaut, pas une loi universelle. Deux situations justifient un comportement plus strict :

  • Une révocation autoritative. Si le serveur est joignable et renvoie « révoquée » — un remboursement, un rejet de paiement, une clé compromise — c”est un non réel et doit prendre effet rapidement, c”est pourquoi la révocation emprunte la voie du check-in et n”est pas soumise à la fenêtre de grâce. La grâce couvre le silence, jamais un refus explicite.
  • Niveaux à forte valeur ou soumis à conformité. Pour un modèle flottant/concurrent où un siège doit être libéré, ou un déploiement réglementé où l”usage non vérifié est en soi un problème, un lease plus court et une grâce plus courte sont appropriés — le modèle économique, pas le réseau, fixe la tolérance. Faites-en une politique par niveau : une app grand public peut se permettre une semaine généreuse de grâce ; un outil serveur à sièges concurrents pourrait n”autoriser que des heures.

Le point est que le fail-closed doit être un choix délibéré pour des niveaux spécifiques, dicté par la valeur en jeu — pas le défaut accidentel que vous obtenez en traitant un timeout comme un refus.

Régler les boutons

Trois paramètres façonnent toute l”expérience, et ils devraient être explicites, pas émergents :

  • Fenêtre de validité du lease — combien un seul check-in réussi achète. Plus longue = plus résiliente aux pannes, plus lente à refléter une révocation. Des jours pour la plupart des logiciels desktop/B2B.
  • Période de grâce — du temps supplémentaire après le lease avant de dégrader. Une marge de sécurité spécifiquement pour vos pannes ; même un jour réduit significativement les faux verrouillages.
  • Cadence de check-in + backoff — à quelle fréquence vous rafraîchissez quand tout va bien, et comment vous réessayez en cas d”échec. Rafraîchissez bien avant l”expiration du lease (pour que quelques check-ins manqués soient sans conséquence), et faites un backoff à l”échec pour ne pas piétiner un serveur en difficulté.

Réglez-les par niveau et vous obtenez la résilience par construction : les pannes brèves sont invisibles, les plus longues se dégradent en douceur avec un message clair, et seul un « non » réel et autoritatif arrête net un client.

À retenir

Une vérification de licence n”est pas juste une barrière oui/non — elle a un troisième état, « je n”ai pas pu demander », et la façon dont vous gérez cet état est ce qui sépare le licensing qui protège vos revenus de celui qui détruit occasionnellement votre bonne volonté. Mettez en cache un lease signé, donnez-lui une fenêtre plus longue que votre intervalle de check-in, ajoutez une période de grâce par-dessus, et faites de l”état terminal une dégradation gracieuse avec un chemin de retour. Traitez le « non » du serveur comme autoritatif et le silence du réseau comme « pas encore ». Faites cela, et la prochaine fois que votre service de licences aura une mauvaise heure, vos clients ne le remarqueront même pas.

Essayez Nebula.NET

Renforcez votre code .NET en quelques minutes — commencez avec l'édition gratuite.