When someone opens a project-scope service through the access edge, the request reaches your app only after the server has authenticated the person and checked that they hold access to the project. Your app is told who that was. This page is what an app author needs to read that identity — and, when trusting the network is not enough, to verify it.

What arrives with every proxied request

HeaderValue
X-Orc-Userthe user's id
X-Orc-User-Emailtheir email address
X-Orc-Access-Assertionthe same identity as a signed token (below)
X-Forwarded-Hostthe access host the browser used
X-Forwarded-Protoalways https
X-Forwarded-Forthe client chain, with the server appended

Host is rewritten to the internal name your service knows itself by, so links your app builds from Host keep working; the server turns an absolute Location pointing back at that internal origin into the access origin on the way out.

Any X-Orc-* header on the incoming request is removed before these are added. A client cannot claim to be someone by typing the header.

A public name served through the edge carries none of these: nobody signed in, so there is nobody to name.

When the headers are enough, and when they are not

The headers are trustworthy exactly as far as your deployment is: the only route to your service's port is through the edge, which is why the port is not published in the first place. If something else can reach that port — a node in the same project, a sidecar, a developer with a forwarded port — then it can send the headers too, and your app cannot tell the difference.

The assertion removes that assumption. It is a compact JWT signed by the server with a key it never shares, so your app can check the signature itself and stop caring what else can reach it.

Verifying the assertion

The token is signed EdDSA (Ed25519) and its header names the key with kid. The public keys are published, unauthenticated, at:

https://orc8r.com/.well-known/orc-access/jwks.json

It is an ordinary JWKS, cacheable for five minutes:

{
  "keys": [
    {
      "kty": "OKP",
      "crv": "Ed25519",
      "use": "sig",
      "alg": "EdDSA",
      "kid": "9cfbac5a7ac647aa",
      "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
    }
  ]
}

Fetch it once, cache it, and refetch when you see a kid you do not know.

The claims

{
  "iss": "https://orc8r.com",
  "aud": "shop--obs.acme.example.com",
  "sub": "u_d3g2k9x1m4p7",
  "email": "ada@example.com",
  "name": "Ada Lovelace",
  "org": "acme",
  "project": "shop",
  "pool": "obs",
  "endpoint": "api",
  "iat": 1756800000,
  "exp": 1756800300
}

Check three things, in this order, and reject the request if any of them fails:

  1. the signature, against the key whose kid the token names;
  2. aud — it must equal your own access host, the one in X-Forwarded-Host. This is what stops an assertion minted for another service being replayed at yours;
  3. iss — it must be your control plane's URL, https://orc8r.com, and exp must be in the future.

Everything else is description: sub is the same id X-Orc-User carries, org, project, pool and endpoint say which route you were reached as, and name is absent when the account has no display name.

An assertion is good for five minutes and one is reused for up to a minute per person per route, so iat is not a per-request timestamp — do not treat it as a nonce, and do not use the assertion as a replay-proof action token.

With curl and jq

Read the keys:

curl -s https://orc8r.com/.well-known/orc-access/jwks.json | jq .

And, from inside a service that received a request, look at what it was told (decoding is not verifying — this is for seeing the shape):

printf '%s' "$HTTP_X_ORC_ACCESS_ASSERTION" \
  | cut -d. -f2 \
  | tr '_-' '/+' \
  | base64 -d 2>/dev/null \
  | jq .

Every JWT library that supports EdDSA and JWKS does the real check in a few lines: fetch the document, select by kid, verify, then compare aud and iss to your own configuration.

Rotation

The zone settings page has Rotate assertion key. Rotating mints a new key immediately and keeps publishing the previous public key for 24 hours, so a service holding a cached JWKS, or an assertion minted a moment before the rotation, keeps verifying. A library that refetches the document on an unknown kid needs no attention at all.

If no assertion header arrives at all, the server has nothing to sign with yet or does not know its own public URL — set Web URL on the zone settings page. Fall back to the identity headers, or refuse: your app decides which.