Gmail API OAuth2 Error: redirect_uri_mismatch
Gmail API OAuth2 Error: redirect_uri_mismatch
我遵循了这个 Gmail API Python 快速入门教程:
https://developers.google.com/gmail/api/quickstart/python
我按照说明在 API 控制台中配置了我的 OAuth 客户端 ID(请参见下面的第一张图片)。但是,启动脚本会打开一个浏览器会话,导致下面的 400 错误。
重定向 URL 与 API 控制台中注册的匹配。
但是,快速启动脚本会打开以下 URL:
https://accounts.google.com/o/oauth2...&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F...
手动将重定向 URI 更改为 http://localhost:8080 部分解决了我进行授权请求时的问题,但响应无法返回到命令提示符。
如何强制快速启动程序生成 URL,将重定向 URI 保留为 http://localhost:8080?
您收到错误的原因是 Python Quickstart 说:
d。 Select 凭据选项卡,单击创建凭据按钮和 select OAuth 客户端 ID。
e。 Select 应用程序类型 其他,输入名称 "Gmail API Quickstart",然后单击“创建”按钮。
但是,看看您在做什么,您使用的是 Web 应用程序 而不是 其他。
当我使用其他作为client_secret.json时,我没有遇到这个问题。
结果:
The authentication flow has completed.
不需要 hacks/workaround。只需按照说明操作即可:)
说明
发生这种情况是因为传递给 Google API 服务器的 uri_redirect 参数是百分比编码的 ASCII 字符串。这可以通过查看脚本启动的 URL 来验证:
...redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F...
整个 URL 在执行此行之后的步骤中由快速启动脚本编码:
credentials = tools.run_flow(flow, store, flags)
使用调试器逐步完成该过程显示 URL 最终使用 Python 的 urllib 库中的 urlencode 方法进行编码。这导致 client_secret.json 文件中的 redirect_uri 参数转换自:
http://localhost:8080
至
http%3A%2F%2Flocalhost%3A8080%2F
当 Google 收到 OAuth 请求时,它会将 encoded uri_redirect 参数与 un-encoded 一个在 API 控制台中注册。由于它们不匹配,因此返回 redirect_uri_mismatch。
解决方案
理想情况下,Google 应该修改 API 端点以确保在必要时解码此参数,然后再将其与 API 控制台中注册的内容进行比较。
如果 API 控制台接受编码的重定向 URI 条目,但它不接受:
解决方法(警告:hacky)
简单地替换oauth2client库中两个地方编码的redirect_uri参数:
(1) update_query_params _helpers.py
函数
...
start = new_query.find("redirect_uri")+13
end = new_query.find("&",start)
new_query2 = new_query[:start] + "http://localhost:8080" + new_query[end:]
new_parts = parts._replace(query=new_query2)
...
(2) step2_exchange 在 client.py
...
body = urllib.parse.urlencode(post_data)
start = body.find("redirect_uri")+13
end = body.find("&",start)
body2 = body[:start] + "http://localhost:8080" + body[end:]
headers = {
'content-type': 'application/x-www-form-urlencoded',
}
if self.authorization_header is not None:
headers['Authorization'] = self.authorization_header
if self.user_agent is not None:
headers['user-agent'] = self.user_agent
if http is None:
http = transport.get_http_object()
resp, content = transport.request(
http, self.token_uri, method='POST', body=body2, headers=headers)
...
现在一切正常。
我遵循了这个 Gmail API Python 快速入门教程: https://developers.google.com/gmail/api/quickstart/python
我按照说明在 API 控制台中配置了我的 OAuth 客户端 ID(请参见下面的第一张图片)。但是,启动脚本会打开一个浏览器会话,导致下面的 400 错误。
重定向 URL 与 API 控制台中注册的匹配。
但是,快速启动脚本会打开以下 URL: https://accounts.google.com/o/oauth2...&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F...
手动将重定向 URI 更改为 http://localhost:8080 部分解决了我进行授权请求时的问题,但响应无法返回到命令提示符。
如何强制快速启动程序生成 URL,将重定向 URI 保留为 http://localhost:8080?
您收到错误的原因是 Python Quickstart 说:
d。 Select 凭据选项卡,单击创建凭据按钮和 select OAuth 客户端 ID。
e。 Select 应用程序类型 其他,输入名称 "Gmail API Quickstart",然后单击“创建”按钮。
但是,看看您在做什么,您使用的是 Web 应用程序 而不是 其他。
当我使用其他作为client_secret.json时,我没有遇到这个问题。
结果:
The authentication flow has completed.
不需要 hacks/workaround。只需按照说明操作即可:)
说明
发生这种情况是因为传递给 Google API 服务器的 uri_redirect 参数是百分比编码的 ASCII 字符串。这可以通过查看脚本启动的 URL 来验证:
...redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F...
整个 URL 在执行此行之后的步骤中由快速启动脚本编码:
credentials = tools.run_flow(flow, store, flags)
使用调试器逐步完成该过程显示 URL 最终使用 Python 的 urllib 库中的 urlencode 方法进行编码。这导致 client_secret.json 文件中的 redirect_uri 参数转换自:
http://localhost:8080
至
http%3A%2F%2Flocalhost%3A8080%2F
当 Google 收到 OAuth 请求时,它会将 encoded uri_redirect 参数与 un-encoded 一个在 API 控制台中注册。由于它们不匹配,因此返回 redirect_uri_mismatch。
解决方案
理想情况下,Google 应该修改 API 端点以确保在必要时解码此参数,然后再将其与 API 控制台中注册的内容进行比较。
如果 API 控制台接受编码的重定向 URI 条目,但它不接受:
解决方法(警告:hacky)
简单地替换oauth2client库中两个地方编码的redirect_uri参数:
(1) update_query_params _helpers.py
函数...
start = new_query.find("redirect_uri")+13
end = new_query.find("&",start)
new_query2 = new_query[:start] + "http://localhost:8080" + new_query[end:]
new_parts = parts._replace(query=new_query2)
...
(2) step2_exchange 在 client.py
...
body = urllib.parse.urlencode(post_data)
start = body.find("redirect_uri")+13
end = body.find("&",start)
body2 = body[:start] + "http://localhost:8080" + body[end:]
headers = {
'content-type': 'application/x-www-form-urlencoded',
}
if self.authorization_header is not None:
headers['Authorization'] = self.authorization_header
if self.user_agent is not None:
headers['user-agent'] = self.user_agent
if http is None:
http = transport.get_http_object()
resp, content = transport.request(
http, self.token_uri, method='POST', body=body2, headers=headers)
...
现在一切正常。