Skip to content

SecH0us3/dbsc-demo

Repository files navigation

Device Bound Session Credentials (DBSC) Demo

This project demonstrates an implementation of the Device Bound Session Credentials (DBSC) protocol using TypeScript + Cloudflare Workers.

Quick Start

Local Development

  1. Start the secure development server:
    npm install
    npx wrangler dev --local-protocol https --port 8787
  2. Open https://localhost:8787 in Chrome.

⚠️ Important: Since we use a self-signed certificate for local HTTPS, Chrome will show a "Your connection is not private" warning. Click Advanced and then Proceed to localhost (unsafe). DBSC requires HTTPS to function correctly.

Deployment

npm run deploy

What is DBSC?

DBSC (Device Bound Session Credentials) is a technology that transforms a session from "simple cookie presentation" into a process requiring proof of possession of a cryptographic secret that cannot be stolen.

How it Works (Sequence Diagram)

sequenceDiagram
    participant Browser
    participant TPM/SecureEnclave
    participant Server

    Note over Browser,Server: 1. Registration (Login & Binding)
    Browser->>Server: Login (User/Pass)
    Server-->>Browser: 200 OK + auth_cookie (Long-lived) + Secure-Session-Registration header
    Browser->>TPM/SecureEnclave: Generate P-256 Key Pair
    TPM/SecureEnclave-->>Browser: Public Key
    Browser->>Server: POST /StartSession (Secure-Session-Response: dbsc+jwt with JWK)
    Server-->>Browser: 200 OK + sl_auth_cookie (Short-lived, 30s) + dbsc_state (Signed PK)

    Note over Browser,Server: 2. Refresh (Challenge-Response)
    Browser->>Server: POST /RefreshSession (no proof)
    Server-->>Browser: 403 + Secure-Session-Challenge header
    Browser->>TPM/SecureEnclave: Sign Challenge
    TPM/SecureEnclave-->>Browser: Signature
    Browser->>Server: POST /RefreshSession + Secure-Session-Response (dbsc+jwt proof)
    Server-->>Browser: 200 OK + New sl_auth_cookie
Loading

Core Principles

  1. Secret key never leaves the "vault": The private key is generated and stored in a hardware chip (TPM, Secure Enclave). It cannot be copied even if the device is infected with malware.
  2. Short-lived cookies: DBSC uses cookies with a very short lifespan (e.g., 30 seconds or 5 minutes). If an attacker steals such a cookie, it will expire before they can reasonably use it.
  3. Magic of Renewal (Challenge-Response): To obtain a new cookie, the browser must sign a random "challenge" from the server using its private key. A hacker cannot replicate this without access to the hardware key. Importantly, Chrome handles this automatically at the network level. If the browser realizes the sl_auth_cookie is expired (or receives a 403 response indicating it needs a refresh), Chrome pauses the request, performs the challenge-response cycle in the background to get a new cookie, and then automatically resumes the actual request.
  4. Origin Binding: The website's domain is always "baked into" the signature. This protects against Relay attacks (where a hacker tries to use your key to log in to another site).

Invisible to the Frontend

A key feature of native DBSC is that the background refresh requests are completely invisible to the client-side JavaScript.

As shown in the screenshot below, the browser's DevTools Network tab (bottom left) only shows the regular frontend requests (like /api/status). However, the server logs (right) clearly show the POST /RefreshSession requests happening in the background.

DevTools vs Server Logs

This proves that:

  1. The frontend application is completely unaware of the refresh cycle; it's handled entirely by the browser's internal network stack.
  2. The responsibility for session security is shifted away from the application code (which can be vulnerable to XSS) and directly into the browser and the OS's hardware security module.

Graceful Degradation: Two Levels of Trust

A key architectural security concept in DBSC is Graceful Degradation (or sessions with varying levels of trust).

In this implementation, there are two distinct cookies:

  1. auth_cookie (Long-lived, e.g., 30 days): Proves that at some point, the user successfully authenticated.
    • Grants: Read-only actions (viewing public articles, showing the user's name in the header, browsing items).
  2. sl_auth_cookie (Short-lived DBSC cookie, e.g., 30 seconds): Proves that the user is currently at the device that performed the original authentication, backed by a cryptographic hardware key.
    • Grants: High-security actions (transferring money, changing passwords, viewing sensitive data).

Why not just log the user out entirely when sl_auth_cookie expires? If the short-lived cookie expires (e.g., due to a brief loss of internet connectivity, or the laptop going to sleep), the user would be abruptly logged out and forced to enter their password again. This creates a terrible User Experience (UX). By keeping the user conceptually in the system, we shift to a state where the user is authenticated, but not authorized for high-privilege actions (dbscActive: false). The application remains uninterrupted for normal browsing, while strictly enforcing security only when critical actions are requested.

Demonstration: The Hacker Scenario

If an attacker steals a user's cookies (e.g., via malware or XSS), their window of opportunity is minuscule.

  1. The Theft: The attacker steals auth_cookie, dbsc_state, and sl_auth_cookie.
  2. The brief window: For up to 30 seconds, the attacker can impersonate the user fully (while sl_auth_cookie is alive).
  3. The Block: Once the 30 seconds elapse, sl_auth_cookie expires. The attacker's high-privilege access is revoked.
  4. The Failed Refresh: The attacker intercepts the 403 response and the Secure-Session-Challenge header, but fails to generate the signed Secure-Session-Response, because the necessary private key is locked inside the victim's TPM/Secure Enclave. The attacker is permanently locked out of sensitive actions.

You can try this yourself using the hacker-demo.sh script included in this repository!


Security

  • Secret from environment: HMAC signing key is loaded from SECRET_KEY env variable (Cloudflare Secret). Hardcoded fallback is used only in local dev.
  • Algorithm whitelist: Only ES256 and RS256 are accepted in DBSC JWTs. Prevents algorithm substitution attacks (alg: none, HS256 confusion).
  • Dynamic Secure flag: Cookies are set with Secure flag automatically when served over HTTPS.
  • One-time challenges: Registration and refresh challenges are deleted after use to prevent replay attacks.
  • HttpOnly cookies: All session cookies are HttpOnly — not accessible to JavaScript.
  • SameSite=Lax: Prevents CSRF on POST endpoints.

Production Checklist

  • Set SECRET_KEY via wrangler secret put SECRET_KEY
  • Deploy behind HTTPS (Cloudflare provides this automatically)

Demonstration

Full Cycle: Login -> Register -> Refresh -> Logout

DBSC Flow Video

About

Device Bound Session Credentials (DBSC) Demo

Resources

Stars

Watchers

Forks

Contributors