【问题标题】:OAuth 2.0 authentication to Gmail works for accounts with gmail.com domain but not for Google Apps domains对 Gmail 的 OAuth 2.0 身份验证适用于具有 gmail.com 域的帐户,但不适用于 Google Apps 域
【发布时间】:2014-02-13 17:39:56
【问题描述】:

我有一个通过 IMAP 访问 Gmail 的 C# 安装应用程序。使用传统的 IMAP 身份验证,它既适用于个人 Gmail 用户,也适用于 Google Apps 用户。

我现在使用 Google 的 .Net API 添加了对 OAuth 2.0 身份验证的支持。这对于普通的 Gmail 帐户(例如某人@gmail.com)非常有效,但对于具有不同域的 Google Apps 帐户却失败了。系统会提示用户通过 Web 浏览器登录并接受访问,但 IMAP 身份验证尝试失败并显示“凭据无效”。对于 Google Apps 域,是否需要做一些不同的事情?


正如我在下面的评论中首次报道的那样,我在这方面取得了一些小突破。最初,我使用用户参数的文字字符串“user”调用 GoogleWebAuthorizationBroker.AuthorizeAsync()(因为这是我在许多示例中看​​到的)。这适用于普通 Gmail 用户,但我发现,对于 Google Apps,必须传递授权用户的实际电子邮件地址。

有一段时间我认为这是解决问题的全部方法。然而事实证明并非如此。问题是它现在在内部测试中运行良好,但在我们拥有的一个 beta 站点上经常以同样的方式失败。我只能想到 4 个可能的失败原因:(1)程序获得了无效的访问令牌,(2)它以某种方式破坏了该令牌,(3)它错误地执行了 XOAUTH 身份验证或(4)它是使用token对未申请token的账户进行认证。我认为谷歌不太可能提供无效的令牌,因此(1)可以在很大程度上打折。 (2) 和 (3) 总是可能的,但代码适用于我们自己的多个 Gmail 和 Google Apps 帐户的事实使它们看起来不太可能。而客户坚持认为(4)并非如此。所以我仍然感到困惑。

早期有人建议我发布我的一些代码,我现在准备这样做。以下是执行身份验证的 C# 函数的开始:

private void AuthenticateXOAuth2(string strUsername, string strAccessToken)
{
    uint uStatus = 0;

    // The SASL XOAUTH2 initial client response has the following format:
    //
    //  base64("user=" {User} "^Aauth=Bearer " {Access Token} "^A^A")
    string strInitialClientResponse = "user=" + strUsername + "\x1" + "auth=Bearer " + strAccessToken + "\x1\x1";

    byte[] vbInitialClientResponse = Encoding.UTF8.GetBytes(strInitialClientResponse);
    string strBase64InitialClientResponse = System.Convert.ToBase64String(vbInitialClientResponse);

    string strCommand = "AUTHENTICATE XOAUTH2 " + strBase64InitialClientResponse;

    SendCommand(strCommand);
...

我仍在为此苦苦挣扎,走上死胡同,变得更加沮丧。我必须纠正我之前说过的一件事:我断言该程序在内部测试中适用于 Google Apps 域。这是一种错觉。它实际上从来没有。

有人告诉我,我需要使用服务帐户来覆盖域用户。这对我来说似乎令人费解,因为我的程序在任何意义上都不是服务器,但我试过了。它并没有像我尝试的那样工作——但我不能确定我做对了。确认或否定使用服务帐户是正确的策略会大有帮助。

【问题讨论】:

    标签: c# gmail imap google-oauth google-apps


    【解决方案1】:

    没有看到您的代码,我唯一的预感是您没有发送完整的电子邮件地址以供初始客户响应:

    https://developers.google.com/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism

    除此之外,显示您的代码可能有助于我们发现问题。

    【讨论】:

    • 这听起来也是个好主意,谢谢。但是,我已经检查并确认我正在发送完整的电子邮件地址。我会多花点时间,然后可能会发布一些代码。
    • 顺便说一句,我认为developers.google.com/gmail/… 中有一个错误,base64 在初始客户端响应的末尾包含一个不应该存在的换行符。
    • 见base64上面的描述,“base64-encoding后,变成了(为清楚起见插入了换行符)”
    • 我相信你一定误解了这个说法。或者也许我没有清楚地描述我看到的问题。据我了解,该声明仅承认 base64 字符串在该文档中分为两行。如果您对 base64 进行解码并查看解码数据的最后一个字符,您将看到上例中没有的换行符,如果保留该换行符,则会导致身份验证失败。
    • 我不得不把这个项目搁置几个星期,但我现在又回来了,并且已经弄清楚了问题所在。我使用用户参数的文字字符串“user”调用 GoogleWebAuthorizationBroker.AuthorizeAsync()(因为这是我在许多示例中看​​到的)。这适用于普通 Gmail 用户,但我发现,对于 Google Apps,必须传递授权用户的实际电子邮件地址。
    【解决方案2】:

    您可能需要检查是否在您的域帐户中激活了 IMAP/POP;在我工作的公司中,他们出于安全原因限制了此访问权限,您应该如何启用它:

    在您的 Gmail 设置中启用 IMAP

    登录 Gmail。 点击右上角的齿轮。 选择设置。 单击转发和 POP/IMAP。 选择启用 IMAP。 点击保存更改。

    参考:https://support.google.com/mail/troubleshooter/1668960?hl=en#ts=1665018

    【讨论】:

    • 好主意,谢谢,但这不是问题。未启用 IMAP 时,Gmail 可以发送 IMAP 响应,说明以“user@domain.com”身份登录被拒绝:[ALERT] 您的帐户未启用 IMAP 使用。请访问您的 Gmail 设置页面并启用您的帐户以进行 IMAP 访问。 (失败)
    • 查看代码确实需要成为下一步(即使只是演示问题的一个小示例)。仅供参考,我的项目 GYB 是开源的,并且支持 Gmail IMAP OAuth 2.0 身份验证。它成功地与 gmail.com 和 Google Apps 帐户一起使用:code.google.com/p/got-your-back/source/browse/trunk/gyb.py#179
    • 啊哈,我刚刚在看 GYB。我会再看一遍,看看它是否显示我缺少的东西。谢谢!
    猜你喜欢
    • 2015-01-23
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多