用于多用户的.NET Gmail OAuth2

用于多用户的.NET Gmail OAuth2,gmail,gmail-api,google-api-dotnet-client,Gmail,Gmail Api,Google Api Dotnet Client,我们正在构建一个解决方案,需要访问客户的Gmail帐户才能阅读/发送邮件。在帐户注册时,我们会为客户弹出一个Gmail认证页面,然后是一个后端进程,定期阅读他们的电子邮件 文档似乎没有涵盖这个用例。例如,客户机令牌应该存储在client_secrets.json中——如果我们有1000个客户机怎么办 服务帐户用于非用户信息,而不是应用程序数据。此外,如果我使用Google WebAuthorizationBroker,并且用户已删除访问权限或令牌已过期,我不希望我的后端服务器应用程序弹出打开we

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

文档似乎没有涵盖这个用例。例如,客户机令牌应该存储在client_secrets.json中——如果我们有1000个客户机怎么办

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

我想我可以使用IMAP/SMTP来实现这一点,但我认为在我的数据库中存储这些凭据不是一个好主意,我认为谷歌也不希望这样


有没有关于如何实现这一点的参考资料?

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

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


我的项目仍处于研发阶段,我甚至还没有做概念验证。我给出这个答案是希望它能帮助其他人制定一个具体的解决方案。

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

  • 获取客户批准的Web应用程序
    • 使用Google.api.Auth.OAuth2.Mvc和文档中的AuthorizationCodeMvcApp
  • 在数据库中存储结果访问和刷新令牌
  • 使用AE.Net.Mail使用访问令牌进行初始IMAP访问
  • 后端还使用AE.Net.Mail访问
    • 如果令牌已过期,则使用刷新令牌获取新的访问令牌
  • 我还没有完成发送部分,但我想SMTP也会起到类似的作用

    代码基于SO和博客帖子:

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

    ic = new ImapClient("imap.gmail.com", t.EmailAddress, t.AccessToken, AuthMethods.SaslOAuth, 993, true);
    
    获取更新的访问令牌(需要错误处理)(使用与上述步骤1相同的API)

    使用(var wb=new WebClient())
    {
    var data=new NameValueCollection();
    数据[“刷新令牌”]=刷新;
    数据[“客户端id”]=“(Web应用OAuth id)”;
    数据[“客户端密码”]=“(Web应用OAuth密码)”;
    数据[“授权类型”]=“刷新令牌”;
    var response=wb.UploadValues(@)https://accounts.google.com/o/oauth2/token“,”后“,数据);
    字符串标记=System.Text.Encoding.UTF8.GetString(响应);
    var token=Newtonsoft.Json.JsonConvert.DeserializeObject(令牌);
    at=token.access\u token;
    返回;
    }
    
    听起来你需要重新访问谷歌。客户端ID和密码对于每种应用程序类型(Web应用程序、Android等)都是唯一的。至于您的用例,如果您不想让用户在每次使用您的应用程序时都给予同意,那么服务帐户非常适合您所寻找的内容。这称为“将域范围的权限委托给服务帐户”。请阅读更多相关信息。感谢您的回复-但在该页面的顶部写着:“通常,当应用程序使用Google API处理自己的数据而不是用户的数据时,应用程序使用服务帐户。例如,使用GoogleCloudDatastore进行数据持久化的应用程序将使用服务帐户来验证其对GoogleCloudDatastoreAPI的调用。“您链接到的部分说:您的应用程序现在有权作为域中的用户进行API调用,这些用户可能不在我的域中。好的。因此,听起来您的用户不在同一个域中。如果是这种情况,模拟将不可行,因为用户必须在域内。此外,每个应用程序只能有一个客户端密钥。那么,您能提供一些关于您的用例的更多信息吗?谢谢-我们正在构建一个软件解决方案,将向公众出售。该功能的一部分类似于邮件客户端——读入电子邮件并发送消息。最终,我们将在将来添加其他提供商。为了安全起见,我们更喜欢通过OAuth(2)来实现。所以我们的客户会在一个网页上注册-给我们他们帐户的身份验证,然后后端应用程序会处理他们的消息,并代表他们定期发送新消息。
    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;
                }