我正在开发一个主要通过应用程序访问的网站,并且我想使用 OAuth2 进行用户注册和身份验证。由于它是一个 Android 应用程序,我将开始使用 Google 的 OAuth2 东西,因为它在 Android 上提供了不错的 UI。
谷歌声明“你可以选择使用谷歌的身份验证系统来为你的应用程序外包用户身份验证。这可以消除创建、维护和保护用户名和密码存储的需要。” 这就是我想要做的。但是,当我浏览他们的所有示例等等时,我只能找到有关让网站或应用程序根据 Google 的服务对用户进行身份验证的内容。
事实上,当我使用 Google 的 OAuth2 注册我的应用程序(“客户端”)时,可以选择网站客户端和“已安装”客户端(即移动应用程序),但不能同时使用两者。我可以创建两个单独的客户端,但我阅读了 OAuth2 草案,我认为会有一个问题,我现在将对此进行解释。
以下是我设想它的工作方式:
- 用户要求 MyApp 访问他的私人数据。
- 应用程序使用 Android 的
AccountManager
类来为 Google 的 API 请求访问令牌。 - Android 对用户说“应用程序‘MyApp’想要访问您在 Google 上的基本信息。可以吗?”
- 用户说是。
AccountManager
使用存储在手机上的凭据连接到 Google 的 OAuth2 服务器,并要求提供访问令牌。- 返回访问令牌(跟随绿线)。
AccountManager
将访问令牌返回给 MyApp。- MyApp 向 MySite 发送请求以获取用户的私有数据,包括访问令牌。
- MySite 需要使用访问令牌验证用户。它使用 Google 验证此处描述的令牌- “Google,此令牌有效吗?”。
- 现在,我想要发生的是谷歌说“是的,给你的人确实是那个用户。”,但我认为实际会发生的事情(基于 OAuth2 草案和谷歌的文档)是它会说“不方式!该令牌仅对 MyApp 有效,而您是 MySite。GTFO!”。
那么我该怎么做呢?请不要说“使用 OpenID”或“不要使用 OAuth2”或其他类似无益的答案。哦,我真的很想继续使用漂亮的AccountManager
UI 而不是蹩脚WebView
的popup
编辑
来自 Nikolay 的临时答案(如果它有效,我会报告!)是它应该真正有效,而且 Google 的服务器不会关心访问令牌来自哪里。对我来说似乎有点不安全,但我会看看它是否有效!
更新
我用 Facebook 而不是 Google 实现了这个模式,它完全有效。OAuth2 服务器不关心访问令牌的来源。至少 Facebook 没有,所以我认为 Google 也没有。
鉴于此,存储访问令牌是一个非常非常糟糕的主意!但是我们也不想访问 Facebook/Google 的服务器来检查每个请求的身份验证,因为它会减慢一切。最好的办法可能是为您的站点添加一个额外的身份验证 cookie,在验证访问令牌时分发该 cookie,但更简单的方法是将访问令牌视为密码并存储它的哈希值。你也不需要加盐,因为访问令牌真的很长。所以上面的步骤变成了这样:
9. MySite 需要使用访问令牌验证用户。首先,它检查其哈希有效访问令牌的缓存。如果在那里找到令牌的散列,则它知道用户已通过身份验证。否则,它会按照此处所述与 Google 进行检查,使用 Google -“Google,此令牌有效吗?”。
10. 如果 Google 说访问令牌无效,我们会告诉用户 GTFO。否则谷歌会说“是的,这是一个有效的用户”,然后我们检查我们的注册用户数据库。如果找不到该 Google 用户名(或 Facebook id,如果使用 Facebook),我们可以创建一个新用户。然后我们缓存访问令牌的哈希值。