Skip to content

Signing keys and tokens ​

Atlas, Central, and regional services use signed JSON Web Tokens (JWTs) for service calls. A public JSON Web Key Set (JWKS) lets a receiver check a signature without holding the signing key.

A trusted key alone does not grant access. Each receiver also checks who issued the token, which service it targets, when it expires, and what it permits.

How keys reach a region ​

Flow diagram
Loading diagram...
  1. Atlas fetches and validates Central's public keys from the Central JWKS URL every 5 minutes. A failed fetch keeps the last valid set. Removing the URL clears that set.
  2. Atlas creates one regional Ed25519 signing key. Its private half stays in an Atlas Settings Password field.
  3. /api/atlas/jwks.json serves Central's stored public keys plus the regional Atlas public key. It never serves a private key.
  4. Atlas uses that set for API tokens. The proxy fetches it using the configured URL. Atlas passes the URL to Cargo during installation.

The endpoint returns a JSON keys array. Each key has an Ed25519 public value, EdDSA algorithm, and namespaced kid. Atlas accepts 1 to 100 Central keys. It rejects private key fields, duplicate IDs, and unsupported key types.

One key set, separate permissions

The combined key set lets a service verify a Central or regional Atlas signature. It does not make a token valid for every service. A token for Atlas, the proxy, or Cargo needs that service's own audience and claims. Never use an Atlas API token as a proxy credential.

Metal uses regional certificates and mutual TLS, not these JWTs. The security model explains its listeners.

Read a service token ​

A JWT has a signed header and claims. These fields define the service boundary:

FieldMeaning
Header algEdDSA, using an Ed25519 key.
Header kidcentral:<key ID> or atlas:<region ID>:<key ID>. Its prefix must match iss.
isscentral or this region's atlas:<region ID>.
subCaller label. It does not grant permission by itself.
audThe one service this token is for.
iat, expIssue and expiry times as Unix seconds. nbf is checked when present.
scopeOperations the receiver permits. Each service defines its own values.
tenantRequired for Atlas API access. Forbidden on proxy JWTs.
constraintsOptional proxy limits on site or domain names. Atlas API tokens cannot carry nonempty constraints.

An Atlas API token for tenant 7 in region 1 can have this decoded header and claim set. The actual token is the signed, encoded form of these values:

json
{
  "header": {"alg": "EdDSA", "kid": "atlas:1:key-1"},
  "claims": {
    "iss": "atlas:1", "sub": "cargo", "aud": "atlas-admin:1",
    "scope": "*", "tenant": "7", "iat": 1789072323, "exp": 1789072623
  }
}
ReceiverRequired audienceAuthority after signature check
Atlas tenant APIatlas-admin:<region ID>scope=* plus signed tenant. Tenant identity restricts records and X-Tenant-ID.
HTTP proxy control APIatlas-proxy:<region ID>Signed scope and optional name constraints. No tenant claim. Proxy authentication defines the route rules.
Cargo APIatlas-cargo:<region ID> for Atlas's bucket requestAtlas issues scope=*, tenant=0. Cargo's own validation rules are outside this repository.

For example, a Central caller needs a Central-signed token with the regional proxy audience and a permitted scope to change proxy routes. To call Atlas, it needs another token with the Atlas audience and a tenant claim. Atlas can also sign tokens for these services with its regional key.

A receiver rejects a token with a valid signature when its audience, issuer, expiry, or required claims do not match.

What Atlas issues for Cargo ​

During Cargo installation, Atlas supplies two tokens. One lets Cargo call the Atlas API as tenant 0. The other lets it update proxy site routes ending in -svc. Both last 365 days. The installer also receives the combined JWKS URL so Cargo can obtain public keys.

For a bucket request in the other direction, Atlas creates a short-lived token for the regional Cargo audience.

Cargo integration boundary

The Cargo implementation is not in this repository. Its installer currently receives placeholder Central URL and webhook secret values. Check Cargo's own documentation before relying on Central-to-Cargo authorization or webhook behavior.

If access fails ​

Check the receiver's audience first. Then check the kid prefix, iss, signature key, expiry, and service-specific claims.

For Central tokens, check whether the most recent JWKS sync succeeded and whether the stored set contains that key ID. An unknown key ID does not trigger an immediate Atlas fetch. The security model lists other control boundaries.

Source code and tests

AGPL-3.0