Sessions & Bindings

GeckoGuard tracks two types of associations between licenses and devices: bindings (persistent device records) and sessions (active usage tracking).

Bindings

Bindings are persistent records of devices (HWIDs) and IPs that have been associated with a license. They are created automatically during license authorization.

Binding Types

TypeDescription
HWIDHardware ID binding — tracks which devices have used the license
IPIP address binding — tracks which IPs have used the license

Binding Behavior by Policy Mode

ModeBehavior
unlimitedBindings are recorded but not enforced
stickyFirst binding is permanent — subsequent different values are denied
limitUp to maxDistinct unique bindings allowed

Binding Fields

Each binding tracks:

  • valueHash — SHA-256 hash of the HWID/IP
  • region — Country code (for IP bindings with region-based limiting)
  • firstSeenAt — When this binding was first created
  • lastSeenAt — Most recent authorization using this binding
  • revokedAt — If the binding has been reset/revoked

Resetting Bindings

HWID and IP bindings can be reset via the dashboard API, subject to the license's reset budget:

POST /v1/dashboard/licenses/:id/reset-hwid
POST /v1/dashboard/licenses/:id/reset-ip

Reset budgets control:

  • max — total number of resets allowed (0 = no resets)
  • cooldownHours — minimum time between resets

Sessions

Sessions track active concurrent usage of a license. They're created when a sessionId is passed during license authorization and are used to enforce concurrency limits.

How Sessions Work

  1. Your application generates a unique sessionId (e.g., a UUID per app launch)
  2. On each authorization request, pass the sessionId
  3. GeckoGuard creates or updates the session record
  4. If concurrency limits are enabled, the number of active sessions is checked
  5. Sessions that haven't been seen recently can be considered stale

Managing Sessions

List Sessions

const response = await fetch('/v1/dashboard/licenses/LICENSE_ID/sessions', {
  headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});

const { data } = await response.json();
// data.sessions = [{ id, sessionIdHash, ipHash, hwidHash, createdAt, lastSeenAt, revokedAt }]
// data.activeCount = 2
// data.revokedCount = 1

Kill a Specific Session

POST /v1/dashboard/licenses/:id/sessions/:sessionId/revoke

Useful when a user reports a lost/stolen device or wants to log out from a specific location.

Kill All Sessions

POST /v1/dashboard/licenses/:id/sessions/revoke-all

Immediately revokes all active sessions. The user will need to re-authorize on their next launch.

Session Fields

FieldDescription
sessionIdHashHashed session identifier
ipHashHashed IP of the session
hwidHashHashed HWID of the session
createdAtWhen the session started
lastSeenAtLast authorization with this session
revokedAtWhen the session was killed (null if active)

Concurrency Limiting

Set limits.concurrency.mode: 'limit' in your policy with a maxActive count:

{
  "limits": {
    "concurrency": {
      "mode": "limit",
      "maxActive": 2
    }
  }
}

When the limit is reached, new sessions are denied with CONCURRENCY_LIMIT_EXCEEDED. The authorization response includes remaining counts:

{
  "limits": {
    "remaining": {
      "concurrency": 0
    }
  }
}

Best Practices

  1. Generate unique session IDs — use a UUID per application launch, not per request
  2. Reuse the same session ID — send the same ID on periodic re-validations
  3. Kill sessions on app exit — if your app has a clean exit path, revoke the session
  4. Monitor session counts — check the dashboard for users with unusually high session counts
  5. Set reasonable limits — most software works well with 1-3 concurrent sessions