Documentation Index
Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt
Use this file to discover all available pages before exploring further.
Requirements
- Go 1.21 or later
- No external dependencies (standard library only)
Installation
The module path is github.com/AuthForgeCC/authforge-go. Add a released version (pin a v1.x.y tag you rely on):
go get github.com/AuthForgeCC/authforge-go@v1.0.1
Imports always use github.com/AuthForgeCC/authforge-go. Run go mod tidy after editing go.mod.
module example.com/myapp
go 1.21
require github.com/AuthForgeCC/authforge-go v0.0.0
replace github.com/AuthForgeCC/authforge-go => ../path/to/authforge-go
Point replace at a directory that contains the SDK’s go.mod, then run go mod tidy.
Quick start
package main
import (
"errors"
"fmt"
"os"
"github.com/AuthForgeCC/authforge-go"
)
func main() {
client, err := authforge.New(authforge.Config{
AppID: "YOUR_APP_ID",
AppSecret: "YOUR_APP_SECRET",
PublicKey: "YOUR_PUBLIC_KEY",
HeartbeatMode: "server",
OnFailure: func(errMsg string) {
fmt.Fprintf(os.Stderr, "Auth failed: %s\n", errMsg)
os.Exit(1)
},
})
if err != nil {
panic(err)
}
result, err := client.Login("XXXX-XXXX-XXXX-XXXX")
if err != nil {
switch {
case errors.Is(err, authforge.ErrInvalidKey):
fmt.Fprintln(os.Stderr, "Invalid license key.")
default:
fmt.Fprintf(os.Stderr, "Login failed: %v\n", err)
}
os.Exit(1)
}
fmt.Printf("Authenticated! Expires: %d\n", result.ExpiresIn)
select {}
}
Config reference
client, err := authforge.New(authforge.Config{
AppID: "YOUR_APP_ID", // Required
AppSecret: "YOUR_APP_SECRET", // Required
PublicKey: "YOUR_PUBLIC_KEY", // Required - Ed25519 public key from your AuthForge dashboard (base64)
HeartbeatMode: "server", // Required: "server" or "local"
HeartbeatInterval: 15 * time.Minute, // Optional (any value ≥ 1s)
APIBaseURL: "https://auth.authforge.cc",// Optional
OnFailure: nil, // Optional: func(error string)
RequestTimeout: 15 * time.Second, // Optional
SessionTTL: 0, // Optional: time.Duration. 0 = server default (24h). Clamped to [1h, 7d].
HWIDOverride: "", // Optional: custom identity (for example "tg:123456789")
})
SessionTTL
Requested lifetime of the session token returned by /auth/validate. Leave at 0 to accept the server default (24 hours). The server clamps the final value to [1h, 7d]. The requested TTL is preserved across heartbeat refreshes, so long-lived apps using LOCAL mode can extend their offline window up to 7 days.
Billing
- Each successful
Login() or ValidateLicense() costs 1 credit (one /auth/validate debit).
- Heartbeats cost 1 credit per 10 successful calls (billed on every 10th heartbeat). Any
HeartbeatInterval ≥ 1s is economically safe.
- Revocations take effect on the next heartbeat regardless of interval.
Validate license (no heartbeat)
ValidateLicense performs the same /auth/validate request and signature verification as Login, but does not persist session fields on the client, start the heartbeat goroutine, or invoke OnFailure for validate failures (network errors still return an error; repeated network failure does not call OnFailure when using ValidateLicense).
The SDK recognizes AUTHFORGE_SDK_TEST_NONCE for integration tests only; never set it in production (it pins the validate nonce).
Methods reference
result, err := client.Login(licenseKey)
result, err = client.ValidateLicense(licenseKey) // same validate + signatures, no heartbeat / session persistence
client.Logout()
ok := client.IsAuthenticated()
session := client.SessionData()
appVars := client.AppVariables()
licenseVars := client.LicenseVariables()
Login and ValidateLicense return a LoginResult with:
SessionToken
ExpiresIn
AppVariables
LicenseVariables
RequestID
Error handling
The Go SDK exposes sentinel errors so you can branch with errors.Is:
if err != nil {
switch {
case errors.Is(err, authforge.ErrInvalidApp):
// invalid app credentials
case errors.Is(err, authforge.ErrInvalidKey):
// invalid key
case errors.Is(err, authforge.ErrExpired):
// license expired
case errors.Is(err, authforge.ErrRevoked):
// license revoked
case errors.Is(err, authforge.ErrHwidMismatch):
// HWID slots full
case errors.Is(err, authforge.ErrNoCredits):
// no credits
case errors.Is(err, authforge.ErrBlocked):
// blocked
case errors.Is(err, authforge.ErrRateLimited):
// rate limited (validate only)
case errors.Is(err, authforge.ErrReplayDetected):
// replay detected (validate only)
case errors.Is(err, authforge.ErrSignatureMismatch):
// signature verification failed
default:
// transport or unexpected error
}
}
Heartbeat modes
// SERVER mode
client, _ := authforge.New(authforge.Config{
AppID: "...",
AppSecret: "...",
PublicKey: "YOUR_PUBLIC_KEY",
HeartbeatMode: "server",
})
// LOCAL mode
client, _ := authforge.New(authforge.Config{
AppID: "...",
AppSecret: "...",
PublicKey: "YOUR_PUBLIC_KEY",
HeartbeatMode: "local",
})
See Heartbeat Modes for a detailed comparison.
GitHub
Source, releases, and issues: AuthForgeCC/authforge-go.