Metrics & CLI

TL;DR — Two references in one page. Metrics — every counter/histogram/gauge AuthPlane emits, with the prefix (authserver_* for legacy, authplane_* for Phase-3 features), the labels, and a one-line description. CLI — every command the authserver binary ships (serve, migrate, purge, admin *), with their flags and typical use. Same commands run under systemd, Docker, and Kubernetes.


Metrics catalog

Metrics are emitted via OpenTelemetry and can be scraped by Prometheus (observability.metrics.provider: prometheus, default /metrics path) or pushed to an OTLP endpoint (provider: otel or both). Full config in Configuration: observability, Prometheus + Grafana setup in Guides: Monitoring.

Prefix note

Metric names use two prefixes — a historical artifact:

  • authserver_* — original metrics (tokens, auth flow, OIDC, introspection, key management, upstream broker).
  • authplane_* — Phase-3 additions (client credentials, DPoP, token exchange, agent identity, XAA).

Both are stable — dashboard once, don’t change. When grepping /metrics, remember to search both prefixes.

Counters (_total)

OAuth core

MetricWhat it counts
authserver_tokens_issued_totalAccess tokens issued (any grant)
authserver_tokens_refreshed_totalRefresh-token grants
authserver_tokens_revoked_total/oauth/revoke calls that revoked at least one token
authserver_auth_denied_totalAuth requests denied (any reason)
authserver_clients_registered_totalClient registrations via DCR + admin
authserver_consent_decisions_totalUser consent screen decisions (approve/deny)
authserver_login_attempts_total/login submissions (success + failure)
authserver_refresh_token_reuse_totalRefresh-token reuse detections → family revocations
authserver_introspection_total/oauth/introspect calls

OIDC federation

MetricWhat it counts
authserver_oidc_jwks_cache_hits_totalUpstream IdP JWKS cache hits
authserver_oidc_jwks_cache_misses_totalUpstream IdP JWKS cache misses (triggers fetch)

Signing key management

MetricWhat it counts
authserver_key_rotation_totalSigning-key rotations

Broker / upstream token vending

MetricWhat it counts
authserver_upstream_token_issued_totalUpstream-format access tokens vended to MCP clients (Broker resources)
authserver_upstream_token_refresh_totalAuto-refresh operations against persisted upstream credentials
authserver_connection_connect_totalUpstream Connect flow completions
authserver_connection_disconnect_totalUpstream Disconnect operations

Client Credentials

MetricWhat it counts
authplane_client_credentials_issued_totalMachine-token issuances
authplane_client_credentials_denied_totalMachine-token denials

DPoP (RFC 9449)

MetricWhat it counts
authplane_dpop_proofs_validated_totalDPoP proofs that passed validation
authplane_dpop_proofs_rejected_totalDPoP proofs rejected (see labels for reason)

Token exchange (RFC 8693)

MetricWhat it counts
authplane_token_exchange_totalToken exchange operations (label: `kind=impersonation
authplane_token_exchange_denied_totalToken exchange operations denied

Agent identity + XAA

MetricWhat it counts
authplane_agent_tokens_issued_totalTokens issued with agent_id / agent_chain claims
authplane_xaa_policy_evaluation_totalXAA policy evaluations (label: `outcome=allow
authplane_xaa_idp_operations_totalXAA IdP-registry operations
authplane_xaa_subject_resolutions_totalXAA subject-mapping resolutions

Admin API

MetricWhat it counts
authplane_resource_server_ops_totalAdmin resource-server CRUD
authplane_allowlist_ops_totalCross-client allowlist admin ops (legacy path)

HTTP

MetricWhat it counts
authserver_http_requests_totalRequests per (method, path, status)

Histograms (_duration_seconds)

Recorded in seconds. Buckets: 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10.

MetricWhat it measures
authserver_token_issuance_duration_secondsEnd-to-end token issuance
authserver_auth_flow_duration_secondsAuthorize flow duration
authserver_cimd_fetch_duration_secondsCIMD document fetch
authserver_db_operation_duration_secondsStorage backend operations
authserver_oidc_exchange_duration_secondsOIDC code exchange + ID token verification
authserver_introspection_duration_secondsIntrospection call latency
authserver_key_reload_duration_secondsJWKS cache reload
authserver_upstream_token_issuance_duration_secondsUpstream-format token issuance
authserver_http_request_duration_secondsHTTP request latency (label: method, path, status)

Gauges

MetricMeaning
authserver_active_clientsCurrently registered clients
authserver_active_token_familiesLive refresh-token families

Start with these; tune thresholds to your traffic.

  • rate(authserver_auth_denied_total[5m]) > 10 — spike in auth denials (possible attack or misconfig)
  • rate(authserver_refresh_token_reuse_total[5m]) > 0 — refresh-token theft detected (never expected in normal ops)
  • rate(authplane_dpop_proofs_rejected_total[5m]) > 5 — DPoP failures spiking (SDK misconfig or client bug)
  • histogram_quantile(0.99, rate(authserver_token_issuance_duration_seconds_bucket[5m])) > 0.5 — p99 token issuance > 500 ms (DB or Vault latency)
  • authserver_key_rotation_total unchanged for 90d — rotation cadence missed
  • authserver_upstream_token_refresh_total{outcome="failed"} > 0 — upstream provider auth broken

Full alert examples in Guides: Monitoring.


CLI reference

Every AuthPlane operational task can run from the CLI. Same binary as the server (authplane/authserver:latest or the standalone Linux binary). Config is passed as --config <path> or via AUTHPLANE_* env vars.

authserver serve

Start the server. Runs both public (:9000) and admin (:9001) HTTP servers.

authserver serve --config /etc/authserver/config.yaml

Flags:

  • --config <path> — YAML config file. Optional; without it, defaults + env vars are used.

Signal handling:

  • SIGTERM / SIGINT — graceful shutdown (drains for server.shutdown_wait, default 10 s).
  • SIGHUP — reload signing keys hot (current/previous JWKS refresh). No connection drop.

See Operate: Standalone for the systemd unit and Operate: Docker Compose for the container form.

authserver migrate

Apply pending database migrations. Idempotent — safe to re-run.

authserver migrate --config /etc/authserver/config.yaml

Migrations are embedded in the binary via go:embed and applied by serve on boot too — migrate is the standalone form for CI/CD pipelines that want to run migrations separately from the server process. Forward-only; there is no rollback.

The Helm chart’s init container waits for Postgres connectivity but does NOT run this — the main process handles migrations on pod boot.

authserver purge

Delete expired rows from the DB. Not run by serve; schedule externally.

authserver purge --config /etc/authserver/config.yaml
authserver purge --only=dpop-nonces,jti --timeout=5m

Flags:

  • --config <path> — YAML config (needed to reach the DB).
  • --only <targets> — comma-separated list from: assertion-jti, connect-pending-states, dpop-nonces, jti, machine-tokens, refresh-tokens, sessions. Default: all targets.
  • --timeout <duration> — abort after this duration. Default 10m. Pass 0 to disable.

Exit codes — non-zero if any target fails or context canceled. Individual failures log at ERROR with table=<target> attribute; the command continues with remaining targets and fails at the end. Wire into your alerting.

Scheduling recipes for systemd, Docker Compose, and Kubernetes CronJob in Operate: Backup, upgrade, purge.

authserver version

Print the binary version and exit.

authserver version
# authserver v0.1.x commit=abcdef1 built=2026-01-01T00:00:00Z

authserver admin user create

Bootstrap the first admin user (before the Admin UI is reachable).

authserver admin user create \
    --config /etc/authserver/config.yaml \
    --email admin@example.com \
    --password changeme \
    --name Admin \
    --role admin

Flags:

  • --email — user’s email (required)
  • --password — initial password (required; change after first login)
  • --name — display name (required)
  • --roleadmin or user (default user)

After the first admin exists, manage users via the Admin UI or authserver admin user *.


Admin CLI — authserver admin *

Every entity in the Admin API has a matching CLI verb. Common pattern:

authserver admin <entity> <verb> [--flags]

Auth uses the same AUTHPLANE_ADMIN_API_KEY as the REST API. Config path (for DB access) via --config or env.

admin client

OAuth client management.

authserver admin client list                                # list all
authserver admin client create --grant-types authorization_code,refresh_token \
                                --redirect-uris https://app.example.com/cb \
                                --scopes 'tools/read||Read tools' \
                                --scopes 'tools/write||Write tools' \
                                --auth-method client_secret_post \
                                --name "My App"

The CLI subcommands are list, create, update, rotate-secret, and delete. For get, suspend, and reactivate, use the admin REST API — for example:

# Inspect a client
curl -s http://localhost:9001/admin/clients/<client_id> \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Suspend a client (block new tokens)
curl -s -X PATCH http://localhost:9001/admin/clients/<client_id>/suspend \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Reactivate a suspended client
curl -s -X PATCH http://localhost:9001/admin/clients/<client_id>/reactivate \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

Output format: --json for JSON, default is key=value per line.

admin user

Local user management.

authserver admin user list
authserver admin user create --email --password --role admin
authserver admin user update --id <user_id> --email new@example.com
authserver admin user force-logout --id <user_id>
authserver admin user delete --id <user_id>

The CLI subcommands are list, create, update, delete, and force-logout. For get, disable, enable, and password resets, use the admin REST API — for example:

# Look up a user
curl -s "http://localhost:9001/admin/users?email=<email>" \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Disable a user (block logins)
curl -s -X PATCH http://localhost:9001/admin/users/<user_id>/disable \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Enable a user
curl -s -X PATCH http://localhost:9001/admin/users/<user_id>/enable \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Reset a user's password (field on the generic update endpoint)
curl -s -X PATCH http://localhost:9001/admin/users/<user_id> \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"password":"<new>"}'

admin resource

Mint / Broker resources.

authserver admin resource list
authserver admin resource get --slug <slug>
authserver admin resource create --slug my-mcp \
                                  --uri http://localhost:3000/mcp \
                                  --backend-kind mint \
                                  --scope-map "tools/read:tools/read,tools/write:tools/write"
authserver admin resource update --slug my-mcp --scopes 'tools/read||Read tools' --scopes 'tools/write||Write tools' --scopes 'tools/delete||Delete tools'
authserver admin resource delete --slug my-mcp

Broker resources include --broker-provider <id> (identifies the upstream provider). Per-resource policy (policy.exchange.allowed_client_ids, policy.runtime.client_ids, policy.connect.allowed_return_urls) has dedicated subcommands under admin resource policy.

admin provider

Broker providers (upstream OAuth / API key / service account).

authserver admin provider list
authserver admin provider get --id <id>
authserver admin provider create --slug github --protocol oauth \
                                  --display-name "GitHub" \
                                  --config-data ./github-provider.json
authserver admin provider update --id <id> --config-data ./github-provider.json
authserver admin provider delete --id <id>

admin grant

Consent grants + broker grants (per-user).

authserver admin grant list-user-grants --user <user_id>
authserver admin grant revoke-consent --id <consent_grant_id>   # cascades onto live Mint issuances
authserver admin grant revoke-broker --id <broker_grant_id>     # no issuance cascade — upstream tokens are not AS-revocable

admin issuance

Per-token forensic audit rows.

authserver admin issuance list --user <user_id>                  # last N issuances for a user
authserver admin issuance list --client <client_id> --limit 50
authserver admin issuance list --resource <slug> --since 7d       # Go-duration form (e.g. 24h, 7d; max 30d)
authserver admin issuance get --id <issuance_id>

admin key

Signing key management.

authserver admin key list                                       # current + previous kids
authserver admin key rotate                                     # zero-downtime rotation

Same as POST /admin/keys/rotate via the REST API. On multi-instance deployments with postgres_key or vault_transit, propagation is automatic via LISTEN/NOTIFY (ms). Single-instance keyfile may want SIGHUP after rotation.

admin dcr

Runtime DCR mode toggle. Persisted; survives restart.

authserver admin dcr get                                        # show current mode
authserver admin dcr set --mode admin_only                      # switch modes at runtime

Modes: open, approved_redirects, admin_only. See Configuration: dcr.

XAA (Enterprise-Managed Auth) — no CLI subcommand; use the admin REST API

Trusted IdPs, XAA policies, and subject mappings have no authserver admin xaa … CLI equivalent. Manage them through the admin REST API:

# Trusted IdPs
curl -s http://localhost:9001/admin/idps \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
curl -s -X POST http://localhost:9001/admin/idps \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"issuer":"https://idp.example.com","audience":"https://auth.example.com","jwks_uri":"https://idp.example.com/.well-known/jwks.json"}'
curl -s -X POST http://localhost:9001/admin/idps/<idp_id>/refresh-keys \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
curl -s -X DELETE http://localhost:9001/admin/idps/<idp_id> \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Policies
curl -s http://localhost:9001/admin/xaa/policies \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
curl -s -X POST http://localhost:9001/admin/xaa/policies \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"idp_id":"<id>","client_ids":["<client>"],"scopes":["tools/read"],"resources":["https://mcp.example.com/mcp"]}'
curl -s -X DELETE http://localhost:9001/admin/xaa/policies/<policy_id> \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"

# Subject mappings
curl -s http://localhost:9001/admin/xaa/subject-mappings \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
curl -s -X POST http://localhost:9001/admin/xaa/subject-mappings \
    -H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"idp_id":"<id>","mode":"explicit","federated_subject":"foo","local_subject":"bar"}'

Only available when xaa.enabled: true.

admin fronting (advanced)

Fronting-link management for gateway topologies. See Topologies: MCP gateway → hidden Mint.

authserver admin fronting list
authserver admin fronting create --source <slug> --target <slug> \
                                  --scope-map "src/read:dst/read"
authserver admin fronting delete --source <slug> --target <slug>

Global CLI flags

Every subcommand accepts:

  • --config <path> — YAML config path (or set AUTHPLANE_* env vars)
  • --json — machine-readable output (default: key=value lines)
  • --help — subcommand help