omg/docs

Auth

JWT principals, JWKS rotation, on-behalf-of pattern.

vibes-auth (apps/auth/) is the only place that mints JWTs. Everything else verifies via auth.omg.dev/.well-known/jwks.json.

Token shape

{
  "iss": "https://auth.omg.dev",
  "aud": "vibes-infra",
  "sub": "user-abc" | "svc:convex" | "svc:worker" | "svc:ci",
  "appId": "vibes-infra",
  "iat": 1777000000,
  "exp": 1808500000,    // 1 year for service tokens
  "jti": "29629508-..." // for revocation
}
  • User tokens carry the principal of the logged-in human; minted on login, short-lived.
  • Service tokens (sub starts with svc:) are minted on the auth box via bun apps/auth/scripts/mint.ts <name> <ttlSeconds>. There is no public mint endpoint — minting requires SSH access to the auth box. This is intentional: the only thing that could leak from the network is a single token, never the signing key or a mint capability.

On-behalf-of

A service principal can act for a user by adding X-On-Behalf-Of: <userId> to its request. Handlers read identity from the resolved Principal struct (see apps/infra/internal/auth/middleware.go), which carries either:

Principal{ Kind: "user",    UserID: "abc" }
Principal{ Kind: "service", Service: "svc:convex", OnBehalfOf: "abc" }

Every handler treats both shapes identically for authorization purposes; audit logs distinguish them.

Revocation

Each minted token has a jti. Active tokens live in the service_token sqld row (apps/auth/src/schema.ts). Revocation is two endpoints:

  • POST /admin/service-token/revoke — sets revokedAt. (Run on-box via bun scripts/revoke.ts.)
  • GET /tokens/revoked — returns { jtis: string[] }. Public, cached 10s at the edge.

Every infra binary polls /tokens/revoked every 30s into a map[string]struct{} and rejects matching jti on the hot path. So a revoke takes effect everywhere within ~30s plus edge-cache TTL.

Rotating a service token

  1. bun apps/auth/scripts/mint.ts svc:worker 31536000 (1y) on the auth box. Capture the new JWT.
  2. Update the consumer:
    • svc:convexbash apps/web/scripts/convex-prod.sh -- npx convex env set VIBES_INFRA_SERVICE_TOKEN <jwt>
    • svc:workerwrangler secret put VIBES_INFRA_SERVICE_TOKEN
    • svc:cigh secret set VIBES_API_KEY --env e2e
  3. Verify the new key works (one round-trip through the consumer).
  4. bun apps/auth/scripts/revoke.ts <old-jti> to cut off the previous token.

bun apps/auth/scripts/revoke.ts list shows everything live + warns on tokens within 30 days of expiry.