Licensing: 100-day offline cache with anti-rollback + cached server status
- CachedValidityDays bumped 7 → 100 days. Covers the "user goes online once every 3 months for updates" use case without repeatedly nagging for re-auth. - LastValidationAt now uses response.ServerTime (signed Ed25519 by the server) rather than DateTime.UtcNow, so the client's local clock can't be used to forge a fresh validation date. - LastSeenUtc monotonic counter, persisted on every launch as max(stored, now). Combined with a 1h grace window: if the user rolls their PC clock backward to extend the offline cache, the rollback is detected (now < LastSeen - 1h) and the cache is invalidated → forced re-validation next time online. - CachedStatus persists the server-returned status (valid/expired/revoked/ invalid/machine_limit_exceeded) so a revocation done while the user is offline still shows correctly when they next launch with cached data. Auto-override to "expired" if entitlement date has passed (handles the valid → expired transition without needing a server round-trip). - ILicenseService.GetDecryptedKey() exposed for the new auto-revalidation flow. This puts the trust boundary in the right place: cached data is informational offline, the actual download authorization always re-validates against the server (the gate to download is /api/download-url/, which checks the live license state on each call). User can't fake offline-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,4 +18,11 @@ public interface ILicenseService
|
||||
/// auquel cas l'appelant retombe sur l'URL publique du manifest.
|
||||
/// </summary>
|
||||
Task<string?> GetSignedDownloadUrlAsync(string version, CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Décrypte la clé de license stockée en cache (DPAPI CurrentUser). Retourne null
|
||||
/// si pas de clé stockée ou si le déchiffrement échoue (cache déplacé vers une
|
||||
/// autre machine ou autre user Windows).
|
||||
/// </summary>
|
||||
string? GetDecryptedKey();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user