Freebird Integration
Witness can use Freebird verifier tokens as anonymous admission control for
creation through POST /v1/attestations.
Current Contract
Witness targets the current Freebird verifier contract:
| Method | Path | Use |
|---|---|---|
GET |
/.well-known/verifier |
Verifier ID, audience, and V4 scope digest. |
POST |
/v1/verify |
Validate and consume a V4 or V5 token. Reuse is rejected. |
POST |
/v1/check |
Validate a V4 or V5 token without consuming it. |
Verifier requests contain:
{
"token_b64": "<base64url-freebird-token>"
}
The Freebird verifier derives token version, issuer, expiry, audience/scope,
and nullifier state from the token and its issuer key discovery configuration.
Witness accepts token files with exactly the current Freebird verifier input:
token_b64.
Gateway Configuration
export FREEBIRD_VERIFIER_URL=https://freebird-verifier.example.org
export FREEBIRD_REQUIRED=true
export FREEBIRD_CONSUME_TOKENS=true
FREEBIRD_REQUIRED=true rejects new attestation jobs that do not include a token.
This should be the default for public gateways.
FREEBIRD_CONSUME_TOKENS=true uses /v1/verify and prevents token reuse. This
is the recommended mode for attestation-job creation.
FREEBIRD_CONSUME_TOKENS=false uses /v1/check. This proves token possession
without consuming the token, so it must be paired with another replay or rate
limit boundary.
Issuer trust, key discovery, expiry, and V4/V5 audience or scope checks belong in the Freebird verifier. Witness does not duplicate that policy.
For local integration tests only, set:
export FREEBIRD_ALLOW_INSECURE_LOCAL=true
This permits a plaintext loopback verifier URL. It rejects non-loopback hosts and should never be used for a public gateway.
Client Request Shape
Attestation creation requests may include a Freebird token:
{
"hash": "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e",
"freebird_token": {
"token_b64": "<base64url-freebird-token>"
}
}
The CLI can load the same JSON shape:
witness attest --file document.pdf --freebird-token token.json
The gateway validates the hash and checks for an existing canonical job before
calling Freebird. Polling with GET /v1/attestations/:hash and retrying POST
for an existing job do not consume another token. New-job admission and
reservation are serialized per hash within one gateway process; SQLite remains
the canonical cross-process race authority.
Production Notes
- Run the Freebird verifier over HTTPS.
- Use verifier-side trusted issuer/key discovery for V4 and V5.
- Use Redis-backed Freebird nullifier storage for public verifiers.
- Keep Witness and Freebird clocks synchronized.
- Prefer short-lived tokens for high-volume public gateways.
- Test both V4 private-verification tokens and V5 public bearer passes before claiming full Freebird compatibility.
Compatibility Checklist
- [ ] Token file with only
token_b64parses inwitness-cli. - [ ] Gateway sends only
token_b64to/v1/verifyor/v1/check. - [ ] Consuming mode rejects a reused token.
- [ ] Non-consuming mode allows a token to be checked and later consumed.
- [ ] V4 tokens are accepted when bound to the verifier scope digest.
- [ ] V5 public bearer tokens are accepted when the verifier trusts the issuer public key and audience.
Smoke Test
When the Freebird repository is checked out next to Witness, run:
./scripts/freebird-witness-smoke.sh
The script starts a local Freebird issuer/verifier, issues a current
token_b64 token, starts a local Witness network with Freebird required, and
creates an attestation job through the Witness CLI.