Google 隐式帐户链接的操作在 simulator/browser 中有效,但在设备上无效(通过 Google Home 应用程序)
Actions on Google implicit account linking works in simulator/browser, but not on device (via Google Home app)
我已经在 Google 帐户 linking 上实现了操作的隐式流程,并且正在使用 Dialogflow(以前是 API.AI)来定义意图。
完整流程在设备模拟器中运行(来自 AOG)。第一个意图获得 "It looks like your account isn't linked yet..." 响应,调试窗格包含 URL 以启动 linking:
如果我在无缓存的情况下遵循此 URI window:
- 我被重定向到我的应用程序的身份验证页面
- 我选择使用我的 Google 帐户登录(与上面的 [帐户] 相同)
- 我被重定向到 google.com,并在 URI 栏中显示一条成功消息
- 模拟器现在可以通过我的应用程序接受操作并正确响应
但是,如果我使用物理 Google 家庭和 Android 的 gH 应用程序遵循相同的流程。
- 设备告诉我帐户尚未 linked
- 打开Google首页关注'Link to [my app]'link
- 浏览器打开认证页面
- 以用户身份登录
- 重定向到带有单个 link "Return to app" 的白页,其中有一个 href:
about:invalid@zClosurez
链接不成功,因此在 Google 主页上对 运行 意图的额外尝试得到相同的 "Account not yet linked" 响应。
我详细检查了中间 access_token 和状态变量,它们都匹配并且格式正确:
验证后,重定向到(这是'return to app'损坏link的白屏):https://oauth-redirect.googleusercontent.com/r/genzai-app#access_token=[token]&token_type=bearer&state=[state]
因此,就隐式流量帐户而言,模拟器和物理设备的工作方式似乎有些不平行。linking。
我一直在努力解决这个问题,并且与 AOG 支持团队一起努力了很长时间都无济于事。还有其他人看到类似的问题吗?
更新了响应重定向代码:
登录由具有配置文件和电子邮件范围的 react-google-登录组件处理。成功后我们调用:
finish_auth(id_token) {
let provider = {
uri: '/api/auth/google_auth',
params: ['client_id', 'redirect_uri', 'state', 'response_type'],
name: "Google Assistant"
}
if (provider) {
let data = {};
provider.params.forEach((p) => {
data[p] = this.props.location.query[p];
});
if (id_token) data.id_token = id_token;
api.post(provider.uri, data, (res) => {
if (res.redirect) window.location = res.redirect;
else if (res.error) toastr.error(res.error);
});
} else {
toastr.error("Provider not found");
}
}
provider.uri 命中此 API 端点:
def google_auth(self):
client_id = self.request.get('client_id')
redirect_uri = self.request.get('redirect_uri')
state = self.request.get('state')
id_token = self.request.get('id_token')
redir_url = user = None
if client_id == DF_CLIENT_ID:
# Part of Google Home / API.AI auth flow
if redirect_uri == "https://oauth-redirect.googleusercontent.com/r/%s" % secrets.GOOGLE_PROJECT_ID:
if not user:
ok, _email, name = self.validate_google_id_token(id_token)
if ok:
user = User.GetByEmail(_email, create_if_missing=True, name=name)
if user:
access_token = user.aes_access_token(client_id=DF_CLIENT_ID)
redir_url = 'https://oauth-redirect.googleusercontent.com/r/%s#' % secrets.GOOGLE_PROJECT_ID
redir_url += urllib.urlencode({
'access_token': access_token,
'token_type': 'bearer',
'state': state
})
self.success = True
else:
self.message = "Malformed"
else:
self.message = "Malformed"
self.set_response({'redirect': redir_url}, debug=True)
不确定您正在使用哪个 python 中间件或模块,但是
self.set_response({'redirect': redir_url}, debug=True)
似乎正在为返回不正确的响应设置参数。相反,您应该将您的回复重定向到 redirect_url。例如在 Flask 或 Django 中导入重定向模块,例如:
from flask import redirect
或 from django.shortcuts import redirect
然后像这样重定向:
return redirect(redirect_url)
看来 Google 进行了更改,部分解决了这个问题,因为现在可以在模拟器之外完成隐式帐户 linking 流程,方法如下我的问题。
问题似乎源于使用 Google sign-in 按钮登录后使用的 client-side 重定向案例的奇怪处理(在 AOG 方面)。
来自 this thread 的 Jeff Craig:
The current workaround, where we provide the "Return to app" link
currently what we're able to provide. The issue is with the way that
redirecting to custom-scheme URIs is handled in Chrome, specifically,
with regard to the redirect happening in the context of a user action.
XHR will break that context, so what is happening is that you click
the Google Sign-In Button, which triggers an XHR to Google's servers,
and then you (most likely) do a client-side redirect back to the
redirect_url we supply, our handler executes, and isn't able to do a
JS redirect to the custom scheme URI of the app, because were outside
of the context of a direct user click.
This is more of a problem with the Implicit (response_type=token) flow
than with the authorization code (response_type=code) flow, and the
"Return to app" link is the best fallback case we currently have,
though we are always looking for better solutions here as well.
当前行为显示 'Return to app' link,但截至上周,此 link 的 href 不再是 about:invalid@zClosurez
,而是成功完成sign-in 和 linking 过程。这是一个奇怪且令人困惑的用户体验,我希望 Google 将来会有所改进,但这足以让我的应用程序获得 AOG 团队的批准,而无需对我的流程进行任何更改。
好久没搞定了。我们必须先启用 webhook,我们可以在对话流程实现文档中看到如何启用 webhook 如果我们要使用 Google 助手,那么我们必须在首先是集成。然后按照下面提到的步骤在 google:-
上进行帐户链接操作
转到 google 云控制台 -> API 和服务 -> 凭据 -> OAuth 2.0 客户端 ID -> Web 客户端 -> 从那里记下客户端 ID,客户端密码 -> 下载 JSON - 从 json 记下项目 ID,auth_uri,token_uri -> 授权重定向 URI -> 将我们应用程序的 URL 列入白名单 -> 在此 URL 中修复部分是 https://oauth-redirect.googleusercontent.com/r/ 并在 URL 中附加项目 ID -> 保存更改
在 Google 上的操作 -> 帐户 linking 设置 1. 授予类型 = 授权码 2. 客户端信息 1. 填写客户端 ID、客户端密码、auth_uri、token_uri 2. 输入 https://www.googleapis.com/auth and token_uri as https://www.googleapis.com/token 3. Save and run 4. It will show an error while running on the google assistant, but dont worry 5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token 6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email 作为 auth uri,我们就可以开始了。 7. 保存更改。
在托管服务器(heroku)日志中,我们可以看到访问令牌值,通过访问令牌,我们可以获得有关电子邮件地址的详细信息。
将访问令牌附加到此 link“https://www.googleapis.com/oauth2/v1/userinfo?access_token=”,我们可以在生成的 json 页面中获得所需的详细信息。
`accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
r = requests.get(link)
print("Email Id= " + r.json()["email"])
print("Name= " + r.json()["name"])`
我已经在 Google 帐户 linking 上实现了操作的隐式流程,并且正在使用 Dialogflow(以前是 API.AI)来定义意图。
完整流程在设备模拟器中运行(来自 AOG)。第一个意图获得 "It looks like your account isn't linked yet..." 响应,调试窗格包含 URL 以启动 linking:
如果我在无缓存的情况下遵循此 URI window:
- 我被重定向到我的应用程序的身份验证页面
- 我选择使用我的 Google 帐户登录(与上面的 [帐户] 相同)
- 我被重定向到 google.com,并在 URI 栏中显示一条成功消息
- 模拟器现在可以通过我的应用程序接受操作并正确响应
但是,如果我使用物理 Google 家庭和 Android 的 gH 应用程序遵循相同的流程。
- 设备告诉我帐户尚未 linked
- 打开Google首页关注'Link to [my app]'link
- 浏览器打开认证页面
- 以用户身份登录
- 重定向到带有单个 link "Return to app" 的白页,其中有一个 href:
about:invalid@zClosurez
链接不成功,因此在 Google 主页上对 运行 意图的额外尝试得到相同的 "Account not yet linked" 响应。
我详细检查了中间 access_token 和状态变量,它们都匹配并且格式正确:
验证后,重定向到(这是'return to app'损坏link的白屏):https://oauth-redirect.googleusercontent.com/r/genzai-app#access_token=[token]&token_type=bearer&state=[state]
因此,就隐式流量帐户而言,模拟器和物理设备的工作方式似乎有些不平行。linking。
我一直在努力解决这个问题,并且与 AOG 支持团队一起努力了很长时间都无济于事。还有其他人看到类似的问题吗?
更新了响应重定向代码:
登录由具有配置文件和电子邮件范围的 react-google-登录组件处理。成功后我们调用:
finish_auth(id_token) {
let provider = {
uri: '/api/auth/google_auth',
params: ['client_id', 'redirect_uri', 'state', 'response_type'],
name: "Google Assistant"
}
if (provider) {
let data = {};
provider.params.forEach((p) => {
data[p] = this.props.location.query[p];
});
if (id_token) data.id_token = id_token;
api.post(provider.uri, data, (res) => {
if (res.redirect) window.location = res.redirect;
else if (res.error) toastr.error(res.error);
});
} else {
toastr.error("Provider not found");
}
}
provider.uri 命中此 API 端点:
def google_auth(self):
client_id = self.request.get('client_id')
redirect_uri = self.request.get('redirect_uri')
state = self.request.get('state')
id_token = self.request.get('id_token')
redir_url = user = None
if client_id == DF_CLIENT_ID:
# Part of Google Home / API.AI auth flow
if redirect_uri == "https://oauth-redirect.googleusercontent.com/r/%s" % secrets.GOOGLE_PROJECT_ID:
if not user:
ok, _email, name = self.validate_google_id_token(id_token)
if ok:
user = User.GetByEmail(_email, create_if_missing=True, name=name)
if user:
access_token = user.aes_access_token(client_id=DF_CLIENT_ID)
redir_url = 'https://oauth-redirect.googleusercontent.com/r/%s#' % secrets.GOOGLE_PROJECT_ID
redir_url += urllib.urlencode({
'access_token': access_token,
'token_type': 'bearer',
'state': state
})
self.success = True
else:
self.message = "Malformed"
else:
self.message = "Malformed"
self.set_response({'redirect': redir_url}, debug=True)
不确定您正在使用哪个 python 中间件或模块,但是
self.set_response({'redirect': redir_url}, debug=True)
似乎正在为返回不正确的响应设置参数。相反,您应该将您的回复重定向到 redirect_url。例如在 Flask 或 Django 中导入重定向模块,例如:
from flask import redirect
或 from django.shortcuts import redirect
然后像这样重定向:
return redirect(redirect_url)
看来 Google 进行了更改,部分解决了这个问题,因为现在可以在模拟器之外完成隐式帐户 linking 流程,方法如下我的问题。
问题似乎源于使用 Google sign-in 按钮登录后使用的 client-side 重定向案例的奇怪处理(在 AOG 方面)。
来自 this thread 的 Jeff Craig:
The current workaround, where we provide the "Return to app" link currently what we're able to provide. The issue is with the way that redirecting to custom-scheme URIs is handled in Chrome, specifically, with regard to the redirect happening in the context of a user action.
XHR will break that context, so what is happening is that you click the Google Sign-In Button, which triggers an XHR to Google's servers, and then you (most likely) do a client-side redirect back to the redirect_url we supply, our handler executes, and isn't able to do a JS redirect to the custom scheme URI of the app, because were outside of the context of a direct user click.
This is more of a problem with the Implicit (response_type=token) flow than with the authorization code (response_type=code) flow, and the "Return to app" link is the best fallback case we currently have, though we are always looking for better solutions here as well.
当前行为显示 'Return to app' link,但截至上周,此 link 的 href 不再是 about:invalid@zClosurez
,而是成功完成sign-in 和 linking 过程。这是一个奇怪且令人困惑的用户体验,我希望 Google 将来会有所改进,但这足以让我的应用程序获得 AOG 团队的批准,而无需对我的流程进行任何更改。
好久没搞定了。我们必须先启用 webhook,我们可以在对话流程实现文档中看到如何启用 webhook 如果我们要使用 Google 助手,那么我们必须在首先是集成。然后按照下面提到的步骤在 google:-
上进行帐户链接操作转到 google 云控制台 -> API 和服务 -> 凭据 -> OAuth 2.0 客户端 ID -> Web 客户端 -> 从那里记下客户端 ID,客户端密码 -> 下载 JSON - 从 json 记下项目 ID,auth_uri,token_uri -> 授权重定向 URI -> 将我们应用程序的 URL 列入白名单 -> 在此 URL 中修复部分是 https://oauth-redirect.googleusercontent.com/r/ 并在 URL 中附加项目 ID -> 保存更改
在 Google 上的操作 -> 帐户 linking 设置 1. 授予类型 = 授权码 2. 客户端信息 1. 填写客户端 ID、客户端密码、auth_uri、token_uri 2. 输入 https://www.googleapis.com/auth and token_uri as https://www.googleapis.com/token 3. Save and run 4. It will show an error while running on the google assistant, but dont worry 5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token 6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email 作为 auth uri,我们就可以开始了。 7. 保存更改。
在托管服务器(heroku)日志中,我们可以看到访问令牌值,通过访问令牌,我们可以获得有关电子邮件地址的详细信息。
将访问令牌附加到此 link“https://www.googleapis.com/oauth2/v1/userinfo?access_token=”,我们可以在生成的 json 页面中获得所需的详细信息。
`accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
r = requests.get(link)
print("Email Id= " + r.json()["email"])
print("Name= " + r.json()["name"])`