CLI
The oidc.pub CLI is a single binary for everything you do from the command line:
- Authenticate and manage services on oidc.pub
- Sync
openid-configurationand JWKS from your own issuer - Run a local OIDC issuer for development and testing
It also serves as the sync worker for Docker and Kubernetes deployments — see the Sync Worker documentation.
Installation
The CLI requires Node.js 22+ or Docker.
npx oidc.pub --help
npx oidc.pub --help
npm install -g oidc.pub
oidcpub --help
npm install -g oidc.pub
oidcpub --help
docker run --rm -it registry.gitlab.com/oidc.pub/cli:latest --help
docker run --rm -it registry.gitlab.com/oidc.pub/cli:latest --help
Try it locally with dev issuer
You don't need a real OIDC issuer to try oidc.pub. The CLI ships with a built-in dev issuer that generates an RSA keypair, serves the discovery endpoints locally, and mints signed JWTs — all auto-synced to your oidc.pub service on startup.
1. Create a service
npx oidc.pub login
npx oidc.pub service create --name "Demo"
# • Service created: Demo
# Subdomain: demo-7xk2npx oidc.pub login
npx oidc.pub service create --name "Demo"
# • Service created: Demo
# Subdomain: demo-7xk22. Run the dev issuer
Pass --service to derive the issuer URL and sync the discovery document on startup:
npx oidc.pub dev issuer --service demo-7xk2
# • Local issuer running on http://localhost:9229
# • Synced openid-configuration and JWKS to https://demo-7xk2.oidc.pubnpx oidc.pub dev issuer --service demo-7xk2
# • Local issuer running on http://localhost:9229
# • Synced openid-configuration and JWKS to https://demo-7xk2.oidc.pubLeave it running. The issuer URL embedded in tokens is https://demo-7xk2.oidc.pub, so any verifier that trusts that issuer can validate the tokens you mint.
3. Mint a token
In a second terminal, request a signed JWT:
TOKEN=$(curl -s http://localhost:9229/token | jq -r .access_token)TOKEN=$(curl -s http://localhost:9229/token | jq -r .access_token)Or mint a token with custom claims:
TOKEN=$(curl -s -X POST http://localhost:9229/token \
-H "Content-Type: application/json" \
-d '{"sub": "ci-bot", "aud": "my-api"}' | jq -r .access_token)TOKEN=$(curl -s -X POST http://localhost:9229/token \
-H "Content-Type: application/json" \
-d '{"sub": "ci-bot", "aud": "my-api"}' | jq -r .access_token)4. Verify against the public JWKS
The discovery document and JWKS are now served by oidc.pub. Inspect them with curl:
curl -s https://demo-7xk2.oidc.pub/.well-known/openid-configuration | jq .
curl -s https://demo-7xk2.oidc.pub/.well-known/jwks.json | jq .curl -s https://demo-7xk2.oidc.pub/.well-known/openid-configuration | jq .
curl -s https://demo-7xk2.oidc.pub/.well-known/jwks.json | jq .Then verify the token signature using the public JWKS:
npm install jose
node --input-type=module --eval "
import { jwtVerify, createRemoteJWKSet } from 'jose';
const jwks = createRemoteJWKSet(new URL('https://demo-7xk2.oidc.pub/.well-known/jwks.json'));
const { payload } = await jwtVerify(process.argv[1], jwks);
console.log('Token is valid. Claims:', payload);
" "$TOKEN"npm install jose
node --input-type=module --eval "
import { jwtVerify, createRemoteJWKSet } from 'jose';
const jwks = createRemoteJWKSet(new URL('https://demo-7xk2.oidc.pub/.well-known/jwks.json'));
const { payload } = await jwtVerify(process.argv[1], jwks);
console.log('Token is valid. Claims:', payload);
" "$TOKEN"Any OIDC-aware relying party — Vault, GitHub Actions, AWS STS, GCP Workload Identity Federation — configured to trust https://demo-7xk2.oidc.pub will now accept these tokens.
Sync from your own issuer
Once you have a real OIDC issuer (Vault, GitLab, a Kubernetes API server, your own service), point oidc.pub at it with service sync:
npx oidc.pub service sync \
--service demo-7xk2 \
--source-url https://your-issuer.internal \
--oncenpx oidc.pub service sync \
--service demo-7xk2 \
--source-url https://your-issuer.internal \
--onceDrop --once to keep syncing on an interval. For long-running deployments inside Docker or Kubernetes, use the same binary as a container — see the Sync Worker documentation.
Authentication
login
Authenticate via browser-based OAuth. Opens your browser, completes the login flow, and stores a session token locally.
| Flag | Description | Default |
|---|---|---|
--oidcpub-url <url> | oidc.pub base URL | https://oidc.pub |
--profile <name> | Credential profile | default |
--provider <name> | OAuth provider | github |
whoami
Display the currently logged-in user and session status.
logout
Remove stored credentials for the current profile.
Services
service create
Create a new service on oidc.pub. Requires authentication via login or the OIDCPUB_API_KEY environment variable.
| Flag | Description | Required |
|---|---|---|
--name <name> | Human-readable service name | yes |
--subdomain <sub> | Custom subdomain (paid tiers only) | no |
--description <desc> | Service description | no |
service sync
Sync OIDC discovery configuration from a source issuer to oidc.pub. Same engine as the sync worker container.
| Flag | Description | Default |
|---|---|---|
--service <subdomain> | Target service subdomain (required) | — |
--source-url <url> | OIDC issuer URL to sync from | — |
--api-key <key> | API key or JWT (alternative to login) | — |
--once | Sync once and exit | false |
--interval <seconds> | Seconds between syncs | 300 |
Service accounts
Service accounts provide programmatic access to manage your services. Commands are available under service-account (aliased to sa). Available on the Team plan and above.
service-account create
Create a service account. A static policy returns a one-time bearer token (printed to stdout); store it immediately, it is never shown again.
| Flag | Description | Default |
|---|---|---|
--name <name> | Service account name (required) | — |
--services <list> | Comma-separated subdomains the account may act on. Use * for all. | * |
--ip-allowlist <list> | Comma-separated IPs/CIDRs to restrict the token | — |
--policy-file <path> | JSON policy document; overrides --services for full control (e.g. OIDC policies) | — |
npx oidc.pub service-account create --name "CI/CD Pipeline" --services "*"npx oidc.pub service-account create --name "CI/CD Pipeline" --services "*"The policy file is validated against https://oidc.pub/schemas/service-account-policy.v1.json. Reference the URL via $schema for editor autocomplete.
service-account list
List your service accounts.
service-account delete <id>
Permanently delete a service account. Any token it issued stops working immediately.
service-account regenerate-token <id>
Regenerate the token for a static service account. The previous token is invalidated atomically; the new token is printed to stdout.
Local development
dev issuer
Run a local OIDC issuer with an in-memory RSA keypair. Serves discovery and JWKS endpoints and mints signed JWTs. With --service, the discovery document and JWKS are pushed to your oidc.pub service on startup.
| Flag | Description | Default |
|---|---|---|
--service <subdomain> | Target oidc.pub service to sync to | — |
--url <url> | Issuer URL embedded in tokens and discovery | derived from --service |
--port <port> | Local HTTP port | 9229 |
--subject <sub> | Default sub claim | test-user |
--audience <aud> | Default aud claim | — |
--claims <json> | Extra claims as a JSON object | — |
Endpoints served by the local issuer:
| Path | Purpose |
|---|---|
GET /.well-known/openid-configuration | OIDC discovery document |
GET /.well-known/jwks.json | Public JWKS |
GET /token | Mint a JWT with default claims |
POST /token | Mint a JWT with claims from the JSON body |
Profiles
Switch between accounts or environments with --profile. Each profile has its own session token and base URL.
npx oidc.pub login --profile staging --oidcpub-url https://staging.oidc.pub
npx oidc.pub service create --profile staging --name "Test Service"npx oidc.pub login --profile staging --oidcpub-url https://staging.oidc.pub
npx oidc.pub service create --profile staging --name "Test Service"The default profile is default.
Credential storage
Credentials are stored in ~/.config/oidcpub/credentials.json (respects XDG_CONFIG_HOME). The file is created with mode 0600. Session tokens expire after 36 hours.
Legacy Docker sync mode
The latest image is backward compatible with existing sync worker deployments. When OIDCPUB_SERVICE_ID is set and no subcommand is given, the container runs in legacy sync mode automatically. Existing Docker and Kubernetes deployments continue to work without changes after updating the image reference.