1. Introduction
For now, see the explainer.
This spec is an early-stage draft. Missing details and remaining TODOs are called out with Issue: blocks.
2. Security considerations
3. Privacy considerations
4. Framework
4.1. Observer store
The user agent maintains an observer store. It is a set of weak references to DeviceBoundSessionsObserver objects. The store is initially empty.
When an observer has been reclaimed by garbage collection, it must be removed from the store.
4.2. Registration buffer and store
The user agent maintains a registration attempts store. It is a map from storage key to registration buffer. The store is initially empty.
Should we make this a formal storage endpoint?
A registration buffer is a list of DeviceBoundSessionRegistrationReports. Each buffer is initially empty.
User agents should put a reasonable limit on the number of attempts stored in each buffer and their time-to-live.
5. The DeviceBoundSessionsObserver interface
This interface can be used to observe device bound sessions and registration attempts.
[Exposed =Window ,SecureContext ]interface {DeviceBoundSessionsObserver constructor (DeviceBoundSessionsObserverCallback ,callback optional DeviceBoundSessionsObserverOptions = {} );options undefined observe ();undefined disconnect ();sequence <DeviceBoundSessionsReport >takeRecords (); };callback =DeviceBoundSessionsObserverCallback undefined (sequence <DeviceBoundSessionsReport >,reports DeviceBoundSessionsObserver );observer
A DeviceBoundSessionsObserver has an associated callback (a DeviceBoundSessionsObserverCallback) and an associated options (a DeviceBoundSessionsObserverOptions).
DeviceBoundSessionsObserver(callback, options) constructor is called:
DeviceBoundSessionsObserver observer of a list of DeviceBoundSessionsReports reports:
-
Queue a global task on the networking task source given observer’s relevant global object to run these steps:
-
If observer store does not contain observer, then return.
-
Invoke observer’s callback with « reports, observer » and "
report", and callback this value observer.
-
Callers of this algorithm must verify that observer is allowed to know about reports under the user agent’s current policies, notably storage partitioning.
5.1. DeviceBoundSessionsObserverOptions dictionary
dictionary {DeviceBoundSessionsObserverOptions AbortSignal signal ; };
signal, of type AbortSignal-
The
abortevent stops the observer from receiving further reports.
5.2. observe() method
observe() is called:
-
If observer store contains this, then return.
-
Append a weak reference to this to observer store.
-
If signal exists, then add the following abort steps to signal:
-
Call this’s
disconnect().
-
-
Let reports be the result of collecting past reports for this.
DeviceBoundSessionsObserver observer:
-
Let environment be observer’s relevant settings object.
-
Let observer key be the result of running obtain a storage key for non-storage purposes given environment.
-
Let reports be a new list.
-
If registration attempts store[observer key] exists, then set reports to a clone of registration attempts store[observer key].
-
For each sessions by id of session store’s values:
-
For each session of sessions by id’s values:
-
If determine session visibility given environment and session does not return "visible", then continue.
-
Let session report be the result of creating an established session report given session.
-
If reports contains a
DeviceBoundSessionRegistrationReportregistration such that registration[session] exists and equals session report, then continue. -
Append session report to reports.
-
-
-
Return reports.
5.3. disconnect() method
disconnect() is called:
-
Remove this from observer store.
User agents may want to also clean up previously set up abort steps and remove garbage-collected references from the store.
5.4. takeRecords() method
takeRecords() is called:
-
Let reports be the result of collecting past reports for this.
-
Let observer key be the result of running obtain a storage key for non-storage purposes given this’s relevant settings object.
-
Remove registration attempts store[observer key].
-
Return reports.
5.5. Report types
enum {DeviceBoundSessionsReportKind ,"session" };"registration" dictionary DeviceBoundEstablishedSessionReport {required DeviceBoundSessionsReportKind type ;required DOMString sessionOrigin ;required DOMString sessionId ;required DOMString refreshUrl ;required DOMHighResTimeStamp creationTime ; };dictionary DeviceBoundSessionRegistrationReport {required DeviceBoundSessionsReportKind type ;required DOMString registrationUrl ;required boolean success ;required DOMHighResTimeStamp endTime ;DeviceBoundEstablishedSessionReport session ;DOMString reason ;unsigned short code ;DOMString providerUrl ;DOMString providerSessionId ; };typedef (DeviceBoundSessionRegistrationReport or DeviceBoundEstablishedSessionReport );DeviceBoundSessionsReport
5.5.1. Registration attempt report
A DeviceBoundSessionRegistrationReport represents the outcome of the multi-stage process started by process a session registration. See § 7.1 Changes to the DBSC specification.
type, of type DeviceBoundSessionsReportKind-
Must be
"registration". registrationUrl, of type DOMString-
The serialized registration endpoint URL to which the registration request was sent.
success, of type boolean-
True if the registration attempt resulted in an established device bound session; false otherwise.
endTime, of type DOMHighResTimeStamp-
The duration from the Unix epoch to the coarsened wall time when the registration process concluded.
Using the wall clock meansendTimeis not monotonic across registration reports. For example, system clock changes could modify the apparent order of reports.An alternative would be to compute these timestamps using the estimated monotonic time of the Unix epoch here.
This would in turn have the drawback of inconsistent timestamps between a successful registration report’s
endTimeand itssession[creationTime]. session, of type DeviceBoundEstablishedSessionReport-
The
DeviceBoundEstablishedSessionReportfor the newly created device bound session, present whensuccessis true. reason, of type DOMString-
A human-readable or categorical description of why the registration attempt failed, present when
successis false.Replace the free-form string with a WebIDL enum of standardized failure reasons.
code, of type unsigned short-
The HTTP status code received from the registration endpoint, present when the attempt failed due to an HTTP response status.
providerUrl, of type DOMString-
For a federated session registration attempt, the serialized provider URL specified in the `
Secure-Session-Registration` header. providerSessionId, of type DOMString-
For a federated session registration attempt, the provider session identifier specified in the `
Secure-Session-Registration` header.
-
Let report be a
DeviceBoundSessionRegistrationReportwith:typeregistrationUrl-
The URL serializer of registration URL.
success-
success.
endTime-
The duration from the Unix epoch to the current coarsened wall time.
-
If resulting session was given, then set report[
session] to the result of creating an established session report given resulting session. -
If reason was given, then set report[
reason] to reason. -
If code was given, then set report[
code] to code. -
If provider URL was given, then set report[
providerUrl] to the URL serializer of provider URL. -
If provider session id was given, then set report[
providerSessionId] to provider session id. -
Report report with resulting session (if given).
DeviceBoundSessionRegistrationReport report given an optional device bound session resulting session:
-
Let registration key be the storage key of report.
-
For each observer of observer store:
-
Let environment be the relevant settings object for observer.
-
Let observer key be the result of running obtain a storage key for non-storage purposes given environment.
-
If observer key equals registration key, then inform observer of « report », and continue.
-
If resulting session was not given, then continue.
-
If determine session visibility given environment and resulting session does not return "visible", then continue.
-
-
If registration attempts store[registration key] does not exist, then set registration attempts store[registration key] to a new registration buffer.
-
Append report to registration attempts store[registration key].
DeviceBoundSessionRegistrationReport registration is defined as:
-
Let url be the result of running the URL parser on registration[
registrationUrl]. -
Let origin be url’s origin.
-
Let site be obtain a site given origin.
-
Return a storage key whose origin is origin and top-level site is site.
5.5.2. Established session report
A DeviceBoundEstablishedSessionReport represents a device bound session. Note that DeviceBoundSessionRegistrationReport also contains a session: if an observer is informed of an established session via a (buffered) DeviceBoundSessionRegistrationReport, it must not be informed of the same session a second time via a DeviceBoundEstablishedSessionReport.
type, of type DeviceBoundSessionsReportKind-
Must be
"session". sessionOrigin, of type DOMString-
The serialized origin of the device bound session’s session scope.
sessionId, of type DOMStringrefreshUrl, of type DOMString-
The serialized refresh URL of the device bound session.
creationTime, of type DOMHighResTimeStamp-
The duration from the Unix epoch to the device bound session’s creation time.
-
Let report be a new
DeviceBoundEstablishedSessionReportdictionary with:typesessionOrigin-
The serialization of an origin given session’s session scope’s origin.
sessionId-
session’s session identifier.
refreshUrl-
The URL serializer of session’s refresh URL.
creationTime-
The duration from the Unix epoch to session’s creation time.
-
Return report.
DeviceBoundEstablishedSessionReport a equals another DeviceBoundEstablishedSessionReport b if all of the following are true:
-
a[
sessionOrigin] is b[sessionOrigin]. -
a[
creationTime] is b[creationTime].Note: In [dbsc-1], a device bound session is keyed in the session store by its site and session identifier. Comparing
creationTimealso distinguishes a session from a later registration that overwrote the same session identifier.
6. Session reports visibility
-
Let url be environment’s creation URL.
-
If url is not session’s refresh URL:
-
If the result of running determine if a URL is in scope with url and session is false, then return "hidden".
-
-
If environment has storage access, then return "visible".
-
Return "hidden".
Consider making this a WPT instead.
Given the following (incomplete) session definition:
{ "session_identifier" : "session_id" , "refresh_url" : "/refresh" , "scope" : { "origin" : "https://example.com" , "include_site" : true , "scope_specification" : [ { "type" : "exclude" , "domain" : "sites.example.com" , "path" : "/" }, { "type" : "exclude" , "domain" : "*.example.com" , "path" : "/static" } ] }, "credentials" : [{ "type" : "cookie" , "name" : "auth_cookie" , "attributes" : "Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Strict" }] }
The following table illustrates whether session_id is visible to various execution environments:
| Creation URL | Storage access | Visible? | Reason |
|---|---|---|---|
https://example.com/account
| Top-level window | true
| In scope of session_id, has storage access.
|
https://sub.example.com/app
| Top-level window | true
| Also in scope of session_id, by its include_site.
|
https://example.com/refresh
| Top-level window | true
| Refresh URL bypasses scope check. |
https://example.com/refresh
| Embedded without storage access | false
| No access to 1P example.com storage.
|
https://sites.example.com/a
| N/A | false
| URL matches the sites.example.com/ exclusion rule.
|
https://app.example.com/static/index.html
| N/A | false
| URL matches the *.example.com/static exclusion rule.
|
7. Changes to other specifications
7.1. Changes to the DBSC specification
Avoid deep monkey-patching here: open a PR against [dbsc-1], then remove this section.
In device bound session, add the following item:
- creation time
-
The current coarsened wall time at which this session was created.
In process a session registration:
-
Modify the step that checks if key pair is "
failure" to record a registration attempt on failure. -
Pass provider URL and provider session id as additional optional inputs to send a request.
Note: The next two changes mention "if session id is null" to send a report only when send a request creates a new session. When that algorithm runs for a refresh, session id is known.
In send a request:
-
Accept an optional provider URL and an optional provider session id to adequately construct a federation attempt report when applicable.
-
If session id is null, then:
-
Whenever returning early due to a network error or an invalid HTTP status code, record a registration attempt.
-
Pass provider URL and provider session id to create a session.
-
In create a session:
-
Accept an optional provider URL and an optional provider session id.
-
After setting the expiration timestamp, also set creation time.
-
Whenever invoking terminate the session and returning (cf. the last "credential" loop), if session id is null, then record a registration attempt with an appropriate failure reason, code, etc.
-
When adding a session to the session store, if session id is null, then record a registration attempt (successful, passing session).