← Chrome 147 reference · Device Bound Session Credentials
DBSC protocol reference · lifecycle
Protocol lifecycle and server algorithm
A state machine derived from the current Editor’s Draft, with Chromium-specific behavior kept separate. Use it to specify expiry, termination, replay, logout, and recovery instead of guessing from a happy-path diagram.
State model
No DBSC session
├─ signed-key registration (ES256/RS256) + valid response → Registered (signing key)
├─ none registration + valid response → Registered (no signing key; no device-binding guarantee)
└─ registration failure / invalid config / terminal status → No DBSC session
(terminate(null) is a no-op: nothing was created, removed, or replaced)
Registered (key, id, scope, credentials, cached challenge?)
├─ applicable credential present → request continues
├─ applicable credential missing → Refresh pending → Registered / retryable failure
├─ refresh continue:false, invalid replacement config, terminal 4xx → Terminated
│ (terminate(existing id) removes the existing DBSC session)
└─ expiry / Clear-Site-Data / cookie/site-data clear / key loss → No DBSC sessionDecision inputs
For each request, identify sessions by registrable domain, remove expired records, skip a session already deferred on this request, test scope and allowed refresh initiator, then test whether a declared cookie that would apply is missing. This is the draft’s algorithm; it means “cookie absent” is evaluated with normal cookie applicability, not merely a name lookup.
Effects
The browser defers the original request, posts a refresh, and restarts the original network operation after refresh. It excludes the refresh URL from protected scope to prevent loops. Registration instead begins asynchronously with a null session ID and creates a session only after a valid, cookie-settable configuration. It may set an implementation-chosen session expiration timestamp, recommended to align to maximum cookie lifetime.
Terminal versus retryable outcomes
Every terminate call is parameterized by the session ID passed to the request algorithm. For registration that ID is null, so invalid response JSON/config, continue:false, and terminal statuses leave the user agent with no DBSC session: terminate is a no-op and cannot remove or replace one. For refresh the ID names an existing session, so invalid replacement JSON/config, continue:false, or refresh 4xx other than the 403 proof path remove that session. Network errors, 407, 429, redirects, and 5xx return without creating or removing a session; user agents may back off. Chromium’s current source adds retry budgeting/cached signatures for transient errors. Exact limits, delays, and key-store failure behavior are implementation details—servers must remain correct without relying on them.
Scope and initiator boundary
Origin-scoped sessions require same origin; site-scoped sessions require same site. Later scope rules override earlier ones; * and *.example.com have draft-defined host matching. Out-of-scope refresh triggers need a host pattern in allowed_refresh_initiators. The browser applies cookie-like policy so DBSC does not bypass blocked cookie behavior.
Server pseudocode
server_policy_for_login(response):
if authorization is protected:
emit Secure-Session-Registration with ES256 and/or RS256; never offer none
else if intentionally using ordinary authorization:
use a separate ordinary endpoint/policy; do not emit Secure-Session-Registration
registration(response, key_pair):
session_id = null
if response is terminal or instructions are invalid or continue is false:
terminate(session_id) # no-op: null identifies no DBSC session
return no_dbsc_session
if no declared credential can be set:
terminate(session_id) # still a no-op; do not create/replace a session
return no_dbsc_session
store_new_dbsc_session(response.instructions, key_pair)
# The draft permits key_pair = null for a none offer. It does not automatically
# redirect that DBSC registration to an ordinary path; it has no signing-key guarantee.
refresh(request):
id = parse_sf_string(request.header["Sec-Secure-Session-Id"])
s = dbsc_sessions.find(id) or generic_failure()
if s.revoked or s.expired: return terminal_4xx() # terminate(id) removes existing session
proof = request.header["Secure-Session-Response"]
if not proof:
nonce = issue_random_nonce(id, short_ttl=True)
return 403, {"Secure-Session-Challenge": sf_string(nonce, id=id)}
jwt = parse_and_verify_dbsc_jws(proof, key=s.public_jwk, allowed_algs=s.algs)
if jwt.typ != "dbsc+jwt" or jwt.has_jwk or not consume_recent_nonce(id, jwt.jti):
return 403, challenge_response(id)
rotate_short_lived_cookie_atomically(s)
return 200, set_cookie_headers()
# For refresh, invalid instructions or continue:false likewise call terminate(id),
# which removes s. This differs from null-ID registration above.Logout and recovery examples
# Registration failure: session_id is null, so the terminate step is a no-op.
HTTP/1.1 400 Bad Request
# No DBSC session was created, removed, or replaced.
# Server-directed DBSC termination in a refresh response: session_id exists.
HTTP/1.1 200 OK
Content-Type: application/json
{"continue":false}
# The existing client DBSC session is removed.
# Application logout should also revoke server DBSC state and expire protected cookies.
Set-Cookie: sid=; Path=/; Max-Age=0; Secure; HttpOnly; SameSite=Lax
# Key/site-data loss: no proof can be recovered. Send the user through normal login
# and create a new server session/key binding; do not repair by accepting old cookies.Compatibility
| Item | Requirement / behavior |
|---|---|
| Chrome | DBSC availability, not page-layout support: ChromeStatus lists DBSC as in development, with Chrome desktop milestone 145. Its Android milestone is null/unknown; availability remains controlled by implementation and feature configuration. |
| Firefox | No signal; the Mozilla standards-position issue is the public evidence, not an implementation commitment. |
| Safari | No signal; the WebKit standards-position issue is the public evidence, not an implementation commitment. |
| Other engines | Unknown. The W3C document is an Editor’s Draft, not a final interoperable Recommendation. |
Security and privacy
Record logout/revocation server-side, rotate short-lived cookie values, and make nonce consumption race-safe. Clear-site-data and user cookie clearing must clear DBSC keys/sessions in conforming user agents, so application recovery cannot depend on client-held binding state. DBSC limits exported-cookie replay, not active on-device misuse. A none path has no signing key or JWK possession proof, so it has no device-binding security guarantee: do not offer it for protected authorization and keep any intentional ordinary flow separate.
Primary sources: algorithms · URL-in-scope algorithm · refresh-initiator algorithm · missing-credential algorithm · session-request algorithm · security · chrome · chromium · retry · json. External sources open in a new tab.