Production-ready API gateway using Decentralized Identifiers (DIDs) and Verifiable Credentials (VCs) for privacy-preserving authentication and authorization.
This gateway enables passwordless, privacy-preserving authentication for APIs without traditional usernames, passwords, or centralized identity providers.
✅ W3C Standards Compliant - Full DID Core and Verifiable Credentials support
✅ Multiple DID Methods - did:key (local), did:web (domain-based), did:ion (blockchain)
✅ Zero Trust Architecture - Every request authenticated and authorized
✅ Privacy-Preserving - Users control their data, no central registry
✅ Production-Grade - Multi-zone deployment, auto-scaling, automated backups
✅ Self-Healing - Circuit breakers, retry logic, automatic failover
┌──────────────────────────────────────────────────────────────┐
│ Client Applications │
│ (wallet-cli, Web App, Mobile App, Browser Extension) │
└────────────────────┬─────────────────────────────────────────┘
│ HTTPS + TLS 1.3
▼
┌──────────────────────────────────────────────────────────────┐
│ Load Balancer │
│ (Multi-zone, Health-check aware) │
└────────────────────┬─────────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Gateway │ │ Gateway │ │ Gateway │ (6 replicas across
│ Zone A │ │ Zone B │ │ Zone C │ 3 availability zones)
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└──────────────┼──────────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ DID Resolution │ │ VC Verification │
│ ┌────────────┐ │ │ ┌────────────┐ │
│ │ did:key │ │ │ │ JWT-VC │ │
│ │ did:web │ │ │ │ StatusList │ │
│ │ did:ion │ │ │ │ Revocation │ │
│ └────────────┘ │ │ └────────────┘ │
│ + Circuit Breaker│ │ + Trust Tier │ │
│ + Retry Logic │ │ + Policy Check│ │
└──────────────────┘ └──────────────────┘
│ │
└───────────────┬───────────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Multi-Layer │ │ PostgreSQL HA │
│ Cache (Redis) │ │ + Sentinel │
│ ┌────────────┐ │ │ ┌────────────┐ │
│ │ L1: Ristretto│ │ │ Policies │ │
│ │ L2: Redis │ │ │ │ Issuers │ │
│ │ <80% hits │ │ │ │ Revocations│ │
│ └────────────┘ │ │ └────────────┘ │
│ 3 replicas │ │ 3 replicas │
└──────────────────┘ └──────────────────┘
│
▼
┌──────────────────┐
│ Upstream API │
│ (Protected) │
└──────────────────┘
- Go 1.21+
- Docker & Docker Compose
- PostgreSQL 16+ (or use Docker)
- Redis 7+ (or use Docker)
# Clone repository
git clone https://github.com/example/privacy-gateway
cd privacy-gateway
# Start all services
docker compose up --build
# Services will be available at:
# - Gateway: http://localhost:8080
# - Issuer: http://localhost:8090
# - PostgreSQL: localhost:5431
# - Redis: localhost:6379# Build wallet CLI
go build -o wallet-cli cmd/wallet-cli/main.go
# 1. Generate a new DID wallet
./wallet-cli did new --out ./wallet.json
# Output: did:key:z6MkkSC2U9aJDrzgV64PZL8Rqi75aPVifp4iqKtqb6XfoUcM
# 2. Request a credential from issuer
./wallet-cli cred request \
--issuer http://localhost:8090 \
--did "$(cat wallet.json | jq -r .did)" \
--type PremiumCredential \
--claims plan=premium \
--out ./cred.jwt
# 3. Register issuer as trusted (one-time setup)
./scripts/register-issuer.sh
# 4. Authenticate and get access token
./wallet-cli auth verify \
--gateway http://localhost:8080 \
--wallet ./wallet.json \
--cred ./cred.jwt \
--scopes premium
# Output: {"access_token":"eyJ...","expires_in":300}
# 5. Call protected API
./wallet-cli call \
--gateway http://localhost:8080 \
--token "YOUR_ACCESS_TOKEN" \
--path /api/v1/premiumFormat: did:key:z6MkkSC2U9aJDrzgV64PZL8Rqi75aPVifp4iqKtqb6XfoUcM
- ✅ Self-sovereign - No central registry
- ✅ Instant - No network lookup required
- ✅ Perfect for testing - Generate offline
- 🔐 Security: Ed25519 public key embedded in DID
Example:
./wallet-cli did new --out wallet.json
# Creates did:key with embedded public keyFormat: did:web:example.com or did:web:example.com:users:alice
- ✅ Human-readable - Uses your domain name
- ✅ DNS-based trust - Leverage existing web infrastructure
- ✅ Easy rotation - Update DID document at
.well-known/did.json - 🔄 Cache TTL: 1 hour (configurable)
Resolver:
did:web:example.com→https://example.com/.well-known/did.jsondid:web:example.com:users:alice→https://example.com/users/alice/did.json
Circuit Breaker: 5 failures, 60s reset, 3 retry attempts
Format: did:ion:EiDahaOGH-liLLdDtTxEAdc8i-cfCz-WUcQdRJheMVNn3A
- ✅ Decentralized - Anchored on Bitcoin blockchain
- ✅ High trust - Immutable, censorship-resistant
- ✅ Standards-based - Sidetree protocol
- ⏱️ Slower - Blockchain resolution (~1-3s)
Resolver: https://ion.msidentity.com/identifiers/{did}
Circuit Breaker: 5 failures, 120s reset, 5 retry attempts (aggressive)
- Multi-key Token Management - JWT with key rotation support
- Secrets Management - Environment, Kubernetes, Vault providers
- TLS/mTLS - End-to-end encryption, mutual authentication
- Security Headers - CSP, HSTS, X-Frame-Options, X-XSS-Protection
- Input Validation - DID format validation, size limits, sanitization
- Rate Limiting - Per-DID, per-route, Redis-backed
- W3C DID Core - Compliant DID resolution and DID documents
- Verifiable Credentials - JWT-VC format with cryptographic proofs
- StatusList2021 - Privacy-preserving revocation checking
- Trust Tiers - Issuer reputation system (1-5 scale)
- Policy Engine - Dynamic access control based on VC types
Multi-Layer Caching:
- L1 Cache (Ristretto): In-memory, <1ms latency
- L2 Cache (Redis): Distributed, 1-5ms latency
- Target: >80% cache hit rate
- TTL: did:key (permanent), did:web (1h), did:ion (24h)
Horizontal Auto-Scaling (HPA):
- Min replicas: 3
- Max replicas: 20
- Metrics: CPU (70%), Memory (80%), RPS (1000/pod)
- Scale-up: 50%/min (fast)
- Scale-down: 10%/min (slow, prevent flapping)
Database Optimization:
- 8 performance indexes on policies, issuers, revocations
- Connection pooling
- Query optimization
Load Testing:
- k6 test suite included
- Target: 5,000 RPS sustained
- P99 latency: <100ms
High Availability:
- Multi-zone deployment - 6 replicas across 3 availability zones
- Pod anti-affinity - Spread across nodes and zones
- Tolerate failures - Survives entire zone outage
- Zero downtime updates - Rolling deployment with maxUnavailable=1
Circuit Breakers:
- Prevents cascading failures
- Automatic recovery detection
- Fast-fail when services are down
- Metrics tracking (open/closed/half-open)
Retry Logic:
- Exponential backoff with jitter
- Configurable max attempts
- Retryable vs non-retryable errors
- Context-aware cancellation
Automated Backups:
- Frequency: Daily at 2 AM (CronJob)
- Storage: Local + S3 (off-site)
- Retention: 7 days
- Compression: gzip
- Verification: Automated restore testing
Disaster Recovery:
- RTO (Recovery Time Objective): 30 minutes
- RPO (Recovery Point Objective): 15 minutes
- 5 disaster scenarios documented
- Tested recovery procedures
- Runbook: docs/disaster-recovery.md
Redis Sentinel:
- 3 replicas with automatic failover
- Quorum = 2
- <10s failover time
- Zero data loss
Metrics (Prometheus):
- Request rate, latency (p50, p95, p99)
- Error rate by endpoint
- DID resolution success/failure rate
- Cache hit/miss rate
- Circuit breaker state
- HPA scaling events
Health Checks:
/healthz- Full health with component details/healthz/live- Liveness probe (Kubernetes)/healthz/ready- Readiness probe (Kubernetes)
Structured Logging:
- JSON format
- Request ID tracing
- Performance metrics
Dashboards:
- Grafana overview dashboard (deploy/monitoring/)
- Prometheus alerts configured
- SLO tracking (99.9% availability)
docker compose up --buildServices:
- Gateway: :8080
- Issuer: :8090
- PostgreSQL: :5431
- Redis: :6379
- Upstream (mock): :8081
# Apply configurations
kubectl apply -f deploy/k8s/
# Includes:
# - gateway-ha.yaml (6 replicas, multi-zone)
# - redis-sentinel.yaml (3 replicas, auto-failover)
# - hpa.yaml (auto-scaling)
# - backup-cron.yaml (daily backups)
# Verify deployment
kubectl get pods -l app=did-gateway
kubectl get hpa
kubectl get pdb
# Check health
kubectl port-forward svc/did-gateway 8080:8080
curl http://localhost:8080/healthz | jq# Gateway
GATEWAY_ADDR=:8080 # Listen address
POSTGRES_DSN=postgres://... # Database connection
REDIS_ADDR=redis:6379 # Redis connection
TOKEN_ISSUER=gateway # JWT issuer
TOKEN_SECRET=... # JWT signing key (use secrets manager)
LOG_LEVEL=info # info, debug, warn, error
# Issuer
ISSUER_ADDR=:8090
ISSUER_KEY_FILE=/data/issuer/keys.json# Run all tests
go test ./...
# With coverage
go test -cover ./...
# Specific package
go test ./internal/gateway/did/... -vcd test/load
# Interactive test runner
./run-tests.sh
# Options:
# 1. Full auth flow (100 → 10,000 VUs)
# 2. DID resolution (cache hit rate testing)
# 3. Quick smoke test (100 VUs, 1 minute)
# 4. Custom scenario
# 5. Run all tests
# Direct k6 execution
k6 run auth-flow.js
k6 run did-resolution.jsPerformance Targets:
- Max RPS: 5,000
- P99 latency: <100ms
- Error rate: <1%
- Cache hit rate: >80%
# Full auth flow
./test-auth-flow.sh
# DID resolution
./test-did-resolution.sh
# Credential verification
./test-vc-verification.sh.
├── cmd/
│ ├── gateway/ # API Gateway entrypoint
│ ├── issuer/ # VC Issuer entrypoint
│ ├── upstream/ # Mock upstream API
│ └── wallet-cli/ # CLI tool for testing
├── internal/
│ ├── gateway/
│ │ ├── api/ # HTTP handlers
│ │ ├── did/ # DID resolution (key/web/ion)
│ │ ├── policy/ # Policy engine
│ │ └── vc/ # VC verification
│ └── shared/
│ ├── cache/ # Multi-layer caching
│ ├── circuitbreaker/ # Circuit breaker
│ ├── health/ # Health checks
│ ├── retry/ # Exponential backoff
│ └── secrets/ # Secrets management
├── deploy/
│ ├── k8s/ # Kubernetes manifests
│ ├── docker/ # Docker configs
│ ├── scripts/ # Deployment scripts
│ └── monitoring/ # Grafana dashboards
├── test/
│ ├── load/ # k6 load tests
│ └── did-web-server/ # Test server for did:web
└── docs/ # Documentation
# Build all binaries
go build ./cmd/gateway
go build ./cmd/issuer
go build ./cmd/wallet-cli
# Run locally
./gateway &
./issuer &
# Test
./wallet-cli did new --out test.json# Format code
go fmt ./...
# Lint
golangci-lint run
# Security scan
gosec ./...
# Dependency audit
go list -m all | nancy sleuthPolicies define access rules in deploy/docker/migrations/gateway/002_seed.sql:
INSERT INTO policies (id, name, route_prefix, required_scopes, required_vc_types)
VALUES
('public', 'Public', '/api/v1/public', '{}', '{}'),
('basic', 'Basic', '/api/v1/basic', '{basic}', '{}'),
('premium', 'Premium', '/api/v1/premium', '{premium}', '{PremiumCredential}');Register trusted issuers:
# Automatic registration
./scripts/register-issuer.sh
# Manual registration
kubectl exec -it postgres-0 -- psql -U gateway -d gateway << EOF
INSERT INTO issuers (did, public_key, enabled, trust_tier)
VALUES ('did:key:...', 'base64_public_key', true, 1);
EOFTrust Tiers:
- Tier 1: Basic trust (default)
- Tier 2: Verified issuer
- Tier 3: High-trust issuer
- Tier 4: Premium issuer
- Tier 5: Maximum trust (government, banks)
Cause: Issuer not registered or keys changed (tmpfs restart)
Solution:
# Re-register issuer
./scripts/register-issuer.sh
# Get fresh credential
./wallet-cli cred request --issuer http://localhost:8090 ...Cause: Services not ready (PostgreSQL/Redis starting)
Solution:
# Check service health
docker compose ps
# Wait for health checks
docker compose logs postgres | grep "ready to accept"
docker compose logs redis | grep "Ready to accept"Cause: External service (did:web, did:ion) is down/slow
Solution:
# Check circuit breaker stats
curl http://localhost:8080/metrics | grep circuit_breaker
# Manual reset (if needed)
# Circuit auto-recovers after timeout (60s web, 120s ion)Cause: Cache warming needed or TTL too short
Solution:
# Check cache stats
curl http://localhost:8080/metrics | grep cache_
# Warm cache with common DIDs
for did in $(cat common-dids.txt); do
curl "http://localhost:8080/v1/resolve?did=$did"
doneWe welcome contributions! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Write tests for new functionality
- Ensure all tests pass (
go test ./...) - Format code (
go fmt ./...) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
- W3C DID Working Group - DID specifications
- W3C Verifiable Credentials - VC standards
- Microsoft ION - did:ion implementation
- StatusList2021 - Revocation standard
- Phase 5: Enhanced observability (distributed tracing)
- Phase 6: CI/CD automation
- Additional DID methods (did:ethr, did:pkh)
- BBS+ signatures for selective disclosure
- SDK for popular languages (JavaScript, Python)
- Zero-knowledge proof integration
- Federation with other gateways
- Compliance certifications (SOC 2, ISO 27001)