Identity & Trust — How It Works
This page explains how connectors prove their identity and establish trust using the Decentralized Claims Protocol (DCP).
Two DIDs Per Machine
Each machine has two separate identities with different jobs:
┌─────────────────────────────────────────────────────────────────┐
│ Machine (e.g. 192.168.1.50) │
│ │
│ ┌───────────────────────────┐ ┌────────────────────────────┐ │
│ │ Participant DID │ │ Issuer DID │ │
│ │ did:web:host%3A7093 │ │ did:web:host%3A9876 │ │
│ │ │ │ │ │
│ │ Served by: Identity Hub │ │ Served by: nginx │ │
│ │ Key: Ed25519 │ │ Key: EC P-256 │ │
│ │ Port: 7093 │ │ Port: 9876 │ │
│ │ │ │ │ │
│ │ "This is who I am" │ │ "I vouch for members" │ │
│ │ Used for: DSP protocol │ │ Used for: signing VCs │ │
│ └───────────────────────────┘ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
The participant DID identifies the connector in protocol interactions (catalog requests, negotiations, transfers). Its Ed25519 key pair is auto-generated by the Identity Hub.
The issuer DID signs Verifiable Credentials. Its EC P-256 key pair is generated by generate-keys.sh and never leaves the machine. In standalone mode, each machine is its own issuer — it signs its own membership credential.
Setup Phase
Setting up a machine has four steps. Each step feeds into the next:
Step 1: Generate Keys
./generate-keys.sh
Generates key material on disk:
generate-keys.sh
│
├──→ deployment/assets/issuer_private.pem (EC P-256 key pair
│ deployment/assets/issuer_public.pem for signing VCs)
│
└──→ config/certs/private-key.pem (key pair for Data Plane
config/certs/public-key.pem EDR token signing)
Step 2: Build Docker Images
./gradlew dockerize
Builds three Docker images from source:
| Image | Source |
|---|---|
controlplane:latest | runtimes/controlplane/ |
dataplane:latest | runtimes/dataplane/ |
identityhub:latest | runtimes/identityhub/ |
Each image: eclipse-temurin JRE + shadow JAR + health check.
Step 3: Start Services
docker compose up -d
Starts services in dependency order:
postgres, vault, did-server, http-receiver ← start in parallel (no deps)
│ │
▼ ▼
identityhub ← waits for postgres + vault healthy
│
▼
controlplane ← waits for postgres + vault + identityhub + did-server
│
▼
dataplane ← waits for postgres + vault + controlplane
Configuration is injected via environment variables:
MY_PUBLIC_HOST— DID identifiers, callback URLs, DP public URLTRUSTED_ISSUER_DIDS— trusted issuer registry in Control Plane
Step 4: Seed Identity
./deployment/seed.sh
The seed script performs seven substeps:
- Generate MembershipCredential — signs a VC JWT with the issuer private key
- Create participant context in Identity Hub — generates Ed25519 key pair, returns client ID/secret
- Activate participant — marks the participant as active
- Publish participant DID — makes the DID document available at
http://<host>:7093/.well-known/did.json - Store STS client secret in Vault — so the Control Plane can authenticate to the STS
- Store MembershipCredential in wallet — Identity Hub can now present it during DCP auth
- Update issuer DID document on nginx — makes the issuer public key available at
http://<host>:9876/.well-known/did.json
Runtime Flow — Catalog Request Between Two Machines
When Machine B (consumer) requests Machine A’s (provider) catalog, seven steps happen:
1. Get Token
Machine B’s Control Plane requests an SI (Self-Issued) token from its local STS (Identity Hub port 7096). The STS returns a JWT containing an inner access token.
2. Send DSP Request
Machine B sends the catalog request to Machine A’s DSP endpoint (port 19194) with the SI token as a Bearer token.
3. Verify SI Token
Machine A reads the iss claim from the token (did:web:B:7093), resolves Machine B’s participant DID document over HTTP, extracts the Ed25519 public key, and verifies the JWT signature.
4. Request Credentials
Machine A extracts the inner access token (which contains scope: MembershipCredential:read), reads the CredentialService URL from Machine B’s DID document, and sends a presentation request to Machine B’s Identity Hub (port 7091).
5. Present Credential
Machine B’s Identity Hub finds the MembershipCredential in its wallet and wraps it in a Verifiable Presentation (VP).
6. Verify MembershipCredential
Machine A checks:
- Is the VC’s issuer (
did:web:B:9876) in the trusted issuer registry? - Resolves the issuer DID document from nginx (port 9876) to get the P-256 public key
- Verifies the VC JWT signature
- Checks VC type and expiry
7. Return Catalog
All checks pass — Machine A returns its catalog to Machine B.
Machine B (consumer) Machine A (provider)
Control Plane ──→ STS: "token for A"
Control Plane ──→ A's DSP: catalog request + SI token
A resolves B's DID ──→ verify SI token ✓
A calls B's Credential API ──→ get VP
A resolves B's issuer DID ──→ verify VC ✓
Catalog response ←── A returns catalog
The flow is fully symmetric. When Machine A requests Machine B’s catalog, the roles mirror exactly.
Token Structure
The SI token uses a token-in-token pattern:
┌─ Outer JWT (SI Token) ──────────────────────────────────────┐
│ │
│ Header: { alg: "EdDSA", kid: "did:web:B:7093#key-1" } │
│ │
│ Payload: { │
│ iss: "did:web:B:7093" ← who is making request │
│ aud: "did:web:A:7093" ← who the request is for │
│ exp: ... │
│ │
│ token: ┌─ Inner JWT (Access Token) ────────────────────┐ │
│ │ scope: "org.eclipse.edc.vc.type: │ │
│ │ MembershipCredential:read" │ │
│ │ │ │
│ │ Tells the provider what credential │ │
│ │ to request from the consumer's wallet │ │
│ └───────────────────────────────────────────────┘ │
│ } │
│ │
│ Signed with: Machine B's Ed25519 private key │
└─────────────────────────────────────────────────────────────┘
Trust Chain
Machine A trusts Machine B because:
- B’s SI token is signed by B’s Ed25519 key — verified via DID resolution (
did:web:B:7093) - B has a MembershipCredential — presented from B’s Identity Hub wallet
- The VC is signed by B’s issuer (
did:web:B:9876) — issuer is in A’sTRUSTED_ISSUER_DIDSlist, signature verified via issuer DID resolution
Key Verification Summary
| What is verified | Key used | Key type | Public key source |
|---|---|---|---|
| SI token (DSP request auth) | Participant key | Ed25519 | did:web:host%3A7093 — Identity Hub DID document |
| MembershipCredential (VC) | Issuer key | EC P-256 | did:web:host%3A9876 — nginx DID server |