A working reference implementation of a Zero-Trust architecture for internal
(East-West) APIs. Every request between services is authenticated with mutual
TLS, authorized with a JSON Web Token, and - crucially - the token is
cryptographically bound to the caller's TLS client certificate
(RFC 8705 certificate-bound access
tokens, cnf.x5t#S256). A stolen token cannot be replayed from another node,
because it is only honoured on a connection that proves possession of the
matching certificate.
The repository also ships a deliberately vulnerable bearer-token baseline so the difference can be demonstrated: the same token-theft attack that succeeds against the baseline is blocked by the Zero-Trust design.
Reference implementation accompanying a bachelor's thesis on Zero-Trust architectures for internal APIs.
An ordinary bearer JWT follows the rule "whoever holds the token may use it." On an internal network that has historically been treated as trusted, a token leaked through logs, SSRF, a compromised sidecar, or a misrouted request can be replayed from anywhere - enabling lateral movement. Binding the token to the holder's certificate turns "whoever holds the token" into "whoever holds the token and the private key behind the certificate it was issued to," which is the proof-of-possession property this project demonstrates.
Each service is a Policy Enforcement Point (PEP) that runs four fail-closed checks on every request, in order:
| # | Check | Rejects |
|---|---|---|
| 1 | mTLS - a client certificate that nginx verified is present | requests with no/invalid certificate (at the TLS layer) |
| 2 | JWT - signature (via JWKS), iss / aud / exp / nbf / scope |
forged, expired or misaddressed tokens |
| 3 | Proof of possession - cnf.x5t#S256 equals the presented cert's thumbprint |
tokens replayed from a different certificate |
| 4 | Authorization - the central PDP permits subject + action + resource | actions outside least privilege |
The mTLS-terminating reverse proxy follows the deployment described in RFC 8705 §3: nginx verifies the client certificate chain and forwards the leaf to the app, which re-derives the thumbprint for the binding check (defense in depth).
Requires Docker with Compose v2.
make up # build images, generate the PKI, start the whole system
make demo # run the legitimate consumer (happy path)
make attacks # run the attack scenarios: baseline vs Zero-Trust
make down # stop everything and remove volumesmake demo shows a successful orders and billing read plus a 403 when the
consumer tries to write billing (least privilege). make attacks prints a table
contrasting the baseline (attack succeeds) with the Zero-Trust system (blocked).
| Path | Role |
|---|---|
pki/ca.py |
Internal CA (EC P-256); issues server/client certificates |
auth_server/ |
Authorization Server: issues cert-bound JWTs, serves JWKS |
common/pep.py |
Policy Enforcement Point - the four-step check |
common/jwt_utils.py |
ES256 token minting/validation, JWKS helpers |
common/mtls.py |
x5t#S256 thumbprint, client-cert parsing |
pdp/ |
Central Policy Decision Point + policies.yaml |
services/ |
Internal orders and billing APIs |
client/consumer.py |
Legitimate caller (happy path) |
baseline/ |
Vulnerable bearer-token baseline |
attacks/ |
Token replay, missing certificate, forged token |
bench/ |
Latency/throughput benchmark and charts |
nginx/gateway.conf |
mTLS-terminating reverse proxy |
Measures the per-request cost of stacking the controls (HTTP → TLS → mTLS → mTLS+JWT+PoP):
docker compose run --rm bench # writes bench/results/results.json
python bench/plot.py # writes bench/figures/{latency,rps}.pngpip install -r requirements.txt
python -m pytest tests/ -qThe suite covers each control with positive and negative cases; the headline test
is the token replay: a valid token presented from a different certificate is
rejected with certificate binding mismatch.
- RFC 8705 - OAuth 2.0 mutual-TLS client authentication and certificate-bound access tokens
- RFC 7800 - proof-of-possession key semantics for JWTs (
cnf) - RFC 7519 - JSON Web Token
- NIST SP 800-207 - Zero Trust Architecture
MIT - see LICENSE.
