Version: Current
Historical release snapshot. These docs are frozen. Read current docs.
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 live contract
Section titled “The live contract”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.
Incident: the first three checks
Section titled “Incident: the first three checks”In order, all read-only:
curl -sS -o /dev/null -w '%{http_code}\n' \ https://auth.tcp.systems/.well-known/openid-configurationcurl -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- The status code separates a dead provider (
000,502,404) from a live one (200). - The issuer field separates a live provider from a wrong-host fetch. A
recorded misdiagnosis on 2026-10-30 reported
text/htmldiscovery with HTTP 200; that was a fetch against the wrong host, not a provider fault. The real document is JSON whoseissueris exactlyhttps://auth.tcp.systems. - 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.
Register a client
Section titled “Register a client”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.
- Open the admin UI from a tailnet node, or reach
127.0.0.1:1411on tcp. - 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. - Copy the generated client id and secret straight into the consumer’s
secret store. The API alternative is
POST /api/oidc/clientswith the admin API key in theX-API-KEYheader, thenPOST /api/oidc/clients/<id>/secretto mint a secret; keep both values out of argv and shell history (a0400file or stdin). - Configure the surface from discovery plus the registered values. The
console’s names are
OIDC_ISSUER,OIDC_CLIENT_ID,OIDC_REDIRECT_URIand the deploy secretAUTH_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.
Rotate a client secret
Section titled “Rotate a client secret”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.
What this page does not cover
Section titled “What this page does not cover”- Container deploy, rollback and restore (owner-held; see the auth repository).
- The authenticated login round-trip verification, which needs
AUTH_PROBE_CLIENT_IDandAUTH_PROBE_CLIENT_SECRETin the environment beforetools/verify-pocketid-oidc.shwill run its probe section. - The machine plane. Virtual keys are an acumen concern; see the acumen runbook and acumen auth.