Client integration

beanguard-client is a Spring Boot library you add to your own application so it fetches, decrypts, and enforces the content of a licence issued by your beanguard-server.

Maven dependency

<dependency>
    <groupId>dev.beanguard</groupId>
    <artifactId>beanguard-client</artifactId>
    <version>0.1.5</version>
</dependency>

beanguard-client registers itself as a Spring Boot autoconfiguration — it requires no additional @Enable* annotation in your application.

Implementing BeanGuardConfiguration

All server connection configuration and your application's licence identity come from a single bean implementing BeanGuardConfiguration:

package com.example.myapp.licence;

import dev.beanguard.client.config.BeanGuardConfiguration;
import dev.beanguard.client.config.LicenceKeys;
import dev.beanguard.client.config.ServerConfig;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class MyBeanGuardConfiguration implements BeanGuardConfiguration {

    @Override
    public ServerConfig getServerConfig() {
        return new ServerConfig(
            "https://api.beanguard.dev",
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...", // LICENCE_PUBLIC_KEY from the admin panel
            "dGhpcyBpcyBhIHNlY3JldCBrZXkgZm9yIEFFUy0yNTY=" // LICENCE_SECRET_KEY from the admin panel
        );
    }

    @Override
    public Optional<LicenceKeys> getLicenceKeys() {
        return Optional.of(new LicenceKeys(
            "11111111-1111-1111-1111-111111111111", // licence key
            "my-licence-secret" // licence secret
        ));
    }

    @Override
    public Optional<String> loadLicence() {
        // load the last saved licence, e.g. from a file or your application's database
        return Optional.empty();
    }

    @Override
    public void saveLicence(String licence) {
        // save the received licence so it survives a restart without a server connection
    }
}
  • getServerConfig() — your beanguard-server address, the RSA public key (LICENCE_PUBLIC_KEY), and the AES secret (LICENCE_SECRET_KEY) generated in the admin panel, Settings → Cryptographic keys tab.
  • getLicenceKeys() — the key and secret of your customer's specific licence. Return Optional.empty() if no licence has been assigned yet.
  • loadLicence() / saveLicence() — a local cache of the last received licence, so the application keeps working even without a momentary connection to the server.

Reading licence status

When BeanGuardConfiguration is present in the context, the autoconfiguration registers a LicenceRegistry — the licence is fetched on application startup and refreshed every hour:

import dev.beanguard.client.registries.LicenceRegistry;
import dev.beanguard.client.registries.LicenceStatus;
import org.springframework.stereotype.Component;

@Component
class LicenceBanner {

    private final LicenceRegistry licenceRegistry;

    LicenceBanner(LicenceRegistry licenceRegistry) {
        this.licenceRegistry = licenceRegistry;
    }

    boolean isLicenceValid() {
        return licenceRegistry.getStatus() == LicenceStatus.LOADED;
    }
}

LicenceStatus takes the values NOT_LOADED, MISSING_KEY, WRONG_KEY, WRONG_SECRET, EXPIRED, LOADED — use them, for instance, to show a "licence expired" banner in your application.

Transferring a licence to another machine

To move an existing licence to a new machine (a reinstall, or a lost secret), use the BeanGuardServer bean. The flow has two steps:

import dev.beanguard.api.models.licence.LicenceTransferInitResponse;
import dev.beanguard.api.models.licence.LicenceTransferStatusResponse;
import dev.beanguard.client.server.BeanGuardServer;

// 1. Start the transfer - the server emails a confirmation link to the licence owner.
LicenceTransferInitResponse init = beanGuardServer.initiateLicenceTransfer(licenceKey);
// Keep init.transferToken() and init.expiresAt() until the transfer completes.

// 2. Poll until the owner opens the link.
LicenceTransferStatusResponse status = beanGuardServer.getLicenceTransferStatus(init.transferToken());
switch (status.status()) {
    case "CONFIRMED" -> {
        // status.secret() is the new secret - store it with the licence key,
        // then call licenceRegistry.refreshLicence().
    }
    case "EXPIRED" -> { /* start over with initiateLicenceTransfer */ }
    default -> { /* PENDING - check again later */ }
}

The transfer is confirmed by the licence owner, not by the machine that started it: the confirmation link goes only to the email on the licence, and transferToken can only be used to poll. The first poll after the owner confirmed rotates the licence secret and returns it; the secret can be collected once, so store it immediately (a later poll returns an error). The previous secret keeps working until then. Initiating a transfer for an unknown key, or within TRANSFER_INIT_COOLDOWN_SECONDS of the previous request, looks like success but sends no email, so polling that token reports an error.

Both methods throw BeanGuardServerException when the server rejects the request (for example an unknown licence key or transfer token). Storing the pending transfer and the new secret is up to your application, since BeanGuardConfiguration only reads the licence keys - see beanguard-demo for a working example.

Method-level annotations enforce the limits and features from the licence — see Licensing annotations.

Was this page helpful?