Binding Auth Tokens to Client Secrets Securely

Tokens Bound to Secrets
Bearer replay never dies, so this library kills it by binding every token to a client secret through a challenge-response proof.
A stolen token becomes dead weight without the secret, because the server verifies a cryptographic binding on every request, rejecting anything that lacks proof from the challenge handshake, closing replay windows that bearer schemes leave open.
Bearer's Fatal Flaw
Most auth tools fall into two camps. Bearer tokens are easy to steal and replay, while JWT exposes claims to interceptors. The gap was a token format that stays opaque, binds to a secret, and carries expiry in the binding so replay dies after expiry.
OAuth flows have flaws that CVEs document yearly, from PKCE bypass to state not bound to sessions, and the root cause is that bearer tokens carry no proof the presenter owns the credential, so the goal was a library that binds every token to a client secret through challenge and response, with opaque encrypted payloads only the server can decode, for SSO and confidential.

Cracks in the Flow
- Bearer tokens work for anyone who holds them, so interception means replay.
- JWT exposes claims to anyone who intercepts the token in transit.
- PKCE bypass lets servers skip verifier checks when challenge was present.
- State not bound to sessions allows CSRF and account linking takeover.
- Non-atomic state claim creates race conditions for one-time token use.
Serve Every Auth Flow
- Generate a challenge with a client secret, nonce, and expiry in the binding.
- Verify challenge, state, and token in constant time on the server side.
- Encrypt token payloads with AES-GCM so only the server can decode them.
- Attach a client binding tag through HMAC so only the holder can validate.
- Serve SSO, internal company auth, and confidential clients from one flow.
Single Secret, Triple Checks
The strategy is one binding, many flows. A challenge engine generates proof from a client secret, feeding a state manager that ties CSRF to the same binding, while a token encoder encrypts payloads with AES-GCM and attaches a client binding tag through HMAC, so the server verifies challenge, state, and token in constant time across SSO, internal auth, and confidential.
One secret, three checks, zero bearer exposure. Challenge, state, and token share one binding, so replay dies at every layer.

Auth Loop Closes Tight
Every auth flow starts with a challenge and ends with a bound token. A client generates a proof using its secret and a nonce, binding the proof to its identifier, redirect URI, and expiry, then sends it to the server, which verifies the binding in constant time and issues a token encrypted with AES-GCM, attaching a client binding tag so only the holder can validate it.
// Client generates challenge, server verifies and issues bound token
const { requestProof, requestNonce, expiresAt } = await Auth.Client.generate({
clientSecret,
clientId: 'my-app',
redirectUri: 'https://myapp.example/callback',
expireInMs: 300_000
})
const proofOk = await Auth.Server.verifyChallenge({
clientSecret,
clientId: 'my-app',
redirectUri,
expiresAt,
requestProof
})
const token = await Auth.Server.generateToken({
serverSecret,
payload: { subject: 'user-1', clientId: 'my-app', expiresAt, issuedAt },
clientId: 'my-app',
clientSecret,
issuer: 'https://auth.example',
version: '2026'
})
// Only the client secret holder can verify this token
A state manager ties each request to a nonce, binding tag, and expiry, so the server verifies state integrity before proceeding and the application claims it atomically to prevent replay, closing the race that compromised accounts in post-mortems.
Tokens stay opaque to the client and encrypted to the server, so interception reveals nothing and replay fails without the secret, because the payload is sealed with AES-GCM using a server-derived key, and a client binding tag through HMAC ensures only the holder can validate, while expiry inside the binding closes the replay window across SSO and confidential clients.

Binding Holds Firm
| Feature | Delivered |
|---|---|
| Challenge | Proof of possession with nonce, binding, and expiry |
| State | CSRF protection tied to client binding, one-time use |
| Token | AES-GCM encrypted with client binding tag via HMAC |
| Verify | Constant-time comparison for all binding checks |
| Use Cases | SSO, internal company auth, confidential clients |
| Replay | Closed by expiry in binding and atomic state claim |
Replay Lost Its Window
- Binding beat bearer for every confidential use case, as a token tied to a client secret survives interception because the attacker cannot use it without the secret while a bearer token works for anyone who holds it.
- Opaque beat transparent for payloads, as encrypted tokens reveal nothing while JWT exposes claims to any interceptor.
- Constant-time comparison prevented timing attacks on binding verification.
- Expiry inside the MAC input closed replay windows without server-side state.
Sealed Against the Thief
What began as a way to close replay windows became a library binding tokens to client secrets across SSO, internal, and confidential workflows. Challenge, state, and token share one binding, keeping the loop from proof to verification tight and safe.
One secret, one binding, zero replay. The token works for the holder and no one else, even if intercepted in transit or stolen.