我正在尝试设置account linking对于我的 Google Home 操作。为了在用户登录进行链接时对用户进行身份验证,我使用 Firebase Auth 和 FirebaseUI-web与 Google 登录提供商。页面和代码流 validates当我使用 Google OAUth2 Playground 时 test account linking using the Google Home emulator ,我都使用桌面 Chrome 进行了测试。但是当我用 Google Home device and app 进行测试时,它启动流程并显示登录按钮,让我选择一个帐户,重定向回我的页面,然后生成错误:
当我将 Chrome 调试控制台连接到它时,控制台中出现以下错误:
[ 1.995s] [firebaseui] Internal error: {"error":{"errors":[{"domain":"global","reason":"invalid","message":"Cannot parse context"}],"code":400,"message":"Cannot parse context"}}
If I look at the network log, the last xhr POST returns a 400 error. (Some information redacted, since I don't know the sensitivity of the data being sent.)
Request:
URL:https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=[redacted]
Method:POST
请求 header :
Content-Type:application/json
Origin:https://redacted.example.com
Referer:https://redacted.example.com/auth?response_type=code&client_id=api-ai-test&redirect_uri=https://oauth-redirect.googleusercontent.com/r/redacted-project&scope=test1&state=redacted
User-Agent:Mozilla/5.0 (Linux; Android 6.0.1; A0001 Build/MHC19Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36
X-Client-Version:Chrome/JsCore/3.6.5
正文:
{
"postBody": "id_token=redacted&access_token=re.dacted&providerId=google.com",
"requestUri": "https://redacted.example.com/auth?response_type=code&client_id=api-ai-test&redirect_uri=https://oauth-redirect.googleusercontent.com/r/redacted-project&scope=test1&state=redacted",
"returnIdpCredential": true,
"returnSecureToken":true
}
HTTP 响应代码为 400,正文为:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "Cannot parse context"
}
],
"code": 400,
"message": "Cannot parse context"
}
}
有什么办法可以让它正常工作吗?是什么导致了这个问题?
更新以更好地解释用户流程
重要的是要了解 FirebaseUI 用于对登录到我的 OAuth2 服务的用户进行身份验证。不获取 OAuth 信息直接提供给 Home。
所以流程是:
- 用户在首页上通过“Ok Google,通过语音与账单支付对话”等触发器启动操作
- 由于用户尚未将其 Home 连接到“语音账单支付”服务,Home 会提示用户转到 Google Home 应用并关联两个帐户。
- 该卡片显示如下。
- 用户点击该卡,就会打开一个 Chrome 自定义选项卡,其中包含我的登录页面,让他们登录到我的服务。此页面是使用 FirebaseUI 实现的,并有一个按钮让他们可以使用 Google 帐户登录我的服务。
- 如有必要,他们可以选择帐户、登录,然后重定向回页面以继续。正是在这一点上出现了错误。
- 但是,如果它正常工作,该页面将向我的后端服务发送登录信息。这将结束 FirebaseUI 的参与。此时,后端服务将联系 Firebase Auth 服务以获取帐户信息、为此帐户生成授权代码,然后让页面继续 OAuth2 流程并向 Google 提供来 self 的服务的授权代码。
请注意,虽然 (4) 发生在 Chrome 自定义选项卡中,但我也告诉它在 Chrome 本身中打开(通过选项卡中的菜单项),并且它仍然显示相同的问题。
我不清楚步骤(5)中到底发生了什么。对身份工具包服务的一些调用似乎在失败并显示调用失败之前可以正常工作。
最佳答案
好的。我认为这就是正在发生的事情。 FirebaseUI signInWithCredential 用于使用 OAuth token 登录,调用下面的 verifyAssertion。这会将 Google OAuth 访问 token 和 ID token 与 requestURI(当前 URL)一起传递到 Firebase Auth 后端。
问题是您正在尝试使用 FirebaseUI 构建自己的 OAuth 提供程序。 OAuth协议(protocol)建议由第3方应用程序(google home)提供状态参数,然后与授权码一起返回给它。问题是当前 URL 中的此状态参数正在 verifyAssertion(requestUri 字段)请求中发送到 Firebase Auth 后端,然后尝试检查它并注意到它无效(这并不意味着由 Firebase Auth 后端在本例中使用) case),从而抛出错误“无法解析上下文”,当 OAuth 状态参数不匹配时会抛出该错误。
要使其正常工作,托管登录 UI 的网页不应在查询字符串中包含状态参数。
目前,这里有一个解锁您的选项:
- Google Home 会触发帐户关联,并使用所有预期参数(redirect_uri、scope、client_id、state、response_type)重定向到您的网页。
- 将这些内容保存在 sessionStorage 中并重定向到托管您的 FirebaseUI 的另一个页面。
- 使用 sessionStorage 信息,渲染 firebaseUI 和所有其他 UI,当用户完成流程时,用户将返回到登录页面。
- 然后,您可以发出授权码,提取 sessionStorage 信息(redirect_uri、state)并重定向到带有状态和授权码的redirect_uri。
总结是,您需要确保当用户登录后重定向回托管 firebaseui 的页面时,URL 查询字符串中没有可用的状态参数。否则,Firebase Auth 后端会认为它是为此而设计的。
测试上述内容并让我知道这是否有效。我将在下周就这个问题回复您。
如果不清楚,请告诉我,如果需要,我可以进一步解释。
关于firebase-authentication - 将 firebaseui-web 与 Google Home 结合使用时出现 "Cannot parse context"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41862343/