谷歌OAuth 2授权-错误:redirect_uri_mismatch

617

我在https://code.google.com/apis/console网站上注册了我的应用程序,设置了生成的客户端ID客户端密钥到我的应用程序中,并尝试使用Google登录。

不幸的是,我收到了以下错误消息:

Error: redirect_uri_mismatch
The redirect URI in the request: http://127.0.0.1:3000/auth/google_oauth2/callback did not match a registered redirect URI

scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
response_type=code
redirect_uri=http://127.0.0.1:3000/auth/google_oauth2/callback
access_type=offline
approval_prompt=force
client_id=generated_id

这条信息是什么意思,我该如何修复它? 我使用了gem omniauth-google-oauth2


35
如遇此问题,您可通过在浏览器中访问以下URL进行调试:https://accounts.google.com/o/oauth2/auth?client_id={client_id}&response_type=token&redirect_uri={redirect_uri}&scope={scope},而无需运行整个应用程序进行测试。请注意,翻译时尽量保持原意,使内容更通俗易懂,不要添加解释或其他内容。 - Jack M
2
我注意到,谷歌自动将 redirect_uri 绑定在双引号中(redirect_uri="whatever")以上的 URL 中,并导致此错误。如果我删除这个双引号,我就能通过下一个屏幕了。现在,我们该如何避免这个双引号,因为它是由谷歌自动重定向的? - Abhishek Soni
@JackM,response_type 不应该等于 code 吗?那么 token 是什么? - Benyamin Jafari
47个回答

587

重定向 URI (响应返回的位置) 必须在 APIs 控制台中进行注册,该错误表明您尚未完成此操作或未正确完成。

前往您项目的控制台,查看 API 访问选项。您应该能够看到您的 客户端 ID客户端密钥,以及重定向 URI 的列表。如果您需要的 URI 未列出,请单击编辑设置并将其添加到列表中。

注意:(以下摘自下���一条高评价评论)更改 Google API 控制台并使其生效可能需要一些时间。通常只需几分钟,但有时可能需要更长时间。


15
有一些魔力,因为一个小时前我尝试相同的回调时它没有起作用,但现在它正在工作。无论如何,谢谢! - user984621
429
遇到了类似的问题,想指出更新 Google API 控制台并使更改生效可能需要一些时间。通常只需几分钟,但有时可能需要更长时间。 - sdolphin
55
让我补充一下 @Bazyl 的回答:在我收到的信息中,他们提到了URI“http://localhost:8080/”(当然,这似乎是谷歌内部配置)。我将授权的URI更改为那个,“http://localhost:8080/”,消息就不再出现了……而且视频也上传成功了…API文档非常糟糕……每次我使用谷歌API时,我只是感到“幸运”,因为缺乏良好的相关文档……:( - David L
9
在你的浏览器中打开一个私密/无痕窗口,然后再试一次。有时这可以解决缓存问题。 - Dunc
25
在Google控制台的"Api & Auth > Credentials"中,Google没有提供重定向URI的选项。无论我是创建新的客户端ID还是生成新的密钥,都无法从Google控制台指定重定向URI,这并不重要。 - user3338098
显示剩余33条评论

197

在我的情况下,涉及到 wwwnon-www URL。实际站点使用 www URL,而 Google 开发者控制台中的 Authorized Redirect URIs 使用 non-www URL。因此,重定向 URI 不匹配。我通过更新 Google 开发者控制台中的 Authorized Redirect URIswww URL 来解决此问题。

其他常见的 URI 不匹配包括:

  • 在 Authorized Redirect URIs 中使用 http://,而实际 URL 使用 https://,或者反之亦然
  • 在 Authorized Redirect URIs 中使用有斜杠结尾的 URL (http://example.com/),而实际 URL 则没有斜杠结尾 (http://example.com),或者反之亦然

以下是 Google 开发者控制台的逐步截图,这对于那些难以找到开发者控制台页面以更新重定向 URIs 的人将会非常有帮助。

  1. 前往https://console.developers.google.com

  2. 选择您的项目

选择您的项目

  1. 点击菜单图标

点击菜单图标

  1. 点击 API 管理器 菜单

选择API管理器菜单

  1. 点击 Credentials 菜单,然后在 OAuth 2.0 Client IDs 下,您会找到客户端名称。在我的情况下,它是 Web Client 1。点击它会弹出一个窗口,在那里您可以编辑授权的Javascript来源(Authorized Javascript Origin)授权重定向URI(Authorized redirect URIs)

选择凭据菜单

注意:默认情况下,已授权的URI包括所有本地主机链接,任何在线版本都需要包括完整路径,而不仅仅是域名,例如 https://example.com/path/to/oauth/url

这是一篇谷歌文章,介绍了如何创建项目和客户端ID


5
我将"Authorized JavaScript origins"和"Authorized redirect URIs"都保留为空白,然后将"Authorized redirect URIs"设置为"http://127.0.0.1/google_account/authentication",这样就可以了。 - Krishh
1
对于那些遇到困难的人,如果您是通过其他谷歌页面(例如Drive API页面)创建应用程序的,您可能看不到这些选项。我不得不从API管理器控制台内删除并重新创建客户端ID。 - tgun926
1
为了查看JavaScript来源和重定向URI,我需要将应用程序类型设置为“Web应用程序”。 - Michael Grant
我正在为一个由Firebase创建的应用程序进行此操作,并且必须忽略创建新的客户端ID,而是使用名为“Web客户端(由Google服务自动创建)”的现有ID。 - kip2
在我的情况下,问题是一个斜杠 :| - amirhossein
显示剩余3条评论

138
如果你正在使用 Google+ JavaScript按钮,那么你必须使用 postmessage 代替实际的URI。由于谷歌的文档没有清楚地说明这一点,我花了几乎一整天的时间才弄清楚这一点。

8
由于这个问题是谷歌搜索错误信息时的热门结果,所以在此提供一些额外的指引。正如 Mike 所说,对于重定向 URI,请使用 "postmessage"。如果您正在使用 Web 应用程序服务器流程,则需要在两个位置指定此流程。一个是在 JavaScript 上的 g-signin 按钮中。另一个是在服务器代码中的授权客户端中。 - Rob Whiteside
5
postMessage听起来不错,但它会导致无用的“Error: invalid_request”错误,“origin参数是必需的!” - user3338098
17
尝试解决这个问题几个小时后,你的回答帮了我很多!谷歌文档不是很清楚。在服务器端,如果您使用谷歌API客户端库,应该使用以下代码:$client->setRedirectUri('postmessage');而不是$client->setRedirectUri('http://your.url...'); - Guicara
4
哇...@Guicara的解决方案让我在长时间的挣扎后终于迎来了成功。 - djthoms
1
我曾经在Django-Rest-Social-Auth和Angular前端中遇到了问题,但当我将'redirect_uri'设置为'postmessage'时,问题得以解决。非常感谢! - Sijeesh
显示剩余12条评论

113

如果您在客户端检索到一个授权码,例如使用GoogleAuth.grantOfflineAccess()API,现在想要将该代码传递给服务器、赎回它并存储访问和刷新令牌,则必须使用文字串postmessage而不是redirect_uri

例如,在Ruby文档中的片段基础上构建:

client_secrets = Google::APIClient::ClientSecrets.load('client_secrets.json')
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'profile https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'postmessage' # <---- HERE
)

# Inject user's auth_code here:
auth_client.code = "4/lRCuOXzLMIzqrG4XU9RmWw8k1n3jvUgsI790Hk1s3FI"
tokens = auth_client.fetch_access_token!
# { "access_token"=>..., "expires_in"=>3587, "id_token"=>..., "refresh_token"=>..., "token_type"=>"Bearer"}

唯一提到postmessage的Google文档是这个旧的 Google+ 登录文档。由于 G+ 即将关闭,因此在此提供屏幕截图和存档链接

Legacy Google+ API DOC

离线访问文档页面竟然没有提到这一点,简直无法容忍。#FacePalm


1
@mariobgr 是的,其他回答提到了 postmessage,但我想说明具体情况(例如 grantOfflineAccess),在这种疯狂的未记录黑客攻击下我必须使用它。:P 我也不希望这是真的。:) 让我头痛了几个小时。 - Jeff Ward
今天早上又让我困扰了几个小时的是另一个 postmessage 问题:在分析 Google 的 Python 客户端代码后,我终于找到了这个:"postmessage: string,通常设置为 'postmessage' ,以匹配客户端指定的 redirect_uri"。另外,在他们的文档中也有提到:"默认的 redirect_uri 是当前 URL 去掉查询参数和哈希片段。"这意味着如果您的 redirect_uri 不是当前 URL,则需要在 gapi.auth2.init() 中明确指定它,在服务器端,您将使用 postmessage - James Rasmussen
Jeff,你太棒了!我刚刚花了几个小时来调试Google的Auth API,这是其中之一的问题。疯狂的“解决方案”在任何地方都没有记录。事实上,他们自己的文档在这里给出了错误的答案。太棒了!(另外,Google到底是什么意思?) - Kirill
postmessage 解决了我的问题,谢谢! - undefined

66

对于我的网络应用程序,我通过编写进行了更正

instead of : http://localhost:11472/authorize/
type :      http://localhost/authorize/

感谢您的分享,对我很有帮助。我之前遇到了问题,因为GitHub OAuth2 API 不需要您删除端口号。 - florisla
这对我也起作用了。我正在遵循这个课程:http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on,但一直出现“重定向URI错误”。在将https://localhost:44334/signin-google更改为https://localhost/signin-google后,它就可以正常工作了。非常感谢有用的提示。 - FrenkyB
2
非常感谢。我正在使用https://github.com/google/google-api-dotnet-client-samples 进行测试,但是每次运行时,“请求中的重定向URI”似乎来自不同的端口。这对我帮助很大。否则我可能需要花费数小时才能找出问题所在! - Alejandro Lozdziejski
太棒了,这对我的情况完美地起作用了!我不得不添加 http://127.0.0.1/authorize/,因为它没有解析到本地DNS。 - newLoop

48

1.你会看到像这样的错误:

在此输入图片描述

2.然后,你应该点击请求详细信息 在此输入图片描述

之后,您需要复制该URL并将其添加到 https://console.cloud.google.com/ 中。

  1. 进入 https://console.cloud.google.com/

在此输入图片描述 在此输入图片描述

  1. 点击菜单 -> API 和服务 -> 凭据

在此输入图片描述

  1. 您会看到类似这样的仪表板,点击“编辑OAuth客户端” enter image description here

  2. 现在在“授权的JavaScript来源”和“授权的重定向URL”中添加显示错误称为“redirect_uri_mismatch”的URL,即此处为 http://algorithammer.herokuapp.com ,所以我已将其添加到“授权的JavaScript来源”和“授权的重定向URL”中的两个位置。

  3. 点击保存并等待5分钟,然后再尝试登录


这个可行,似乎不需要等待5分钟,在我的情况下小于等于2分钟就可以了。 - Eric

40
请确保检查协议是 "http://" 还是 "https://",因为 Google 也会检查协议。 最好将两个 URL 都添加到列表中。

11
不,最好确保你正在使用https。 - Brad Koch

15

5
这是因为 redirect_uri 在开发者控制台和你的应用程序中必须完全匹配。 - tony gil
我在开发者控制台和应用程序中都没有结尾的“/”,两者完全匹配,但却无法正常工作。我不得不添加一个结尾的“/”才能使脚本正常工作。 - vvvvv
这解决了我的问题,谢谢。不知道为什么需要这个。 - Shahriar Rahman Zahin

13

这个答案与Mike的答案Jeff的答案相同,都在客户端将redirect_uri设置为postmessage。我想在服务器端添加更多内容,并介绍适用于此配置的特殊情况。

技术栈

后端

前端

"Code"流程(特定于Google OAuth2)

概述:React --> 请求社交认证 "code" --> 请求JWT令牌以在自己的后端服务器/数据库中获取 "登录" 状态。

  1. 前端(React)使用“Google登录按钮”,responseType="code"获取授权代码。(它不是令牌,也不是访问令牌!)
    • 这个 Google 登录按钮来自上面提到的 react-google-login
    • 点击按钮会弹出一个窗口,供用户选择账户。当用户选择了一个账户并窗口关闭后,您将从按钮的回调函数中获取代码。
  2. 前端将代码发送到后端服务器的 JWT 端点。
    • 使用{ "provider": "google-oauth2", "code": "在此处检索到的代码", "redirect_uri": "postmessage" }进行 POST 请求。
  3. 对于我的 Django 服务器,我使用 Django REST Framework JWT + Django REST Social Auth。 Django 接收来自前端的代码,与 Google 的服务进行验证(已为您完成)。一旦验证成功,它将向前端发送 JWT(令牌)。前端现在可以收集令牌并将其存储在某个地方。
    • Django中的settings.py文件中的REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URIREST_SOCIAL_DOMAIN_FROM_ORIGINREST_SOCIAL_OAUTH_REDIRECT_URI都是不必要的。(它们是Django REST Social Auth使用的常量)。简而言之,您不需要在Django中设置任何与重定向URL相关的内容。在React前端中,"redirect_uri": "postmessage"就足够了。因为您必须在前端上执行所有Ajax式POST请求的社交认证工作,并且根本不需要提交任何表单,所以默认情况下实际上不会发生任何重定向。这就是为什么如果您正在使用code + JWT流程,则重定向URL变得无用,服务器端重定向URL设置不起作用的原因。
    • Django REST Social Auth会处理帐户创建。这意味着它将检查Google帐户电子邮件/名字和姓氏,看它是否与数据库中的任何帐户匹配。如果没有,则会为您创建一个帐户,使用完全相同的电子邮件和名字。但是,如果您的电子邮件是youremailprefix@example.com,则用户名将类似于youremailprefix717e248c5b924d60。它会附加一些随机字符串以创建唯一的用户名。这是默认行为,我相信您可以自定义它并随意查阅他们的文档。
    • 前端存储该令牌,当需要对后端服务器执行CRUD操作时,特别是创建/删除/更新,如果将令牌附加在您的Authorization头中并发送请求到后端,Django后端现在将其视为登录,即已验证用户。当然,如果您的令牌过期,您必须通过发出另一个请求来刷新它。

天哪,我花了6个多小时终于做到了!我相信这是我第一次看到这个postmessage的东西。任何使用Django + DRF + JWT + Social Auth + React组合的人都肯定会遇到这个问题。我无法相信除了这里的答案外,没有任何文章提到这一点。但是我真的希望这篇文章可以为您节省大量时间,如果您正在使用Django + React堆栈。


11
在我的情况下,我的凭证申请类型是“其他”。因此,在凭证页面中找不到“授权重定向URI”。它似乎出现在应用程序类型:“Web应用程序”中。但是,您可以单击“下载JSON”按钮以获取“client_secret.json”文件。 enter image description here 打开JSON文件,您可以找到以下参数:"redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]。我选择使用http://localhost,对我来说很有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接