category
第三方Cookie已经成为用户跟踪和隐私问题的代名词。2021年,谷歌提出了一项计划,将第三方cookie从基于铬的浏览器中退役,并推出FedCM API。在本博客中,我们将讨论这一变化,以及它对传统OAuth流意味着什么。
目录
- 介绍
- 什么是第三方cookie
- 对OAuth协议的影响
- FedCM简介
- 支持FedCM:身份提供商如何适应
- 结论
介绍
联合身份一直是身份验证领域的游戏规则改变者。凭借更高的安全性、更顺畅的登录和更大的转换,它已成为应用程序最受欢迎的身份验证选择。尽管有几种方法可以启用联合身份,但OAuth协议已成为最受欢迎的协议。2022年,谷歌为保护人们的在线隐私而创建的隐私沙盒团队发布了一份公告,宣布发布和测试新的以隐私为重点的API,最终目标是到2024年从Chrome中退役第三方cookie。他们为什么这么做?如何访问不同域的cookie?这对OAuth有何影响?在这个博客中,我们将探讨这些问题以及更多内容。
什么是第三方cookie?
cookie是网站可以存储在用户计算机上的一些信息。网站使用Cookie进行会话管理和个性化设置。不过,第三方cookie是由用户当前所在域以外的域设置的。例如,当您浏览网站并与嵌入的视频或广告交互时,外部域会设置一些第三方Cookie。出现的问题是,服务使用第三方cookie来跟踪网站上的用户活动,以根据其浏览和搜索历史提供有针对性的广告。这引发了一些隐私问题,也是谷歌决定停用第三方cookie的主要原因。
对OAuth协议的影响
OAuth传统上执行到身份提供程序域的全页重定向,并访问会话cookie(如果存在)或允许用户登录。此流不受第三方cookie更改的影响。然而,一些应用程序,如谷歌一键点击(google one-tap),希望实现更有机的流量,并允许用户在不被重定向的情况下登录。他们使用iframe实现这一点,并访问第三方cookie来检查用户是否有有效的会话。
由于从技术上讲,用户不会重定向到不同的域,因此必须使用第三方cookie来促进身份验证,而正是这种流受到第三方Cookie失效的影响。
FedCM简介
联邦同意管理(FedCM)API是一种解决方案,旨在解决受影响的OAuth流中第三方cookie的限制。FedCM在不需要使用第三方cookie的情况下实现了更多的私密登录流。浏览器控制用户设置,显示用户提示,并且只有在得到明确的用户同意后才能联系谷歌、脸书或Github等身份提供商。
支持FedCM:身份提供商如何适应
实现FedCM兼容有两个步骤:
-
身份提供程序集成
- 这将是一个像谷歌、脸书或Github这样的身份提供商,希望与FedCM兼容。
-
客户端集成更改
- 前端库也需要更新以支持FedCM流。在谷歌的情况下,这将是谷歌一键式SDK。
步骤1:身份提供程序集成
要与FedCM集成,身份提供程序需要执行以下操作:
A.提供一个众所周知的文件来识别身份提供者。B.为帐户列表和断言发布提供配置文件和端点(以及可选的客户端元数据)。C.使用登录状态API更新其登录状态。
A.提供一个众所周知的文件来识别身份提供者。
存在一个潜在的隐私问题,即身份提供者能够辨别用户是否在未经明确同意的情况下访问。这具有跟踪影响,因此身份提供程序需要提供一个众所周知的文件来验证其身份并缓解此问题。
众所周知的文件是通过GET请求请求的,该请求不遵循重定向。这有效地防止了身份提供者了解是谁提出了请求以及客户端试图连接哪个。
众所周知的文件必须由身份提供程序的eTLD+1提供,地址为/.aknowledge/web Identity。例如,如果身份提供程序端点在https://accounts.idenity-provider.example/,他们必须在https://idenity-provider.example/.well-known/web-identity.众所周知的文件内容应该具有以下JSON结构:
{
"provider_urls": ["https://accounts.idenity-provider.example/config.json"]
}
例如,谷歌的知名文件可以在https://www.google.com/.well-known/web-identity
它提供以下文件:
{
"provider_urls": [
"https://accounts.google.com/gsi/fedcm.json"
]
}
B.为帐户列表和断言发布提供配置文件和端点(以及可选的客户端元数据)。
- 身份提供程序配置文件列出了浏览器处理身份联合流和管理登录所需的端点。
- 配置文件(位于https://accounts.identity-provider.example/config.json在我们的示例中)应该具有以下JSON结构:
{
"accounts_endpoint": "/accounts.php",
"client_metadata_endpoint": "/client_metadata.php",
"id_assertion_endpoint": "/assertion.php",
"login_url": "/login",
"branding": {
"background_color": "green",
"color": "0xFFEEAA",
"icons": [
{
"url": "https://Identity Provider.example/icon.ico",
"size": 25
}
]
}
}
例如,Google的配置如下所示:
{
"idtoken_endpoint": "https://accounts.google.com/gsi/fedcm/issue",
"id_token_endpoint": "https://accounts.google.com/gsi/fedcm/issue",
"id_assertion_endpoint": "https://accounts.google.com/gsi/fedcm/issue",
"accounts_endpoint": "https://accounts.google.com/gsi/fedcm/listaccounts",
"client_metadata_endpoint": "https://accounts.google.com/gsi/fedcm/clientmetadata",
"client_id_metadata_endpoint": "https://accounts.google.com/gsi/fedcm/clientmetadata",
"signin_url": "https://accounts.google.com/gsi/fedcm/signin",
"login_url": "https://accounts.google.com/gsi/fedcm/signin",
"revocation_endpoint": "https://accounts.google.com/gsi/fedcm/revoke",
"disconnect_endpoint": "https://accounts.google.com/gsi/fedcm/revoke",
"supports_add_account": true,
"modes": {
"button": {
"supports_use_other_account": true
},
"widget": {
"supports_use_other_account": false
}
},
"branding": {
"background_color": "#1a73e8",
"color": "#fff",
"icons": [
{
"url": "https://accounts.google.com/gsi-static/google-logo.png"
}
]
}
}
C.使用登录状态API的登录状态
登录状态API允许身份提供程序通知浏览器其在特定浏览器中的登录(登录)状态,即是否有任何用户登录到当前浏览器上的身份提供程序。
对于每个已知的身份提供程序(由其配置URL标识),浏览器保留一个三态变量,该变量表示具有三个可能值的登录状态:
- “登录”:身份提供程序至少有一个用户帐户已登录。如果登录状态为“已登录”,则会向IdP的帐户列表端点发出请求,并在浏览器提供的FedCM对话框中向用户显示可用于登录的帐户。
- “已注销”:所有身份提供程序帐户当前都已注销。如果登录状态为“已注销”,则FedCM get()请求返回的promise将被拒绝,而不会向帐户列表端点发出请求。在这种情况下,由开发人员来处理流,例如通过提示用户前往并登录到合适的IdP。
- “未知”:此身份提供程序的登录状态未知。这是默认值。如果登录状态为“未知”,则会向IdP的帐户列表端点发出请求,并根据响应更新登录状态:
如果端点返回可用于登录的帐户列表,请将状态更新为“已登录”,并在浏览器提供的FedCM对话框中向用户显示登录选项。
如果端点未返回任何帐户,则将状态更新为“已注销”;FedCM get()请求返回的promise随后被拒绝。
步骤2:客户端集成更改
对于使用谷歌等身份提供商提供的SDK的客户端,除了更新到最新版本外,不应该有明确的要求。如果您想手动与FedCMAPI交互,以下是您需要做的。
使用凭据管理器API获取联合凭据
使用navigator.certificate.get()函数,您可以请求用户使用已登录到浏览器的现有Identity Provider帐户登录到客户端。此功能采用身份选项,可以在其中配置身份提供程序的详细信息。
实例
async function signIn() {
const identityCredential = await navigator.credentials.get({
identity: {
context: "signup",
providers: [
{
configURL: "https://accounts.idp.example/config.json",
clientId: "********",
nonce: "******",
loginHint: "user1@example.com",
},
],
},
});
}
如果身份提供程序成功验证了用户身份,则返回IdentityCredential对象。此对象包含一个令牌,该令牌包含已使用身份提供程序的数字证书签名的用户身份信息。
然后,您可以将令牌发送到服务器以验证证书,成功后,可以使用令牌中的(现在受信任的)身份信息将他们登录到其服务(启动新会话),如果他们是新用户,则可以将他们注册到其服务,等等。
如果用户从未登录过Identity Provider或已注销,则get()方法会拒绝并返回错误,您可以将用户引导到Identity Provider登录页面以登录或创建帐户。
这是典型的流程:
FedCM流量
- 客户端调用navigator.certificate.get()函数来启动登录流。
- 浏览器从get()调用中提供的configURL请求两个文件:
- 众所周知的文件(/.aknowledge/web identity),可从configURL的eTLD+1上的/.aknowled/web identify获得。
- Identity providers配置文件(/config.json),位于configURL
- 浏览器根据已知文件中的有效配置URL列表验证get()请求中传递的configURL。
- 如果浏览器将身份提供程序的登录状态设置为“已登录”,则会向身份提供程序配置文件中的accounts_endpoint发出认证请求(即使用标识已登录用户的cookie),以获取用户的帐户详细信息。发送请求时不带client_id参数或Origin标头,这会阻止身份提供程序了解用户试图登录的客户端。因此,返回的帐户列表与客户端无关。
- 身份提供程序使用从`accounts_endpoint“请求的帐户信息进行响应。这是与用户的身份提供程序cookie相关联的所有帐户的数组,用于与身份提供程序相关联的任何客户端。
- 浏览器使用前两个请求获得的信息来创建UI,要求用户选择一个帐户登录客户端(在有多个可用帐户的情况下)。
- 如果用户授予了这样做的权限,则浏览器会向id_assertion_endpoint发出有凭据的请求,以向身份提供程序请求所选帐户的验证令牌。
- 流完成后,get()promise将使用IdentityCredential对象进行解析,该对象提供了进一步的客户端功能。最值得注意的是,此对象包含一个令牌,客户端可以验证该令牌来自身份提供程序(使用证书),并且包含有关已登录用户的可信信息。一旦客户验证了令牌,他们就可以使用包含的信息让用户登录并启动新会话,为他们的服务注册等。令牌的格式和结构取决于身份提供商,与FedCM API无关(客户需要遵循身份提供商的说明)。
有关FedCM如何工作的更多信息,您可以查看官方文档。
结论
最后的主要问题是身份提供商是否应该符合FedCM。尽管FedCM仍处于开发的初级阶段,谷歌主要推出了这些更改,以确保谷歌一键点击仍然有效,但关注它很重要。FedCM还不是一个网络标准,在当前迭代中与SAML或OpenID连接不兼容。这也相当困难。但是,随着浏览器隐私法的变化,如果FedCM成为联邦身份的实际方法,身份提供商可能必须遵守。
- 登录 发表评论