RFC-0023: Federation Security#
Status: Proposed
Created: 2026-02-25
Authors: OpenIntent Contributors
Requires: RFC-0001 (Intents), RFC-0018 (Cryptographic Identity), RFC-0019 (Verifiable Event Logs), RFC-0022 (Federation Protocol)
Abstract#
This RFC layers authentication, authorization, and verification onto federation (RFC-0022). It defines server identity, signed envelopes, delegation tokens, trust policies, and cross-server event log reconciliation.
Motivation#
RFC-0022 defines the federation contract — what data moves between servers and when. It deliberately defers security to this companion RFC so that trusted intra-org deployments can federate without cryptographic overhead.
Cross-org and public federation require answers to four questions:
- Identity. How does Server B verify that a request actually came from Server A?
- Authorization. How does Server B verify that Server A is allowed to dispatch this particular intent with these permissions?
- Integrity. How does Server A verify that Server B's results haven't been tampered with?
- Delegation. How does Server B prove to Server C that it's acting on behalf of Server A, with narrowed permissions?
Specification#
Server Identity#
Servers identify themselves using did:web decentralized identifiers backed by Ed25519 key pairs:
from openintent.federation.security import ServerIdentity
identity = ServerIdentity.generate(server_url="https://server-a.example.com")
# identity.did => "did:web:server-a.example.com"
# identity.public_key => Ed25519 public key bytes
# identity.private_key => Ed25519 private key bytes
The DID document is published at /.well-known/did.json:
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:web:server-a.example.com",
"verificationMethod": [{
"id": "did:web:server-a.example.com#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:server-a.example.com",
"publicKeyMultibase": "z6Mk..."
}],
"authentication": ["did:web:server-a.example.com#key-1"]
}
Envelope Signing#
Federation envelopes are signed using Ed25519:
from openintent.federation.security import sign_envelope, verify_envelope_signature
signed = sign_envelope(envelope, identity)
# signed.signature is set
is_valid = verify_envelope_signature(signed, identity.public_key)
HTTP Message Signatures (RFC 9421)#
For transport-level authentication, MessageSignature implements RFC 9421:
from openintent.federation.security import MessageSignature
sig = MessageSignature.create(
method="POST",
url="/api/v1/federation/dispatch",
body=envelope_bytes,
identity=identity
)
is_valid = MessageSignature.verify(sig, identity.public_key)
Trust Policies#
TrustEnforcer implements three trust modes:
| Policy | Behavior |
|---|---|
open |
Accept all federation requests |
allowlist |
Accept only from listed server DIDs |
trustless |
Require valid signature and UCAN delegation chain |
from openintent.federation.security import TrustEnforcer, TrustPolicy
enforcer = TrustEnforcer(
policy=TrustPolicy.ALLOWLIST,
allowed_servers=["did:web:server-b.example.com"]
)
enforcer.enforce(envelope) # raises if not allowed
UCAN Delegation Tokens#
UCAN (User Controlled Authorization Networks) tokens encode delegation chains:
from openintent.federation.security import UCANToken
token = UCANToken.create(
issuer=identity,
audience="did:web:server-b.example.com",
capabilities=["dispatch", "receive"],
expiry_seconds=3600
)
encoded = token.encode() # base64url JWT-style string
decoded = UCANToken.decode(encoded)
# Attenuate for sub-delegation
narrowed = token.attenuate(capabilities=["receive"])
SSRF Protection#
Outbound federation URLs are validated to prevent Server-Side Request Forgery:
from openintent.federation.security import validate_ssrf
validate_ssrf("https://server-b.example.com") # OK
validate_ssrf("http://localhost:8080") # raises ValueError
validate_ssrf("http://169.254.169.254") # raises ValueError (cloud metadata)
Blocked ranges: localhost, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, IPv6 loopback.
Cross-Server Event Log Reconciliation#
Federated intents produce events on both the originating and receiving servers. RFC-0019 Merkle primitives allow both servers to verify event log consistency:
- Each server maintains its own hash chain for federated events
- Attestations include the Merkle root at completion time
- Either server can request an inclusion proof for any event
Security Considerations#
- Key rotation:
ServerIdentitysupports key rotation by publishing updated DID documents. Old keys remain valid for signature verification during a transition period. - Token expiry: UCAN tokens include mandatory expiry. Expired tokens are rejected regardless of signature validity.
- HMAC fallback: For environments without Ed25519 support, HMAC-SHA256 signing is available as a fallback (shared secret required).
SDK Implementation#
See the Federation Guide for usage examples and the Federation API Reference for complete class documentation.