$ guides / discord-bot

Discord Bot

Implement Discord user-based licensing with AuthForge using HWID override.

Guide

This pattern binds licenses to Discord users by setting hwidOverride = discord:<user_id>.

Architecture

  1. User runs a slash command (for example /license activate).
  2. Bot asks for key via ephemeral response or DM.
  3. Bot validates with AuthForge using override identity discord:<user_id>.
  4. On success, bot stores entitlement state and unlocks premium commands.

Why this works

  • Discord user IDs are stable and immutable for the account.
  • AuthForge seat limits and reset behavior remain unchanged.
  • You get user-identity licensing without pretending a Discord bot has a real machine HWID.

Use user_id, not usernames or display names.

The default client configuration is all a bot process needs. Bots usually re-check keys per request with validateLicense (as below), which stores no session; if you instead call login, the bot runs on the signed session through its grace period. Optional online check-ins (onlineHeartbeat: true, periodic /auth/heartbeat calls) are meant for login-style sessions on the end user’s machine where you want fast revocation and concurrent-use detection; a Discord bot only needs to validate keys and enforce entitlements on your server.

For cron jobs, per-message handlers, or any path that re-checks the license often, prefer validateLicense (or the equivalent in your language: validate_license, ValidateLicense, validate_license, etc.). It performs the same /auth/validate request and signature verification as login, but does not start check-in timers and does not require logout() to clean up background work. One-time startup flows can still use login if you want a long-lived session that runs through the grace period.

Node example (discord.js-style pseudocode)

import { AuthForgeClient } from "@authforgecc/sdk";

async function validateDiscordKey(discordUserId, licenseKey) {
  const client = new AuthForgeClient({
    appId: process.env.AUTHFORGE_APP_ID,
    appSecret: process.env.AUTHFORGE_APP_SECRET,
    publicKey: process.env.AUTHFORGE_PUBLIC_KEY,
    hwidOverride: `discord:${discordUserId}`,
  });

  const result = await client.validateLicense(licenseKey);
  if (!result.valid) {
    return { ok: false, code: result.code };
  }
  return { ok: true, appVariables: result.appVariables, licenseVariables: result.licenseVariables };
}

Operational recommendations

  • Use ephemeral responses or DMs to avoid exposing keys in channels.
  • Rate limit invalid attempts to reduce brute force.
  • Use maxHwidSlots=1 for strict per-user license behavior.
  • Document how users can request resets if they change accounts.

Contact support

Feel free to reach out if you have questions, need help getting set up, or run into something unexpected. We'll get back to you as soon as we can.

Email us at support@authforge.cc