NATS WebCrypto Proof-of-Possession Authentication Example
This shows the authentication flow for browser-based Proof-of-Possession using a forked version of the nats.js client. This extends your NATS zero trust network all the way to the web browser.
NATS is a distributed messaging system where who can connect and what they can touch is governed by a cryptographic chain of trust. This example shows: 1) NATS permissions mapped from roles configured in an OIDC identity server. 2) A hierarchy of Ed25519-signed JWTs that allow different organizations to share infrastructure, control client access within each organization, and guarantee their data only ever goes to the clients authorized for it.
After log in to an OIDC identity server like keycloak, the browser generates a WebCrypto key pair and requests a NATS Zero Permission JWT from the SPA BFF, passing the public key. The SPA BFF validates the OIDC access token from an httpOnly cookie, and relays it to an internal signing service. That internal signing service re-verifies the token and mints a NATS User JWT with no actual access to any subjects, but having 1 critical anchor: the browser's public key is given in the sub claim. This Zero Permission JWT is passed back to the browser.
Then the browser opens a connection to NATS, which challenges the connection with a nonce. The browser signs that nonce with its non-extractable private key. The signed challenge, the ZP token, and the OIDC Access Token are used as credentials to access NATS. NATS uses the public key in the sub claim to verify possession of the private key. Then NATS delegates authorization to Auth-Callout, which validates the OIDC token and maps its claims to a NATS account and permissions - minting and signing a new User JWT then returning it to the broker. NATS retains that JWT internally to validate any requests from the browser as long as that connection is alive.