C# and VB.NET

Add licensing to a .NET app with the PWFAuth NuGet package.

The PWFAuth NuGet package handles the encryption, the heartbeat and the kill switch for you. It targets .NET Standard 2.0 and .NET 8, so it works in WinForms, WPF and console apps on .NET Framework 4.6.2 and newer, in C# and in VB.NET.

Install

Terminal
dotnet add package PWFAuth

In Visual Studio: Project → Manage NuGet Packages, search for PWFAuth, install.

Use version 1.5.0 or newer. Every reply from the server is signed, and the package checks the signature with the key it carries; 1.4.0 carries an older key and is refused by the current server. Programs built with 1.4.0 have to be rebuilt.

The package talks only to https://pwfauth.com; any other server address is refused.

Keep the secret out of your code

Read the app secret at start-up instead of writing it in the source, for example from App.config or an environment variable:

App.config
<appSettings>
  <add key="PWFAuthAppSecret" value="YOUR_64_CHARACTER_APP_SECRET" />
</appSettings>

Sign in and start the heartbeat

VB.NET
Imports PWFAuth

Public Class FormLogin
    Public Shared Client As PwfClient

    Private Async Sub btnSignIn_Click(sender As Object, e As EventArgs) Handles btnSignIn.Click
        Client = New PwfClient(ConfigurationManager.AppSettings("PWFAuthAppSecret"))
        AddHandler Client.SessionEnded, Sub(s, args)
                                            ' already on the UI thread
                                            MessageBox.Show(args.Message, "Signed out")
                                            Application.Exit()
                                        End Sub

        btnSignIn.Enabled = False
        Dim login = Await Client.LoginAsync(txtKey.Text.Trim())
        btnSignIn.Enabled = True

        If Not login.Success Then
            lblStatus.Text = login.Message       ' written for the customer
            Return
        End If

        Client.StartHeartbeat()                  ' the kill switch: never skip it
        FormMain.Show()
        Hide()
    End Sub
End Class
C#
using PWFAuth;

var client = new PwfClient(secret);
client.SessionEnded += (s, e) =>
{
    MessageBox.Show(e.Message, "Signed out");
    Application.Exit();
};

var login = await client.LoginAsync(txtKey.Text.Trim());
if (!login.Success) { lblStatus.Text = login.Message; return; }

client.StartHeartbeat();
Always call StartHeartbeat(). Without it the program never learns that a key was banned, paused or expired, and the server drops the silent session.

SessionEnded fires when the key is banned, paused, expired, deleted or reset, when you end the session from the panel, when the app goes into maintenance, and when the server cannot be reached three times in a row. e.IsNetworkFailure tells the last case apart.

Show the licence

The sign-in reply carries everything about the key:

VB.NET
Dim user As JsonElement
If login.TryGetProperty("user", user) Then
    Dim exp As JsonElement
    If user.TryGetProperty("expires_at", exp) AndAlso exp.ValueKind = JsonValueKind.String Then
        lblLicence.Text = "Expires " & DateTime.Parse(exp.GetString()).ToLocalTime().ToString("g")
    Else
        lblLicence.Text = "Lifetime licence"     ' expires_at is null for lifetime keys
    End If
End If

Other fields: user.key_type, user.days_remaining, app.name, app.version, app.message (your welcome message), features, texts and slides.

Move the licence to a new PC

When the key belongs to another PC, offer to move it. This works when self-service is on for the app (see HWID resets):

VB.NET
If Not login.Success AndAlso (login.ErrorCode = PwfErrorCodes.HwidMismatch OrElse
                              login.ErrorCode = PwfErrorCodes.DeviceLimit) Then
    If MessageBox.Show(login.Message & vbCrLf & "Move your licence to this PC?", "PWF Auth",
                       MessageBoxButtons.YesNo) = DialogResult.Yes Then
        Dim reset = Await Client.ResetHardwareIdAsync(key, "Moved to a new PC")
        MessageBox.Show(reset.Message)
        If reset.Success Then login = Await Client.LoginAsync(key)
    End If
End If

Customer accounts

Instead of a key, a customer can sign in with a username and password (see Users). The session and the heartbeat work exactly as with a key:

VB.NET
Dim login = Await Client.AccountLoginAsync(username, password)
If Not login.Success Then
    MessageBox.Show(login.Message)          ' INVALID_CREDENTIALS, BANNED, PAUSED, EXPIRED, HWID_MISMATCH …
    Return
End If
Client.StartHeartbeat()

Sign-up, keys and password changes, when sign-up is on for the app:

VB.NET
Dim r = Await Client.RegisterAccountAsync(username, password, email)   ' REGISTRATION_DISABLED when sign-up is off
If r.ErrorCode = PwfErrorCodes.KeyRequired Then                      ' "Sign-up needs a licence key" is on
    r = Await Client.RegisterAccountWithKeyAsync(username, password, key, email)
End If

Dim more = Await Client.RedeemKeyAsync(key)                          ' signed in: adds the key's time
Dim back = Await Client.RedeemKeyAsync(username, password, key)      ' signed out, works after expiry too
Dim c = Await Client.ChangeAccountPasswordAsync(username, currentPassword, newPassword)

A changed password signs out every copy using the account, the one that changed it too: sign in again with the new password. An account is bound to one PC; when it moves, you reset its machine in Users.

RegisterAccountWithKeyAsync and RedeemKeyAsync need version 1.3.0 of the package or newer. A key spent on an account cannot sign in on its own any more: LoginAsync answers KEY_REDEEMED.

Sign out

VB.NET
Await Client.LogoutAsync()      ' ends the session; the key stays bound to this PC
Client.Dispose()

More calls

CallDoes
CheckKeyAsync(key)Reads a key's status without signing in or using a machine seat.
CreateTrialAsync()A free trial key for this PC, when trials are on.
GetAppInfoAsync()App name, version, download link, maintenance state.
GetTextsAsync() / GetSlidesAsync()Remote texts and announcement slides.
CheckUpdateAsync(version)Is there a newer build? See Updates.

A complete example

A ready console program in VB.NET that does all of the above (sign in with a key or an account, sign-up, password change, saved key, trial, moving a licence, licence card, updates, live kill switch) is available on request: ask us on Telegram.

Something missing or unclear? Tell us on Telegram.