【问题标题】:.NET Gmail OAuth2 for multiple users适用于多个用户的 .NET Gmail OAuth2
【发布时间】:2016-04-13 10:27:10
【问题描述】:

我们正在构建一个解决方案,该解决方案需要访问我们客户的 Gmail 帐户才能阅读/发送邮件。在帐户注册时,我们会弹出一个供客户执行 Gmail 身份验证页面的弹出窗口,然后是一个后端进程来定期阅读他们的电子邮件。

文档似乎并未涵盖此用例。例如https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth 说客户端令牌应该存储在 client_secrets.json 中 - 如果我们有 1000 个客户端怎么办?

服务帐户用于非用户信息,而是应用程序数据。此外,如果我使用 GoogleWebAuthorizationBroker 并且用户已删除访问权限或令牌已过期,我不希望我的后端服务器应用程序弹出一个网络浏览器,就像这样。 p>

我想我可以使用 IMAP/SMTP 来完成此操作,但我认为将这些凭据存储在我的数据库中不是一个好主意,我认为 Google 也不希望这样做。

是否有关于如何实现的参考?

【问题讨论】:

  • 听起来您需要重新访问 Google OAuth 2.0 documentation。客户端 ID 和密钥对于每种应用程序类型(Web 应用程序、Android 等)都是唯一的。至于您的用例,如果您不想在用户每次使用您的应用时都征得用户同意,那么服务帐户非常适合您正在寻找的内容。这称为“将域范围的权限委托给服务帐户”。阅读更多关于它的信息here
  • 感谢您的回复 - 但该页面顶部显示:“通常,当应用程序使用 Google API 处理自己的数据而不是用户的数据。 例如,使用 Google Cloud Datastore 进行数据持久性的应用程序将使用服务帐户来验证其对 Google Cloud Datastore API 的调用。”
  • 您链接到的部分说:您的应用程序现在有权以您域中的用户身份进行 API 调用这些将随机人不在我的域中。
  • 好的。因此,听起来您的用户不在同一个域中。如果是这种情况,模拟将不可行,因为用户必须在域内。此外,每个应用程序应该只有一个 client_secret。那么,您能否提供有关您的用例的更多信息?
  • 谢谢 - 我们正在构建一个将向公众出售的软件解决方案。部分功能类似于邮件客户端——读入电子邮件并发送消息。最终,我们将来也会添加其他提供商。为了安全起见,我们更喜欢通过 OAuth(2) 来完成。所以我们的客户会在网页上注册 - 向我们提供他们帐户的身份验证,然后后端应用程序会处理他们的消息并定期代表他们发送新消息。

标签: gmail gmail-api google-api-dotnet-client


【解决方案1】:

我也有同样的情况。我们正在计划一项功能,即用户批准代表他们发送电子邮件的访问权限,但消息的实际发送由非交互式进程(在应用程序服务器上运行的计划任务)执行。

我认为最终的答案是定制的 IAuthorizationCodeFlow,它只支持使用现有令牌进行访问,并且不会执行授权过程。我可能会让流程模拟用户单击交互式流程上的拒绝按钮时发生的响应。也就是说,任何获取授权令牌的需求都将简单地返回一个“拒绝”的 AuthorizationResult。

我的项目仍处于研发阶段,我什至还没有进行概念验证。我提供这个答案是希望它可以帮助其他人开发具体的解决方案。

【讨论】:

    【解决方案2】:

    虽然@hurcane 的回答很可能是正确的(还没有尝试过),但这就是我过去几天的工作。我真的不想从文件中反序列化/序列化数据来让它工作,所以我有点混搭了这个解决方案

    1. 获取客户批准的 Web 应用程序
      • 使用来自 Google.Apis.Auth.OAuth2.Mvc 的 AuthorizationCodeMvcApp 和文档
    2. 在 DB 中存储生成的访问和刷新令牌
    3. 使用 AE.Net.Mail 使用访问令牌进行初始 IMAP 访问
    4. 后端也使用AE.Net.Mail访问
      • 如果令牌已过期,则使用刷新令牌获取新的访问令牌。

    我还没有完成发送部分,但我认为 SMTP 会类似地工作。

    代码基于 SO 和博客文章:

    t = 包含令牌信息的 EF 对象

    ic = new ImapClient("imap.gmail.com", t.EmailAddress, t.AccessToken, AuthMethods.SaslOAuth, 993, true);
    

    获取更新的访问令牌(需要错误处理)(使用与上述步骤 #1 相同的 API)

    using (var wb = new WebClient())
                {
                    var data = new NameValueCollection();
                    data["refresh_token"] = refresh;
                    data["client_id"] = "(Web app OAuth id)";
                    data["client_secret"] = "(Web app OAuth secret)";
                    data["grant_type"] = "refresh_token";
    
                    var response = wb.UploadValues(@"https://accounts.google.com/o/oauth2/token", "POST", data);
                    string Tokens = System.Text.Encoding.UTF8.GetString(response);
                    var token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Tokens);
                    at = token.access_token;
                    return at;
                }
    

    【讨论】:

      猜你喜欢
      • 2011-07-25
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 2023-03-31
      • 2018-01-13
      • 1970-01-01
      相关资源
      最近更新 更多