1. Introduction
This section is not normative.
Note this is a very early drafting for writing collaboration only
The web is built on a stateless protocol, to provide required functionality Web applications store data locally on a user’s computer in order to provide functionality the are very common today. Primarily this is used for logged in user sessions that can last for a long time.
In general user agents do not have a secure way of storing files supporting these activities across commonly used operating systems, and actions may have serious consequences, for example transferring money from a bank account.
This document defines a new API, Device Bound Sessions Credentials (DBSC), that enables the server to verify that a session cannot be exported from a device by using commonly available TPMs, or similar APIs, that are designed for this purpose.
The goal is to provide users with a safe and secure experience, while offering the use cases users are already used to. At the same time we want to ensure that the users privacy is respected with no new privacy identifiers being leaked by this protocol.
1.1. Examples
Device Bound Session Credentials are designed to make users more secure in different situations. Some of the use cases of DBSC are:1.1.1. Signed in session
1.1.2. Device integrity
1.1.3. Device reputation
payment.example
could create a session bound
to when users visit commercial site shopping.example
. It could track the
reliability of the device over time to decide how likely a transaction is
legitimate. 2. Security Considerations
The goal of DBSC is to reduce session theft by offering an alternative to long-lived cookie bearer tokens, that allows session authentication that is bound to the user’s device. This makes the internet safer for users in that it is less likely their identity is abused, as malware is forced to act locally and thus becomes easier to detect and mitigate. At the same time the goal is to disrupt the cookie theft ecosystem and force it to adapt to new protections long term.As long as the session is valid a host can know with cryptographic certainty that it is on the same device as the session was originally bound to if the session was registered to a secure device.
2.1. Non-goals
DBSC will not prevent temporary access to the browser session while the attacker is resident on the user’s device. The private key should be stored as safe as modern operating systems allow, preventing exfiltration of the session private key, but the signing capability will still be available for any program running as the user on the user’s device.DBSC will also not prevent an attack if the attacker is replacing or injecting into the user agent at the time of session registration as the attacker can bind the session either to keys that are not TPM bound, or to a TPM that the attacker controls permanently.
DBSC is not designed to give hosts any sort of guarantee about the device a session is registered to, or the state of this device.
3. Privacy Considerations
The goal of the DBSC protocol is to introduce no additional surface for user tracking: implementing this API (for a browser) or enabling it (for a website) should not entail any significant user privacy tradeoffs.Some of the consideration taken to ensure this:
-
Lifetime of a session/key material: This should provide no additional client data storage (i.e., a pseudo-cookie). As such, we require that browsers MUST clear sessions and keys when clearing other site data (like cookies).
-
Implementing this API should not meaningfully increase the entropy of heuristic device fingerprinting signals. Unless allowed by user policy, DBSC should not leak any stable TPM-based device identifier.
-
As this API MAY allow background "pings" for performance, this must not enable long-term tracking of a user when they have navigated away from the connected site.
-
Each session has a separate new key created, and it should not be possible to detect that different sessions are from the same device unless the user allows this by policy.
3.1. Cookies considerations
Cross-site/cross-origin data leakage: It should be impossible for a site to use this API to circumvent the same origin policy, 3P cookie policies, etc.Due to the complexity of current and changing cookie behavior and the interaction between DBSC and cookies the current solution is that each user agent should use the same policy for DBSC as it uses for cookies. If the DBSC cookie credential would not apply to a network request, based on user settings, applied policies or user agent implementation details, neither would any of the DBSC heuristics. This ensures no new privacy behavior due to implementing DBSC.
3.2. Timing side channel leak
If third party cookies are enabled it is possible for an attacker to leak whether or not a user is authenticated by measuring how long the request takes as the refresh is quite slow, partially due to the latency of TPM operations.This only applies if the site to be leaked about has enabled third party cookies, if an attacker does have third-party cookie access there are often attackes and leaks.
This is not a very reliable leak as the user needs to have a session on the site that is currently out of date and would need to be refreshed. The leak cannot be trivially repeated as the first request will renew the session that would likely not expire again for some time.
It is important websites think about this privacy leak before adopting DBSC, even more so if the plan is to use sessions with third party cookies.
4. Alternatives considered
4.1. WebAuthn and silent mediation
5. Framework
This document uses ABNF grammar to specify syntax, as defined in [RFC5234] and updated in [RFC7405], along with the#rule
extension defined in Section 7 of [RFC9112], and the quoted-string
rule defined in Section 3.2.6 of the same document.
This document depends on the Infra Standard for a number of foundational concepts used in its algorithms and prose [INFRA].
5.1. Sessions by registrable domain
A registrable domain sessions is a ordered map from registrable domain to session by id.5.2. Sessions by id
A session by id is an ordered map from session identifier to device bound sessions for a given registrable domain.5.3. Device bound session
A device bound session is a struct with the following items:- session identifier
-
an string that is a unique identifier of a session on an registrable domain
- refresh url
-
an string that is representing the url to be used to refresh the session
- defer requests
-
an OPTIONAL boolean defining if the browser should defer other requests while refreshing a session
- cached challenge
-
an string that is to be used as the next challenge for this session
- session scope
-
a struct defining which url's' are in scope for this session
- session credential
-
a list of session credential used by the session
5.4. Session scope
The session scope is a struct with the following items:- include site
-
a boolean that indicates if all subdomains of are included by default.
- scope specification
-
a list of scope specification used by the session
5.5. Scope specification
The scope specification is a struct with the following items:- type
-
a string to be either "include" or "exclude", defining if the item defined in this struct should be added or removed from the scope
- path
-
a string that defines the path part of this scope item
5.6. Session credential
The session credential is a struct with the following items:- name
-
a string that defines the name of the credential cookie
- attributes
-
a string that defines the other attributes of the credential cookie
6. Algorithms
6.1. Identify session
Given a url and session identifier (session identifier), this algorithm returns a device bound session or null if no such session exists.
-
Let site be the registrable domain of the url
-
Let domain sessions be registrable domain sessions[site] as a session by id
-
Return domain sessions[session identifier]
6.2. Process challenge
Given a response (response), a registrable domain sessions, this algorithm updates the cached challenge for a device bound session, or immediatly resends the DBSC proof signed with the new challenge if the status is 401.
-
Let header name be "
Sec-Session-Challenge
". -
Let challenge list be the result of executing get a structured field value given header name and "list" from response’s header list.
-
For each challenge entry of challenge list:
-
Parse challenge entry according to parsing structured fields.
-
If the type of challenge entry is not an sf-string, continue.
-
Let challenge be the parsed item.
-
Let session id be null.
-
If params["id"] exists and is a sf-string, Set session id to params["id"].
-
If status is 401, resend this request as is with updated challenge in DBSC proof and continue.
-
If session id is null, continue.
-
Identify session as described in identify a session given response and session id and store as session object.
-
If session object is null, continue.
-
Store challenge in session object to be used next time a DBSC proof is to be sent from this device bound session.
-
6.3. Session refresh
To Refreshing an existing session6.4. Send request
6.5. Create session
To Create a new session, start with parsing the registration structured header defined in `Sec-Session-Registration
`:
-
Let header name be "
Sec-Session-Registration
". -
Let registration list be the result of executing get a structured field value given header name and "list" from response’s header list.
-
For each registration entry, params → registration list:
-
Parse registration entry according to parsing structured fields.
-
If registration entry is not an sf-inner-list, continue.
-
Let algorithm list be an empty list.
-
For each algorithm → registration entry
-
If algorithm represents a crypto algorithm supported in `
Sec-Session-Registration
`, and is supported on this client, add algorithm to algorithm list
-
If algorithm list is empty, continue.
-
If params["path"] does not exist, or is not of type sf-string, continue.
-
Let path be params["path"].
-
Let challenge be null, and Let authorization be null.
-
If params["challenge"] exists and is of type sf-string Set challenge to params["challenge"].
-
If params["authorization"] exists and is a string Set authorization to params["authorization"].
-
Call § 6.4 Send request with algorithm list, path, challenge and authorization parameters.
-
6.6. Closing session
To close a session6.7. Fetch Integration
To fetch Integration7. DBSC Formats
7.1. `Sec-Session-Registration
` HTTP header field
The ` Sec-Session-Registration
` header field can be used in a response by the server to start a new device bound session on the
client.
`Sec-Session-Registration
` is a List Structured Header [RFC8941]. Its ABNF
is:
Sec-Session-Registration = sf-list
Each item in the list must be an inner list, and each item in the inner list MUST be a sf-token representing a supported algorithm (ES256, RS256). Only these two values are currently supported.
The following parameters are defined:
-
A parameter whose key is "path", and whose value is a String (Section 3.3.3 of [RFC8941]), conveying the path to the registration endpoint. This may be relative to the current url, or a full url. Entries without this parameter will be ignored in Create a new session.
-
A parameter whose key is "challenge", and whose value is a String (Section 3.3.3 of [RFC8941]), conveying the challenge to be used in the session registration.
-
A parameter whose key is "authorization", and whose value is a String (Section 3.3.3 of [RFC8941]), this parameter will be copied into the registration JWT.
Sec-Session-Registration
` from
https://example.com/login.html:
HTTP/1.1 200 OK Sec-Session-Registration: (ES256);path="reg";challenge="cv";authorization="ac"
HTTP/1.1 200 OK Sec-Session-Registration: (ES256 RS256);path="reg";challenge="cv"
HTTP/1.1 200 OK Sec-Session-Registration: (ES256);path="reg1";challenge="cv1";authorization="a" Sec-Session-Registration: (RS256);path="reg2";challenge="cv2";authorization="b"
HTTP/1.1 200 OK Sec-Session-Registration: (ES256);path="reg1";challenge="cv1";authorization="a", (RS256);path="reg2";challenge="cv2";authorization="b"
7.2. `Sec-Session-Challenge
` HTTP Header Field
The ` Sec-Session-Challenge
` header field can be used in a response by the server to send a challenge to the client that it expects to
be used in future Sec-Session-Response headers inside the DBSC proof, or to
request a newly signed DBSC proof right away if the
`Sec-Session-Challenge
` is a structured header. Its value must be a string.
Its ABNF is:
SecSessionChallenge = sf-stringThe semantics of the item are defined in § 7.2.1 Sec-Session-Challenge structured header serialization.
The processing steps are defined in § 6.2 Process challenge.
7.2.1. Sec-Session-Challenge structured header serialization
The `Sec-Session-Challenge
` is represented as a Structured Field.[RFC8941]
In this representation, a challenge is represented by a string.
Challenges MAY have a Parameter named "id"
, whose value MUST be a String
representing a session identifier. Any other
parameters SHOULD be ignored.
Note: The server might need to use this header to request the DBSC proof to be signed with a new challenge before a session id has been assigned. In this case the session ID is optional.
Sec-Session-Challenge
` from
https://example.com/login.html:
HTTP/1.1 401 OK Sec-Session-Challenge: "new challenge"
HTTP/1.1 401 OK Sec-Session-Challenge: "new challenge";id="my session"
HTTP/1.1 200 OK Sec-Session-Challenge: "new challenge";id="my session"
HTTP/1.1 200 OK Sec-Session-Challenge: "new challenge";id="my session 1" Sec-Session-Challenge: "another challenge";id="my session 2"
HTTP/1.1 200 OK Sec-Session-Challenge: "c1";id="session 1", "c2";id="session 2"
7.3. Sec-Session-Response
HTTP Header Field
The ` Sec-Session-Response
` header field can be used in the request by the user agent to send a DBSC proof to the server to prove
that the client is still in possesion of the private key of the session key.
`Sec-Session-Response
` is a structured
header. Its value must be a string. It’s ABNF is:
SecSessionChallenge = sf-string
This string MUST only contain the DBSC proof JWT. Any parameters SHOULD be ignored.
POST example.com/refresh Sec-Session-Response: "eyJhbGciOiJFUzI1NiIsInR5cCI6ImRic2Mrand0In0.eyJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tL3JlZyIsImp0aSI6ImN2IiwiaWF0IjoiMTcyNTU3OTA1NSIsImp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IjZfR0Iydm9RMHFyb01oNk9sREZDRlNfU0pyaVFpMVBUdnZCT2hHWjNiSEkiLCJ5IjoiSWVnT0pVTHlFN1N4SF9DZDFLQ0VSN2xXQnZHRkhRLWgweHlqelVqRUlXRSJ9LCJhdXRob3JpemF0aW9uIjoiYWMifQ.6Fb_vVBDmfNghQiBmIGe8o7tBfYPbPCywhQruP0vIhxgmcJmuNTaMHeVn_M8ZnOm1_bzIitbZqCWEn-1Qzmtyw"
7.4. Sec-Session-Id
HTTP Header Field
The ` Sec-Session-Id
` header field can be used in the request by the user agent to request the current session is refreshed,
with the current session identifier as a string argument.
`Sec-Session-Id
` is a structured header.
Its value must be a string. It’s ABNF is:
SecSessionChallenge = sf-string
This string MUST only contain the session identifier. Any paramters SHOULD be ignored.
7.5. DBSC Session Instruction Format
The server sends session instructions during session registration and optionally during session refresh. If the response contains session instructions it MUST be in JSON format.At the root of the JSON object the following keys can exist:
- session identifier
-
a string representing a session identifier. If this session instructions is sent during a refresh request this MUST be the session identifier for the current session. If not these instructions SHOULD be ignored. If this session instructions is sent during a registration it MUST either be a unique iditifier for this registrable domain, or it will overwrite the current device bound session with this identifier for the current registrable domain. This key MUST be present.
- refresh_url
-
a string representing the url used for future refresh requests. This can be a full url, or relative to the current request. This key is OPTIONAL, if not present the registration url will be used for future refresh requests.
- continue
-
a boolean representing if the current session should continue, or be closed on the client. This key is OPTIONAL, and if not present the default value will be true.
- defer_requests
-
a boolean describing the wanted session behavior during a session refresh. If this value is true all requests related to this session will be deferred while the session is refreshed. If instead the value is false every request will instead be sent as normal, but with a `
Sec-Session-Response
` header containing the DBSC proof. This key is OPTIONAL, and if not present a value of true is default.
{ "session_identifier" : "session_id" , "refresh_url" : "/RefreshEndpoint" , "scope" : { // Origin-scoped by default (i.e. https://example.com) // Specifies to include https://*.example.com except excluded subdomains. // This can only be true if the origin’s host is the root eTLD+1. "origin" : "example.com" , "include_site" : true , "continue" : false , "defer_requests" : true , // optional and true by default "scope_specification" : [ { "type" : "include" , "domain" : "trusted.example.com" , "path" : "/only_trusted_path" }, { "type" : "exclude" , "domain" : "untrusted.example.com" , "path" : "/" }, { "type" : "exclude" , "domain" : "*.example.com" , "path" : "/static" } ] }, "credentials" : [{ "type" : "cookie" , // This specifies the exact cookie that this config applies to. Attributes // match the cookie attributes in RFC 6265bis and are parsed similarly to // a normal Set-Cookie line, using the same default values. // These SHOULD be equivalent to the Set-Cookie line accompanying this // response. "name" : "auth_cookie" , "attributes" : "Domain=example.com; Path=/; Secure; SameSite=None" // Attributes Max-Age, Expires and HttpOnly are ignored }] }
7.6. DBSC Proof JWT Syntax
A DBSC proof proof is a JWT that is signed (using JSON Web Signature (JWS)), with a private key chosen by the client. The header of a DBSC proof MUST contain at least the following parameters:- typ
-
a string MUST be "dbsc+jwt"
- alg
-
a string defining the algorithm used to sign this JWT. It MUST be either "RS256" or "ES256" from [IANA.JOSE.ALGS].
The payload of DBSC proof MUST contain at least the following claims:
- aud
-
a string, MUST be the url this JWT was originally sent to. Example: "https://example.com/refresh.html"
- jti
-
a string, a copy of the challenge value sent in the registration header.
- iat
-
a string, this claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a NumericDate value.
- jwk
-
a string defining a JWK as specified in [rfc7517].
In addition the following claims MUST be present if present in `Sec-Session-Registration
`:
- authorization
-
a string, direct copy of the string from `
Sec-Session-Registration
`, if set there. Note that this string is OPTIONAL to include in the header, but if it is present it is MANDATORY for clients to add the claim in the DBSC proof.
// Header { "alg" : "ES256" , "typ" : "dbsc+jwt" } // Payload { "aud" : "https://example.com/reg" , "jti" : "cv" , "iat" : "1725579055" , "jwk" : { "kty" : "EC" , "crv" : "P-256" , "x" : "6_GB2voQ0qroMh6OlDFCFS_SJriQi1PTvvBOhGZ3bHI" , "y" : "IegOJULyE7SxH_Cd1KCER7lWBvGFHQ-h0xyjzUjEIWE" }, "authorization" : "ac" }
Based on this response header from the server:
HTTP/1.1 200 OK Sec-Session-Registration: (ES256);path="reg";challenge="cv";authorization="ac"
recieved on a response from http://example.com/page.html
8. Changes to other specifications
8.1. Changes to the Fetch specification
--> Check if session should be refreshed before sending request-
Alternatively add proof with Sec-Session-Response
8.2. Changes to the HTML specification
--> Clear Site Data: Clear the session if this is received9. IANA Considerations
The permanent message header field registry should be updated with the following registrations: [RFC3864]
9.1. Sec-Session-Challenge
- Header field name
- Sec-Session-Challenge
- Applicable protocol
- http
- Status
- draft
- Author/Change controller
- W3C
- Specification document
- This specification (See § 7.2 `Sec-Session-Challenge` HTTP Header Field)
9.2. Sec-Session-Id
- Header field name
- Sec-Session-Id
- Applicable protocol
- http
- Status
- draft
- Author/Change controller
- W3C
- Specification document
- This specification (See § 7.4 Sec-Session-Id HTTP Header Field)
9.3. Sec-Session-Registration
- Header field name
- Sec-Session-Registration
- Applicable protocol
- http
- Status
- draft
- Author/Change controller
- W3C
- Specification document
- This specification (See § 7.1 `Sec-Session-Registration` HTTP header field)
9.4. Sec-Session-Response
- Header field name
- Sec-Session-Response
- Applicable protocol
- http
- Status
- draft
- Author/Change controller
- W3C
- Specification document
- This specification (See § 7.3 Sec-Session-Response HTTP Header Field)