使用 OAuth2,客户端密码用于向 Google 验证您的应用,反之亦然。 OAuth2 服务器只会向提交正确客户端 ID 和客户端密码(以及其他内容)的应用程序颁发令牌。这种安排(部分)正是为了确保其他人不能(例如)“向您的日历发送垃圾邮件”。否则,Google 怎么知道发出请求的应用程序实际上是合法的,而不是垃圾邮件发送者制作的恶意代码以看起来像您的应用程序?
在您可以使用 OAuth2 之前,您的应用程序已在 Google 注册。作为此过程的一部分,Google 会向您发送一个客户端密码,然后您必须将其构建到您的应用程序实例中。此应用程序实例还与授权握手完成时的重定向 URI 相关联。
这样做的结果是,如果每次部署都必须经过注册过程,您就无法真正分发使用 OAuth2 的应用程序。如果您尝试将机密与您的应用程序一起分发,那么它就不再是机密,而且无论如何,您无法知道可能部署它的所有 URI。
我对我正在开发的应用程序采取的一种方法是让应用程序读取一个客户端机密文件,该文件必须由应用程序的安装程序根据他们自己的注册提供。它的格式基于您注册应用程序时 Google 提供的 JSON 下载。要求每个安装人员都经历这个过程是一件很痛苦的事情,但就目前的情况而言,我认为没有更简单的方法也是安全的。
例如,我有一个使用 Google 的 OpenID Connect 身份验证实现,它基于 oauth2client 库,并使用基于 Google 客户端机密文件的文件格式。当一项服务向 Google 注册以使用 OAuth2 时,Google 可以提供一个“客户端机密”文件,如下所示:
{
"web": {
"client_id": "9876543210.apps.googleusercontent.com",
"client_secret": "secret-12345678901234567890",
"client_email": "9876543210@developer.gserviceaccount.com",
"client_x509_cert_url":
"https://www.googleapis.com/robot/v1/metadata/x509/9876543210@developer.gserviceaccount.com",
"redirect_uris":
[ "http://localhost:8000/annalist/login_done/",
"http://annalist-demo.example.org:8000/annalist/login_done/"
],
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs"
}
}
在我的代码中,我使用此文件通过 oauth2client 库启动 OAuth2 流,代码如下所示:
flow = flow_from_clientsecrets(
clientsecrets_filename,
scope=scope,
redirect_uri=request.build_absolute_uri(login_done)
)
因此您可以看到,除了启动流程时使用的客户端 ID 之外,还有更多信息。我的实现的完整代码位于https://github.com/gklyne/annalist/blob/master/src/annalist_root/oauth2/views.py,大约从第 273 行开始,但该模块中有更多逻辑与将详细信息传递回在 Django 框架中运行的应用程序有关。
我还创建了documentation 用于向 Google 注册应用程序并部署客户端凭据的过程。请注意,这些说明是针对身份服务而不是日历 API 的,并且详细信息是针对我的应用程序的,但我希望有足够的通用性来帮助您。
展望未来,IETF 正在制定一个规范,以允许自动注册使用 OAuth2 的应用程序实例。我认为这是相关规范:https://datatracker.ietf.org/doc/draft-ietf-oauth-dyn-reg/。目前(截至 2014 年 9 月)似乎正在考虑将其发布到标准跟踪出版物中,但这并没有说明何时可以更广泛地使用它。