Skip to content
authgrabber
Menu
Reference

Zig reference

Generated reference for the authgrabber binary (ziglang/docgen).

authgrabber Reference §

Zig-built CLI reference for the authgrabber binary, generated with the ziglang/docgen preprocessor. The usage block and the source types are derived from the real binary and source at generation time, so this page cannot drift from the code.

authgrabber captures the browser's authenticated state from the active profile and hands it to an automated browser (obscura). Concretely:

  • Session / SSO cookies (cookies.sqlite): the cookies that keep you signed in across apps (a single sign-on cookie plus per-app session cookies). Opaque cookies at or above 128 characters are flagged as auth candidates.
  • Stored OAuth tokens (webappsstore2.sqlite = localStorage): access, refresh and id tokens, classified by key name (access_token, refresh_token, id_token), by JWT shape (eyJ...), or by being a long opaque cookie. JWT payloads are decoded for the claims exp, iat, iss, sub, aud, scope, name, email, picture.
  • Fresh tokens on demand: the login command runs the active authorization-code flow (PKCE) to mint a new token instead of reusing what is already stored.
  • Saved logins (logins.json / key4.db): the password manager's stored usernames and passwords, decrypted via the logins command using the browser's NSS library.

It does not handle basic-auth credentials, HTTP auth, client secrets, or anything outside the profile's SQLite stores.

Security: several commands decrypt real saved secrets, so keep --values output out of logs and shared files; prefer the default redacted form.

Global §

Usage: authgrabber <command> [args...]. Every command targets exactly one profile: the active one by default, or a specific one passed as [BROWSER:PROFILE] (a Firefox profile name matching Name=, an absolute path, a bare browser name selecting that browser's default profile, or a <browser>:<profile> pair such as vivaldi:Default).

CommandDescription
authgrabber discover [BROWSER:PROFILE]print the resolved profile directory PROFILE may be a Firefox name/path, a browser name (default profile), or "<browser>:<profile>" (e.g. vivaldi:Default)
authgrabber user-agent [BROWSER:PROFILE]print the user-agent the supported browser profile sends
authgrabber logins [--values] [BROWSER:PROFILE]list saved logins (decrypted via NSS)
authgrabber login <flags>active authorization-code flow (PKCE + localhost callback)
authgrabber cookies [--values] [BROWSER:PROFILE]list cookies from the selected profile
authgrabber tokens [--json] [--values] [--host <s>] [BROWSER:PROFILE]list classified auth tokens
authgrabber export-session [--format json|obscura] [--values] [--out <file>] [BROWSER:PROFILE]export session
authgrabber storage [BROWSER:PROFILE]list localStorage per origin
authgrabber query <DB> <SQL>run a SQL SELECT against a SQLite db

PROFILE may be a profile name or an absolute path.

discover §

Resolve and print the active profile directory.

Shell
$ authgrabber discover
/Users/you/Library/Application Support/Firefox/Profiles/xxxxxxxx.default-release
$ authgrabber discover vivaldi:Default
/Users/you/Library/Application Support/Vivaldi/User Data/Default

Supported browsers: firefox (default), vivaldi, brave, edge, chromium, chrome, zen.

logins §

List saved logins (username/password) from the password manager, decrypted via the browser's own NSS library.

Shell
$ authgrabber logins
host.example.com       username-len=12	password-len=14
app.example.com        username-len=8	password-len=11
$ authgrabber logins --values
host.example.com       username=alice@example	password=correct-horse

Default output is hostname username-len=<n> password-len=<n> (values redacted); --values prints the decrypted credentials.

cookies §

List session and SSO cookies from the cookie store.

Shell
$ authgrabber cookies
session-token             app.example.com          212
refresh-token             login.example.com        212
persistent-auth           example.com              1383

Opaque cookies at or above 128 characters are flagged as auth candidates. Chromium profiles (Vivaldi, Brave, Edge, Chrome, Chromium) are decrypted with the OS keychain via the os_crypt scheme.

storage §

List localStorage entries per origin (Firefox webappsstore2.sqlite, Chromium LevelDB log files).

Shell
$ authgrabber storage
[https://example.com]
access_token   = eyJhbGciOi...
refresh_token  = eyJhbGciOi...

tokens §

List classified auth tokens. Tokens are classified by key name (access_token, refresh_token, id_token), by JWT shape (eyJ...), or by being a long opaque cookie. JWT payloads are decoded for the claims exp, iat, iss, sub, aud, scope, name, email, picture.

user-agent §

Print the profile's user agent for the automated browser (obscura).

Shell
$ authgrabber user-agent
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0

export-session §

Emit an obscura session bundle (cookies.json) for the automated browser.

Shell
$ authgrabber export-session --format obscura --values --out ~/.config/authgrabber/session/cookies.json
wrote 12 cookies to /Users/you/.config/authgrabber/session/cookies.json (mode 0600)

The session directory lives under the user's private home location (~/.config/authgrabber/session), never /tmp.

login §

Run the active OAuth authorization-code flow (PKCE + localhost callback) to mint a fresh token.

Shell
$ authgrabber login --auth-url https://provider.example/authorize --client-id abc123 \
    --token-url https://provider.example/token --scope openid
opened the authorization URL in your default browser; waiting for the callback...
token response redacted; use --values to print it

The callback binds an OS-assigned ephemeral port (no fixed-port squatting), the state is compared in constant time, and the token exchange is a POST with grant_type=authorization_code plus the PKCE code_verifier.

query §

Run a SQL SELECT against any SQLite database.

Shell
$ authgrabber query <DB> <SQL>
SELECT name FROM sqlite_master WHERE type='table';
name	moz_cookies

Output is the result rows, columns separated by <TAB>; the database is read together with its -wal sidecar. Errors are reported clearly: OpenFailed, PrepareFailed, database is locked (Firefox running?); retry or close Firefox.

Source types §

The command dispatch is string-based, but the modules expose the public Zig types below. They mirror the state documented in the CLI reference page and are extracted from the source at generation time.

classify.zig §

Token classification: where a value came from, the classified token, and the opaque length cutoff.

src/classify.zig
pub const Store = enum { cookie, localStorage };
pub const Token = struct {
    store: Store,
    origin: []const u8,
    name: []const u8,
    value: []const u8 = "",
    kind: []const u8,
    expiry: ?i64 = null,
    issued_at: ?i64 = null,
    scope: ?[]const u8 = null,
    audience: ?[]const u8 = null,
    subject: ?[]const u8 = null,
    issuer: ?[]const u8 = null,
    name_claim: ?[]const u8 = null,
    email: ?[]const u8 = null,
    picture: ?[]const u8 = null,
};
pub const opaque_min_len: usize = 128;

storage.zig §

Firefox web storage: one origin's extracted entries.

src/storage.zig
pub const Item = struct {
    key: []const u8,
    value: []const u8,
};
pub const Origin = struct {
    name: []const u8,
    items: []Item,
};

cookies.zig §

A row from moz_cookies.

src/cookies.zig
pub const Cookie = struct {
    host: []const u8,
    name: []const u8,
    value: []const u8,
    path: []const u8,
    expiry: i64,
    is_secure: bool,
    is_http_only: bool,
    same_site: i32,
};

oauth_flow.zig §

Proof Key for Code Exchange (RFC 7636) values and the localhost callback result.

src/oauth_flow.zig
pub const Pkce = struct {
    verifier: []const u8,
    challenge: []const u8,
    method: []const u8 = "S256",
};
pub const CallbackResult = struct {
    code: ?[]const u8 = null,
    state: ?[]const u8 = null,
};

Related free functions: codeVerifier, codeChallenge, stateToken, authorizeUrl, tokenExchange, accessToken, and constant-time secureEq.

nss.zig §

Firefox NSS library handle used by logins.

src/nss.zig
pub const Nss = struct {
    handle: ?*anyopaque,
    d_init: NssInit,
    d_shutdown: NssShutdown,
    d_slot: Pk11GetSlot,
    d_checkpw: Pk11CheckPw,
    d_sdr: Pk11SdrDecrypt,
    d_free: SecItemFreeItem,
    slot: ?*anyopaque = null,
};

chromium.zig §

Chromium profile structures: saved logins and LevelDB localStorage entries.

src/chromium.zig
pub const LoginInfo = struct {
    origin: []const u8,
    username: []const u8,
    password: []const u8,
};
pub const LocalStorageEntry = struct {
    origin: []const u8,
    key: []const u8,
    value: []const u8,
};

Related functions: osEncryptedKey, encryptionKey, userAgent, snappyDecompress, parseSSTable, extractLocalStorage, decryptCookieValue, extractCookies, extractLogins.

Build §

Build the binary with the Zig build system (0.16.0):

build.zig.zon
.{
    .name = .authgrabber,
    .version = "0.0.0",
    .fingerprint = 0x94a8b077e1164c1d,
    .minimum_zig_version = "0.16.0",
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}
Shell
$ zig build
$ zig build test
$ zig build cross
$ just release
$ just release-cross

zig build produces zig-out/bin/authgrabber (a ~1.5 MB ReleaseSmall binary), zig build cross cross-compiles for x86_64 and arm64 on Windows, Linux and macOS, and just release runs the optimized native build.

Exit codes §

  • 0 success.
  • Non-zero on errors (unrecognized command, missing args, or a command error).