This page documents the user-facing HTTP endpoints exposed by the TokenSmith service.
Returns a basic JSON health response for the running TokenSmith instance.
Current response fields include:
statusserviceissuercluster_idopenchami_idoidc_issuerservice_identity_ca_configured
Example:
curl -s http://localhost:8080/health | jqReturns the active public signing keys in JWKS format.
Use this endpoint to configure JWT verifiers for TokenSmith-issued tokens.
Current behavior:
- response content type is
application/json - response body contains a standard
keysarray - RSA keys include
kty,use,alg,kid,n, ande
Example:
curl -s http://localhost:8080/.well-known/jwks.json | jqImportant:
- TokenSmith currently exposes a direct JWKS endpoint
- TokenSmith does not currently publish its own OIDC discovery document at
/.well-known/openid-configuration - Configure verifiers with the direct JWKS URL unless you are using a separate discovery layer
These endpoints are intended for local operator workflows and are rejected for non-loopback callers.
Returns current single-provider OIDC runtime status.
Example:
curl -s http://127.0.0.1:8080/admin/oidc/config | jqResponse shape:
{
"status": "ok",
"oidc": {
"configured": true,
"issuer_url": "https://issuer.example",
"client_id": "tokensmith-client",
"local_user_mint_enabled": false
}
}Applies a single-provider OIDC runtime update in-process (no restart required).
Request body:
{
"issuer_url": "https://issuer.example",
"client_id": "tokensmith-client",
"replace_existing": false,
"dry_run": false
}Notes:
- if an OIDC provider already exists,
replace_existingmust betrue dry_run=truevalidates and reports create/replace result without applying- client secrets are env-only (
OIDC_CLIENT_SECRET) and are not accepted in request payload
Canonical token endpoint for the service-to-service bootstrap and refresh flows.
Compatibility alias for the same RFC 8693 / RFC 6749 token handling used by the service-token flow.
For new integrations, prefer POST /oauth/token.
Mint an access token + refresh token session using mTLS client identity.
Requirements:
- TokenSmith started with
--service-identity-ca <pem> - TokenSmith started with TLS listener flags (
--tls-cert-file,--tls-key-file) - caller presents a client certificate signed by the configured service-identity CA
Behavior:
- service identity subject is extracted from client certificate Common Name (
CN) - TokenSmith looks up policy by subject (same subject/audience/scopes model used by bootstrap policy storage)
- response shape matches
POST /oauth/tokensuccess payload (access_token,refresh_token,expires_in, etc.)
Example:
curl -s https://tokensmith.example/service-identity/session \
--cert /etc/openchami/tls/service.crt \
--key /etc/openchami/tls/service.key \
-X POST | jqExchange a one-time bootstrap token for an access token and refresh token.
Request format:
- method:
POST - content type:
application/x-www-form-urlencoded
Required form fields:
grant_type=urn:ietf:params:oauth:grant-type:token-exchangesubject_token=<bootstrap-token>subject_token_type=urn:openchami:params:oauth:token-type:bootstrap-token
Example:
curl -s http://localhost:8080/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token=<bootstrap-token>' \
--data-urlencode 'subject_token_type=urn:openchami:params:oauth:token-type:bootstrap-token'Successful response shape:
{
"access_token": "<service-jwt>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<opaque-refresh-token>",
"refresh_expires_in": 86400,
"scope": "read write",
"issued_token_type": "urn:ietf:params:oauth:token-type:access-token"
}Notes:
- audience and scopes are determined server-side from the bootstrap token policy
- bootstrap tokens are one-time use
- reusing a consumed token fails with
invalid_grant
Rotate a refresh token and receive a new access token plus a new refresh token.
Request format:
- method:
POST - content type:
application/x-www-form-urlencoded
Required form fields:
grant_type=refresh_tokenrefresh_token=<opaque-refresh-token>
Example:
curl -s http://localhost:8080/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<opaque-refresh-token>'Notes:
- refresh tokens are rotated on every successful use
- replaying an old refresh token revokes the entire token family
- expired or revoked refresh tokens fail with
invalid_grant
TokenSmith returns OAuth-style JSON error responses:
{
"error": "invalid_grant",
"error_description": "The provided token is invalid or has already been used"
}Observed error codes include:
invalid_requestunsupported_grant_typeinvalid_granttoo_many_requestsserver_error
Observed status codes include:
200 OK400 Bad Request405 Method Not Allowed429 Too Many Requests500 Internal Server Error
Bootstrap tokens are single-use. Once redeemed, the server marks the bootstrap policy as consumed and rejects future reuse attempts.
TokenSmith rate limits failed bootstrap exchanges per client IP.
Current behavior:
- 5 failed bootstrap exchanges per client IP
- 60 second window
- exceeding the threshold returns
429 too_many_requests
Refresh tokens are tracked as token families.
If an old rotated refresh token is replayed, the family is revoked and future refresh attempts for that family are rejected.