1. 简介
本节为非规范性内容。
许多用户代理会阻止内容访问 Cookie 中存储的非同站点数据。 这可能会破坏依赖访问非同站点 Cookie 的嵌入内容。
requestStorageAccessFor API 使开发者能够为 iframe、
脚本或图像等嵌入资源请求访问非同站点 Cookie。
它通过规定 requestStorageAccessFor(requestedOrigin)
来实现此目的,
该方法允许可遍历可导航对象代表另一个源请求访问未分区 Cookie。
2. 基础设施
本规范依赖于 Infra 标准。[INFRA]
3. requestStorageAccessFor API
本规范定义了一个方法,可用于代表另一个源请求访问未分区数据(requestStorageAccessFor(requestedOrigin))。
Alex 访问 https://social.example/。该页面设置了一个 Cookie。此 Cookie 是在
第一方站点上下文中设置的。
之后,Alex 访问 https://video.example/,其中包含一个
img,
它会加载 https://social.example/profile-image。在这种情况下,
social.example 的 Document
doc 位于第三方上下文中,而先前设置的 Cookie 是否可从
doc.cookie
中看到,取决于用户代理的存储访问策略。
https://video.example/ 上的脚本可以通过调用
doc.requestStorageAccessFor(requestedOrigin)
并将 USVString
requestedOrigin 设为 https://social.example,代表
https://social.example 请求访问权限。
未分区数据 是在某个站点加载于 第一方站点上下文中时可用的客户端存储。
如果一个 Document
是某个可遍历可导航对象的活动文档,则它位于第一方站点上下文中。否则,如果它是一个活动文档,并且其相关设置对象的源和顶级源彼此同站点,则它也位于第一方站点上下文中。
如果一个 Document
不位于第一方站点上下文中,则它位于第三方上下文中。
3.1. 对 Document
的更改
partial interface Document {Promise <undefined >requestStorageAccessFor (USVString ); };requestedOrigin
Document
doc 上以 USVString
requestedOrigin 调用时,requestStorageAccessFor(requestedOrigin)
方法必须运行以下步骤:
-
令 p 为一个新的 promise。
-
如果 doc 不是完全活动的,则使用一个“
InvalidStateError”DOMException拒绝 p, 并返回 p。 -
如果 doc 的节点可导航对象不是可遍历可导航对象,则使用一个“
NotAllowedError”DOMException拒绝 p, 并返回 p。 -
如果 doc 的源是一个不透明源,则使用一个“
NotAllowedError”DOMException拒绝 p, 并返回 p。 -
如果 doc 的相关全局对象不是安全上下文,则使用一个“
NotAllowedError”DOMException拒绝 p, 并返回 p。 -
令 parsedURL 为对 requestedOrigin 运行 URL 解析器所得的结果。
-
令 origin 为 parsedURL 的源。
-
如果 origin 是一个不透明源,则使用一个“
NotAllowedError”DOMException拒绝 p, 并返回 p。 -
令 descriptor 为一个新创建的
TopLevelStorageAccessPermissionDescriptor, 其name设置为“top-level-storage-access”, 并且其requestedOrigin设置为 origin。 -
如果 doc 的
Window对象具有瞬态激活,则令 has activation 为 true; 否则为 false。 -
并行运行以下步骤:
-
令 settings 为 doc 的相关设置对象。
-
令 global 为 doc 的相关全局对象。
-
令 existing state 为 descriptor 使用 settings 时的权限状态。
-
如果 existing state 为已授予:
-
如果 existing state 为已拒绝:
-
在给定 global 的权限任务源上排入一个全局任务,以使用一个“
NotAllowedError”DOMException拒绝 p。 -
返回。
-
如果 has activation 为 false:
-
在给定 global 的权限任务源上排入一个全局任务,以使用一个“
NotAllowedError”DOMException拒绝 p。 -
返回。
-
-
令 permissionState 为使用 descriptor 请求使用“
top-level-storage-access” 权限的结果。注:请注意,在请求权限并决定是否显示提示时, 用户代理会应用由实现定义的行为来塑造最终用户体验。特别是对于
top-level-storage-access,已知用户代理会应用自定义规则, 在不显示提示的情况下授予或拒绝权限。 -
如果 permissionState 为已授予:
-
在给定 global 的权限任务源上排入一个全局任务,以使用一个“
NotAllowedError”DOMException拒绝 p。
-
-
返回 p。
不应直接使用权限任务 源。[privacycg/requestStorageAccessFor 问题 #15]
3.2. 用户代理顶级存储访问策略
-
令 descriptor 为一个新创建的
TopLevelStorageAccessPermissionDescriptor, 其name设置为“top-level-storage-access”, 并且其requestedOrigin设置为 embedded origin。 -
令 existing state 为 descriptor 使用 settings 时的权限状态。
-
如果 existing state 为已授予, 则返回 true。
-
返回 false。
4. 权限集成
requestStorageAccessFor API 定义了一个由名称“top-level-storage-access”标识的强大功能。它定义了以下与权限相关的算法:
PermissionDescriptor-
“
top-level-storage-access”强大功能按如下方式定义一个PermissionDescriptor:dictionary :TopLevelStorageAccessPermissionDescriptor PermissionDescriptor {USVString = ""; };requestedOrigin - 权限查询算法
-
给定一个
PermissionDescriptorpermissionDesc 和一个PermissionStatusstatus,要查询“top-level-storage-access” 权限,运行以下步骤: - 权限键类型
-
“
top-level-storage-access” 功能的权限键的类型为站点。注:
requestedOrigin字段确保权限存储条目使用双重键。 - 权限键生成算法
-
给定一个源 origin 和一个源 embedded origin,要为“
top-level-storage-access” 功能生成一个新的权限键,运行以下步骤:-
如果 embedded origin 与 origin 非同站点,则返回 null。
-
返回从 origin 获取站点所得的结果。
注:检查 embedded origin 是否与 origin 同站点,旨在禁止来自跨站点框架的权限查询。 这依赖于
top-level-storage-access权限请求仅允许在顶级浏览上下文中发起这一不变量。因此, 此检查仅与query(permissionDesc)有关。
-
- 权限键比较算法
-
要比较“
top-level-storage-access” 功能的权限键 key1 和 key2, 运行以下步骤:-
如果 key1 为 null 或 key2 为 null,则返回 false。
-
返回 key1 是否与 key2 同站点。
-
5. Fetch 集成
requestStorageAccessFor(requestedOrigin)
仅直接影响从顶级文档向所请求源发出的子资源请求中的 Cookie 行为。
-
令 has top-level access 为对 request 运行确定请求是否具有 顶级存储访问权限所得的结果。
-
如果 has top-level access 为 false,则返回 false。
-
如果 request 是一个子资源请求,则令 is subresource 为 true; 否则为 false。
-
如果 request 的模式为“cors”,并且 request 的凭据模式为“include”,则令 allowed subresource mode 为 true;否则为 false。
-
如果 is subresource 为 true 且 allowed subresource mode 为 false, 则返回 false。
-
返回 true。
6. 存储访问 API 集成
注:即使成功调用 requestStorageAccessFor(requestedOrigin),
框架仍必须显式调用 requestStorageAccess()
才能访问 Cookie。
此修改允许 requestStorageAccessFor(requestedOrigin)
以类似于先前成功授予 requestStorageAccess()
权限的方式,允许兑现 requestStorageAccess()
调用。
requestStorageAccess(),
以在步骤 13.4 之前(即检查瞬态激活之前)插入以下步骤:
-
令 settings 为 doc 的相关设置对象。
-
令 origin 为 settings 的源。
-
令 descriptor 为一个新创建的
TopLevelStorageAccessPermissionDescriptor, 其name设置为“top-level-storage-access”, 并且其requestedOrigin设置为 origin。 -
如果 descriptor 的权限状态为已授予, 则在给定 global 的权限任务源上排入一个全局任务,以兑现 p,然后返回。
-
如果 descriptor 的权限状态为已拒绝, 则在给定 global 的权限任务源上排入一个全局任务,以使用一个“
NotAllowedError”DOMException拒绝 p,然后返回。
7. 隐私考量
与[STORAGE-ACCESS]一样,requestStorageAccessFor(requestedOrigin)
旨在支持移除跨站点 Cookie。它使开发者能够在附加约束下重新获得跨站点 Cookie。
注:存储访问 API § 6 隐私考量中的许多相同考量也适用。本节主要介绍不同之处。
requestStorageAccess()
要求与嵌入文档进行交互。通过仅要求与顶级文档交互,
requestStorageAccessFor(requestedOrigin)
降低了触发潜在提示的门槛,尽管嵌入文档也可能非常醒目(或使用其他
技术来获得用户交互)。
由实现定义的接受和拒绝步骤
旨在允许用户代理根据其认为合适的逻辑拒绝滥用请求。
所使用的提示必须谨慎指明请求的方向,使用户能够
理解是谁在请求访问权限。
与 requestStorageAccess()
一样,在 requestStorageAccessFor(requestedOrigin)
中也存在用户同意与提示疲劳之间的相同矛盾;
与存储访问 API 非常相似,由实现定义的接受和拒绝步骤
旨在使对此问题持不同立场的实现者能够按其认为合适的方式作出折中。
另一个不同之处是,权限查询可能会因上下文而更加敏感。请注意, 框架必须无法请求以下任一状态:
-
它在作为顶级文档时,是否曾被授予某个源的“
top-level-storage-access” 权限。 -
任意其他源是否在当前顶级站点上被授予 “
top-level-storage-access” 权限。
在前一种情况下,这会允许将虚假域名(或其组合)用作标识符;在 后一种情况下,它会暴露不相关源下的状态。
8. 安全考量
即使与移除跨站点 Cookie 之后的情况相比,requestStorageAccessFor(requestedOrigin)
也不得降低 Web 平台的安全属性,这一点非常重要。
移除第三方 Cookie 可能带来
安全优势,尤其是在缓解依赖已认证请求的攻击方面,例如 CSRF。
我们不希望 requestStorageAccessFor(requestedOrigin)
成为此类攻击可利用的立足点。
注:存储访问 API § 7
安全考量中的属性适用于本提案的大部分内容。具体而言,只有在成功调用 requestStorageAccess()
后,才会授予框架级访问权限。
对于框架访问,requestStorageAccessFor(requestedOrigin)
仅简化了激活和提示要求。
requestStorageAccessFor(requestedOrigin)
确实扩大了两个方面的关注范围:由顶级文档发出的子资源请求,以及
潜在的通知滥用。
8.1. 子资源请求
该 API 提出的具体安全控制措施包括:
-
子资源请求中包含的任何 Cookie 都必须显式标记为
SameSite=None,以表明有意在第三方上下文中使用。 -
要包含任何
SameSite=NoneCookie,请求的模式必须为“cors”;除非被嵌入方通过发送适当的 `access-control-allow-credentials` 标头选择加入,否则将阻止读取响应。发送 `origin` 标头可确保被嵌入方知晓嵌入方的身份。
此外,只有由顶级文档发起的请求才有资格包含
SameSite=None Cookie。这可确保其他嵌入框架不会获得提升后的
权限。
8.2. 通知滥用
与[STORAGE-ACCESS]不同,仅要求与顶级 文档交互,而非嵌入文档。这确实增加了显示提示的可能性。
与存储访问 API 一样,拒绝时会消费用户激活,从而防止重复请求。
由实现定义的拒绝步骤还允许 对滥用者施加数值限制或拒绝列表。
如§ 7 隐私考量中所述,由于请求的方向, 用户代理提示中的措辞应指明哪个站点发起了存储访问请求。