TRUST · PROVE · AUTHENTICATE · AUTHORIZE
mTLS: verify both peers, then authorize the request
Real local cryptographic checks. Separate application permissions. Explicit teaching boundaries.
Client authentication
Application permission
Stage ledger
Exact cryptographic and policy evidence
Separate peer identity from application permission
This experiment prepares independent client and server key pairs, signs a teaching handshake transcript and verifies both private-key proofs with browser WebCrypto. It then authenticates an encrypted fictional request and evaluates a separate resource policy. These are distinct gates. A completed mutually authenticated transport can still receive a simulated forbidden response from the application. Conversely, permitting a transport to continue without a client identity does not automatically grant access to the fictional report. No service, account, network endpoint or real credential is contacted by this lab.
Choose the local trust and client-certificate policy
Trust server key and Trust client key configure local pinned-key fixtures. Enabled pins match the freshly generated peer public-key fingerprint; disabled pins deliberately mismatch it. These switches do not parse or validate real certificates. Present client identity determines whether the client sends its fictional identity record or an empty certificate list. Require client identity determines whether that empty response aborts the handshake. The server requests a client certificate in both modes. In this exercise, a presented but untrusted identity always aborts even when absence would have been permitted. This is the selected strict policy, not the only possible server implementation.
Change the identity and the permission independently
Presented client identity selects alpha or beta in the signed teaching record. Allowed identity is the application allowlist entry, not a change to cryptographic trust. Application permission chooses read-only or read-and-write, while Requested action chooses read or write. Restore defaults, show the final result and observe simulated status two hundred for alpha reading its report. Change Requested action to write and show the result again: the transport still completes and the record integrity check passes, but application permission denies the operation with status four hundred three. Grant read-and-write to allow it. Change Allowed identity to beta while presenting alpha to reproduce a distinct identity-policy denial.
Break actual bytes at a chosen boundary
Tamper with selects no fault, the server signature, client signature, server Finished, client Finished or application record. Signature options flip a byte of an actual ECDSA signature before verification. Finished options alter the real HMAC value before comparison. Record tampering flips a byte before AES-GCM decryption. Show the final result after each edit and inspect where evaluation stops. Later gates remain not checked, and a failed handshake never receives an application HTTP status. Record tampering occurs after handshake completion, so it instead blocks the application policy from receiving an authenticated request.
Inspect the client-authentication boundary
Disable Present client identity while keeping Require client identity enabled. The server rejects the empty identity response. Disable the requirement too: the transport completes without authenticating the client, but this application still denies its report request. Restore defaults and use Next stage to follow server Finished before the client certificate and private-key proof. The transcript order and the two direction-specific proof contexts are visible in Exact evidence. Fresh keys and certificate-like records are generated locally for each configuration edit; no external certificate authority is consulted.
Use playback as inspection time
Play reveals the computed stage snapshots over sixty inspection seconds. Pause freezes the selected stage; Next stage advances one; Restart rewinds the same prepared run. Speed changes viewing pace and Inspect time scrubs backward or forward. Show final result skips to the terminal outcome. New local keys repeats the computation with fresh ephemeral and identity keys without changing your selected policy. Restore defaults resets all trust, identity, permission and fault controls. Controls that need a prepared trace remain disabled while cryptographic work is running, and rapid edits discard older pending results. The textual gate cards and stage ledger supplement the client/server diagram.
Understand precisely what is simplified
The key exchange uses P-256 ECDH, the proofs use ECDSA with SHA-256, Finished uses HMAC, and the application example uses AES-GCM. The handshake transcript is stable JSON, not TLS binary encoding. WebCrypto signatures are raw-format values, not the encoded signature format of an actual TLS implementation. The local public-key pins and alpha/beta labels replace X.509 chain validation, hostname and extended-key-usage checks, certificate expiration and revocation. Handshake records are not encrypted in this teaching transcript. The one application record has synthetic associated data and no real TLS record header. There is no session resumption, cipher negotiation, certificate rotation, post-handshake authentication or production authorization engine. The purpose is to inspect real cryptographic rejection and the identity-to-permission boundary, not certify a service as secure.
Protocol reference: TLS 1.3 authentication messages.