Skip to content
Version: Current

Runbook: auth.tcp.systems

Pocket ID runs as a container on tcp, fronted by Caddy (auth.tcp.systems to 127.0.0.1:1411). There is no systemd unit for it. Deploy, rollback and restore of the container itself are owner-held and live in the tcpsystems/auth repository (docs/CONSOLE-OIDC-LIVE.md); they are stated here as out of scope, not invented. This page covers what an operator can verify and change without touching the container: the OIDC contract, client registration and secret rotation.

The issuer is https://auth.tcp.systems (exact, no trailing slash). Clients must read endpoints from discovery, never from hard-coded paths. Probed read-only on 2026-11-05, the discovery document advertised:

Field Value
issuer https://auth.tcp.systems
authorization_endpoint https://auth.tcp.systems/authorize
token_endpoint https://auth.tcp.systems/api/oidc/token
jwks_uri https://auth.tcp.systems/.well-known/jwks.json
userinfo_endpoint https://auth.tcp.systems/api/oidc/userinfo
introspection_endpoint https://auth.tcp.systems/api/oidc/introspect
device_authorization_endpoint https://auth.tcp.systems/api/oidc/device/authorize
end_session_endpoint https://auth.tcp.systems/api/oidc/end-session
id_token_signing_alg_values_supported RS256
code_challenge_methods_supported plain, S256 (clients send S256 only)
token_endpoint_auth_methods_supported client_secret_basic, client_secret_post, none
scopes_supported openid profile email groups offline_access

No revocation endpoint is advertised. The plain PKCE method and the none token auth method are advertised by Pocket ID and cannot be changed from this repository; the hardening checklist they map to is docs/C08-POCKETID-HARDENING.md in tcpsystems/auth.

In order, all read-only:

Terminal window
curl -sS -o /dev/null -w '%{http_code}\n' \
https://auth.tcp.systems/.well-known/openid-configuration
curl -sS https://auth.tcp.systems/.well-known/openid-configuration \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["issuer"])'
bash tools/verify-pocketid-oidc.sh # in the tcpsystems/auth repository
  1. The status code separates a dead provider (000, 502, 404) from a live one (200).
  2. The issuer field separates a live provider from a wrong-host fetch. A recorded misdiagnosis on 2026-10-30 reported text/html discovery with HTTP 200; that was a fetch against the wrong host, not a provider fault. The real document is JSON whose issuer is exactly https://auth.tcp.systems.
  3. The verifier re-runs the full read-only checklist and exits non-zero on any FAIL. WARN lines are advisory and do not change the exit code.

If all three pass, the provider is fine and the fault is in the client: an unknown client id, a redirect URI that does not match exactly, or a PKCE method other than S256. If the checks fail, the fault is on tcp (the container or its Caddy route) and belongs to the owner path above.

Prerequisites: a Pocket ID admin credential (owner-held) and a tailnet node, or shell access on tcp. The admin UI answers 404 outside the tailnet.

Expected outcome: a client id and secret stored in the consumer’s secret store, with nothing pasted into tickets, logs or documentation.

  1. Open the admin UI from a tailnet node, or reach 127.0.0.1:1411 on tcp.
  2. Administration, then OIDC Clients, then Add client. Name the client after the surface (one client per realm per surface), set the exact callback URL, enable PKCE, and keep the client confidential. The live console callback is https://ai.tcp.systems/console/auth/callback.
  3. Copy the generated client id and secret straight into the consumer’s secret store. The API alternative is POST /api/oidc/clients with the admin API key in the X-API-KEY header, then POST /api/oidc/clients/<id>/secret to mint a secret; keep both values out of argv and shell history (a 0400 file or stdin).
  4. Configure the surface from discovery plus the registered values. The console’s names are OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_REDIRECT_URI and the deploy secret AUTH_CLIENT_SECRET (wrangler secret put, interactive stdin).

State at the last verification (2026-10-30): the console client was not yet registered and the authenticated round-trip was BLOCKED on this step. Treat registration as incomplete until the verifier’s probe section runs green.

A client secret rotation is: mint a new secret on the client (step 3 above), update the consumer’s secret store, restart or redeploy the consumer, verify a sign-in, then invalidate the old secret. The order is mint, update, verify, invalidate; an invalidated old secret locks out every session that has not refreshed.

Rotating the provider’s signing keys is a Pocket ID operation on tcp and is part of the owner-held deploy path, not this page.

  • Container deploy, rollback and restore (owner-held; see the auth repository).
  • The authenticated login round-trip verification, which needs AUTH_PROBE_CLIENT_ID and AUTH_PROBE_CLIENT_SECRET in the environment before tools/verify-pocketid-oidc.sh will run its probe section.
  • The machine plane. Virtual keys are an acumen concern; see the acumen runbook and acumen auth.