AtlasAuth

C++ SDK

Needs libcurl and OpenSSL. Build and link flags are at the top of atlasauth.cpp.

Download atlasauth.h and atlasauth.cpp from the sidebar and add them to your project. Create a client with your app id and public key from the dashboard:

cpp
atlas::Client client("YOUR-APP-ID", "YOUR-PUBLIC-KEY");

Init

Call first. Opens the session. Returns false if the app is in maintenance or disabled, or your version is blocked.

cpp
if (!client.init())
{
    std::cout << client.lastError() << "\n";
    return 1;
}

Login

Username and password.

cpp
if (!client.login(username, password))
{
    std::cout << client.lastError() << "\n";
    return 1;
}

Register

Create an account that redeems a key. The user logs in with username and password after that.

cpp
if (!client.register_(username, password, licenseKey))
{
    std::cout << client.lastError() << "\n";
    return 1;
}

License

Sign in with just a key, no account.

cpp
if (!client.licenseLogin(licenseKey))
{
    std::cout << client.lastError() << "\n";
    return 1;
}

Heartbeat

Start it right after init, before login. You do not need to be logged in. It pings the server on an interval and kicks the user when their key expires, their session is killed, the app goes down, or they are banned.

It is also an anti-tamper check. If the heartbeat thread is paused or suspended, the session goes stale and the user is kicked. Both the server and the SDK measure the gap, so freezing the client clock does not hide it. Running it from init catches a paused thread before the user ever logs in, which is when crackers try to jump past auth.

cpp
client.startHeartbeat([](std::string reason)
{
    std::cout << reason << "\n";
    std::exit(0);
});

Gate anything sensitive on sessionAlive(). It is false the moment the heartbeat stalls, so a frozen heartbeat thread stops your app.

cpp
if (!client.sessionAlive()) return;   // heartbeat stalled or session dead
// run protected code

Variables

Fetch an app variable. Empty if it does not exist, or if it is login-gated and you are not logged in.

cpp
std::optional<std::string> value = client.var("download_url");

Protect content

Stops a cracked copy from working. Put the values your app needs (a download link, an unlock code, a config string) in the dashboard as secret variables, then read them at runtime. A real logged-in user gets the real value. A cracked or faked copy gets a wrong one, so the app can't run.

Read a value and use it:

cpp
long long offset = client.secretLong("aim_offset");
write(gameBase + offset, value);

For a real user offset is correct. For a cracked copy it is wrong, and the app breaks on its own. secretString returns text, secretBytes returns raw bytes. Don't check if it worked, just use it.

Protect a few small values you actually use, not one big value at startup, and change them when you ship an update.

To ship a whole encrypted file or blob inside your app: enter the variable name and click Generate to make a key, encrypt your value in the Encrypt a value box, paste the result into your app, then unlock it at runtime with the same variable name.

cpp
if (auto url = client.decryptSecret("content_key", cipher)) use(*url);

A wrong or missing key makes decryptSecret return empty instead of a value, so a cracked copy gets nothing, not the real value. The difference from secretLong: that one hands back a wrong value, decryptSecret returns empty. Either way the cracked copy never gets the real thing. The value is also locked to this app and variable name.

Log

Send a line to the app log.

cpp
client.log("info", "started");

Status and news

Public. No login needed.

cpp
auto status = client.status();   // status->status, status->online
auto news = client.news();       // std::vector<NewsItem>

HWID seed

Optional. A fixed seed gives the same HWID on any machine, so you can move your own key. Others cannot use it.

cpp
atlas::Client client("YOUR-APP-ID", "YOUR-PUBLIC-KEY");
client.setHwidSeed("your-secret-seed");

Logout

cpp
client.logout();

Reading the user

After a successful login:

cpp
client.username();      // std::string
client.expiryUnix();    // std::optional<int64_t> (empty = lifetime)
client.loggedIn();      // bool
client.lastError();     // last failure message

Harden further

The SDK verifies every response and delivers your keys only to a live session, but the binary still runs on the attacker's machine. To raise the cost:

Optional: setPinnedPublicKeys("sha256//PRIMARY=;sha256//BACKUP=") before init() pins the server's TLS key so a local proxy cannot read traffic. Ship two pins and only use it if you manage the cert key, or a rotation locks users out.

No client-side check is unbreakable by someone who owns the machine. These raise the time and effort, they do not make it impossible.