Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight
Blog
unreal-engine cpp license-keys offline

License Your Unreal Engine Game Offline in an Afternoon

4 min read Nicolas Demanez — Founder

A few months ago I watched a small Unreal Engine indie studio lose a noticeable percentage of their first-week revenue to piracy. Not catastrophic, but real — and entirely avoidable. Their licensing was a roll-your-own key check against a server with no offline fallback, which meant players in low-connectivity situations were bouncing off it too. Two problems for the price of one.

The right architecture for game licensing has been known for a while: tamper-proof signed leases verified locally, with online revalidation running in the background. The Swift SDK has provided this for Apple platforms since Keylight launched. Now there’s a native path for Unreal: the Keylight C++ plugin drops into your Plugins/ directory and exposes a Blueprint-callable subsystem — UKeylightSubsystem — that handles activation, offline lease storage, and background revalidation using Unreal’s own HTTP module.

Here is what that looks like in practice.

The problem with game licensing

Most indie Unreal games that sell direct skip licensing entirely, rely on a storefront to handle it, or wire up a basic server check that fails offline. The first option leaves revenue on the table. The second gives the storefront 30% and your customer data. The third is fragile in exactly the conditions games run in — flights, hotel wifi, LAN parties, play sessions that outlast a connection drop.

The fundamental requirement is an offline-first architecture: the license check runs locally against a cryptographic signature, not against a live server. The server is involved at activation time and periodically in the background, but never on the critical path between the player pressing “Play” and the game loading.

This is what Ed25519-signed offline leases give you. The server signs a payload containing the player’s entitlements and an expiry. Your game ships with the corresponding public key. At every launch, you verify the signature locally — a fast operation with no network dependency. If the signature is valid and the fields pass, the game loads. If Keylight is unreachable for a week, your players notice nothing.

Setting up the plugin

The plugin ships as source — drop it into your project’s Plugins/ directory and add it to your .uproject file:

{
  "Name": "Keylight",
  "Enabled": true
}

No third-party HTTP libraries required. The plugin uses FHttpModule, which ships with every Unreal Engine installation.

Activating from C++

On first launch — or when a player enters a license key — activate against the Keylight API:

#include "KeylightSubsystem.h"

void AYourGameMode::BeginPlay()
{
    Super::BeginPlay();

    UKeylightSubsystem* Keylight = GetGameInstance()
        ->GetSubsystem<UKeylightSubsystem>();

    // Trusted Ed25519 public keys (kid -> base64) from your dashboard.
    TMap<FString, FString> TrustedKeys;
    TrustedKeys.Add(TEXT("k1"), TEXT("<base64-public-key>"));
    Keylight->Configure(TEXT("your-tenant"), TEXT("your-game"), TrustedKeys);

    // Check the cached lease first — no network call if a valid lease exists.
    if (Keylight->GetState() == EKeylightState::Licensed)
    {
        UnlockContent();
        return;
    }

    // No valid lease — show activation prompt.
    ShowLicensePrompt();
}

void AYourGameMode::OnPlayerEntersKey(const FString& LicenseKey)
{
    UKeylightSubsystem* Keylight = GetGameInstance()
        ->GetSubsystem<UKeylightSubsystem>();

    // Bind once, then activate. OnActivateComplete fires on the game thread.
    Keylight->OnActivateComplete.AddDynamic(
        this, &AYourGameMode::OnActivationResult);
    Keylight->Activate(LicenseKey);
}

// Mark UFUNCTION() in your header. Signature matches FOnKeylightResult.
void AYourGameMode::OnActivationResult(
    bool bSuccess, EKeylightState State, const FString& Message)
{
    if (State == EKeylightState::Licensed)
    {
        // Signed lease stored locally — game proceeds
        UnlockContent();
    }
    else
    {
        ShowActivationError();
    }
}

After a successful activation, the signed lease is stored locally. The next launch reads and verifies that lease without touching the network.

Gating content from Blueprints

UKeylightSubsystem is Blueprint-callable, so you can gate content without writing C++. In any Blueprint — your game mode, a character class, a UI widget:

[Event BeginPlay]
    → [Get Keylight Subsystem]
    → [Has Entitlement] ("pro")
    → [Branch]
        True  → [Unlock Pro Content Node]
        False → [Show License Prompt Widget]

HasEntitlement reads from the cached, signature-verified lease — it is a local operation that works offline. Define entitlement labels in your Keylight dashboard; the subsystem checks them against what the signed lease actually grants.

The four states you work with:

StateWhat it means
LicensedValid signed lease on disk
TrialWithin the trial window
ExpiredLease needs renewal
InvalidNo valid lease — prompt activation

What happens offline

After the first activation, the subsystem stores the Ed25519-signed lease using Unreal’s project directory path. On every subsequent launch:

  1. It loads the lease from disk.
  2. It verifies the Ed25519 signature against the bundled public key — a local operation, no network.
  3. If the signature is valid and the expiry has not passed, it resolves Licensed and calls into your delegate.

Background revalidation runs periodically when connectivity is available. That is the moment revocations propagate — a refunded key gets rejected on the next successful server contact, not during an active session. A player mid-game is never interrupted by a network state change.

This matches how players expect games to behave. A valid license always works.

The Stripe side

You do not wire Stripe yourself. Connect your Stripe account in the Keylight dashboard, configure your game as a product, and set a price. When a player completes checkout, Keylight’s webhook handler mints and signs a license key and sends it by email automatically. Your game’s activation endpoint is already live the moment you finish setup.

Wrapping up

The gap between “I want to sell direct” and “I have working offline licensing” used to be a week or two of custom backend work. The Keylight C++ plugin collapses it to an afternoon: drop the plugin into Plugins/, configure the subsystem, activate on first launch, gate content from C++ or Blueprints.

For the full integration reference — configuration options, multi-entitlement setup, and the offline lease format — see Licensing for Unreal Engine games.

If you hit something this post does not cover, send your feedback and I’ll extend it.

— Nicolas Demanez — Founder

Frequently asked

Does the Keylight C++ plugin work with UE5?+

Yes. The plugin ships as Unreal Engine source targeting UE5 and uses FHttpModule for network requests — a module that ships with every Unreal installation. Drop it into Plugins/ and add it to your .uproject file.

How does offline verification work in an Unreal game?+

At activation, UKeylightSubsystem receives an Ed25519-signed lease from the server and stores it locally. On subsequent launches, it verifies the signature against the bundled public key — no network call needed. Background revalidation picks up revocations when connectivity is available.

Do I need a backend server for this?+

No. UKeylightSubsystem calls api.keylight.dev directly. Keylight mints, signs, tracks, and revokes licenses. You only hold the public key used to verify leases locally.

Ready to ship?

Create your account and start licensing your apps in under a minute. Free forever tier included.

Start Free