首页 文章

使用OAuth2为app *和*网站进行身份验证

提问于
浏览
61

我正在开发一个主要通过应用程序访问的网站,我想使用OAuth2进行用户注册和身份验证 . 由于它是Android应用程序,我将开始使用Google的OAuth2内容,因为它在Android上提供了不错的用户界面 .

谷歌说"You can choose to use Google's authentication system as a way to outsource user authentication for your application. This can remove the need to create, maintain, and secure a username and password store."这就是我想要做的 . 然而,当我浏览他们的所有示例和诸如此类的东西时,我只能找到有关网站或应用程序根据Google服务对用户进行身份验证的内容 .

事实上,当我使用Google的OAuth2注册我的应用程序(“客户端”)时,网站客户端和“已安装”客户端(即移动应用程序)可以选择,但不能同时选择两者 . 我可以创建两个单独的客户端,但我读了OAuth2草案,我认为会有一个问题,我现在将解释 .

以下是我设想的工作方式:

OAuth2 flow diagram

  • 用户要求MyApp访问他的私人数据 .

  • App使用Android的 AccountManager 类来请求Google API的访问令牌 .

  • Android对用户说"The app 'MyApp' wants access to your Basic Information on Google. Is this ok?"

  • 用户说是的 .

  • AccountManager 使用手机上存储的凭据连接到Google的OAuth2服务器,并要求提供访问令牌 .

  • 返回访问令牌(绿线后面) .

  • AccountManager 将访问令牌返回给MyApp .

  • MyApp向MySite发送请求以获取用户的私有数据,包括访问令牌 .

  • MySite需要使用访问令牌验证用户 . 它使用Google验证令牌as described here - "Google, is this token valid?" .

  • 现在,我想要发生的是谷歌说"Yes, whoever gave it to you is indeed that user.",但我认为实际发生的事情(基于OAuth2草案和谷歌的文档)是它会说"No way! That token is only valid for MyApp, and you're MySite. GTFO!" .

那我该怎么做呢?请不要说"Use OpenID"或"Don't use OAuth2"或其他同样无益的答案 . 哦,我真的想继续使用漂亮的 AccountManager 用户界面,而不是蹩脚的弹出窗口 WebView s

编辑

来自Nikolay的临时答案(我会报告它是否有效!)它实际上应该有效,而Google的服务器并不关心访问令牌的来源 . 对我来说似乎有点不安全,但我会看看它是否有效!

更新

我用Facebook而不是Google实现了这种模式,它完全有效 . OAuth2服务器不关心访问令牌的来源 . 至少Facebook没有,所以我认为谷歌也没有 .

鉴于此,存储访问令牌是一个非常糟糕的主意!但是我们也没有't want to have to hit Facebook/Google'的服务器来检查每个请求的身份验证,因为它会减慢一切 . 可能最好的办法是为您的站点添加一个额外的身份验证cookie,当您的访问令牌被验证时,您可以将其分发,但更简单的方法就是将访问令牌视为密码并存储其哈希值 . 你不需要加盐它,因为访问令牌真的很长 . 所以上面的步骤变成了:

  1. MySite需要使用访问令牌验证用户 . 首先,它检查哈希有效访问令牌的缓存 . 如果在那里找到令牌的散列,则它知道用户已经过身份验证 . 否则,它会使用Google "Google, is this token valid?"与Google as described here进行核对 .

10.如果Google说访问令牌无效,我们会告诉用户GTFO . 否则谷歌说“是的,这是一个有效的用户”,然后我们检查我们的注册用户数据库 . 如果找不到Google用户名(或Facebook id,如果使用Facebook),我们可以创建新用户 . 然后我们缓存访问令牌的散列值 .

6 回答

  • 5

    您可能需要OpenID Connect,它使用OAuth令牌进行身份验证 . 至于 AccountManager ,当前的OAuth支持有点hacky,新的Google Play Services,设置为发布'soon'应该有希望使这更好 . 在这里查看demo .

  • 1

    我刚刚将an answer发布到类似的StackOverflow问题 .

    谷歌称之为Hybrid Apps,并解释了如何"Android app obtains offline access for Web back-end" .

    它的要点是你必须将一个按摩的 scope 字符串传递给 GoogleAuthUtil.getToken ,以使其返回授权码(而不是OAuth2令牌) . 根据this schematic,授权码可以从您的移动应用程序传递到您的服务器,并可以交换为OAuth2令牌和刷新令牌 .

    scope 参数需要看起来像这样:

    oauth2:server:client_id:<your_server_client_it>:api_scope:<scope_url_1> <scope_url_2> ...
    
  • 1

    您可以在其他任何位置使用移动应用程序检索的访问令牌 . Drive SDK有一个很好的简单介绍,通过流程https://developers.google.com/drive/quickstart-android

  • 1

    至少对谷歌而言,访问令牌最终会过期 . 这就是为什么android AccountManagerinvalidateAuthToken 方法 - 缓存的访问令牌已经过期,你需要告诉 AccountManager 停止给你旧的,而是获得一个新的 . 这使得缓存令牌更安全一些,因为令牌本身不会像您那样为用户提供永久访问权限 . 相反,当有效时,它只是说"at some point in the recent past, this token was acquired by a trusted source."

    在使用令牌时,我发现了一些有用的东西 . 第一个是Google的tokeninfo endpoints . 令牌本身只是base64编码的JSON . 这意味着它未加密,因此您需要确保使用HTTPS进行通信 . 但是,这也意味着您可以检查令牌并更好地了解正在发生的事情 .

    https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=

    如果您的令牌是“abcdef”,您将导航到:

    https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=abcdef

    谷歌会为你打开令牌 . 它是一个简单的JSON对象,包含一个“expires_in”字段,告诉您令牌仍然有效的秒数 . 在下面的视频中的6:03,您可以看到解压缩的令牌:

    https://developers.google.com/events/io/sessions/383266187

    该视频包含对OAuth2的全面概述,如果您要处理OAuth和令牌,则完全值得一看 . 演讲者还讨论了其他形式的Oauth2令牌,这些令牌不是访问令牌,不会过期 .

    另一个有用的资源是OAuth Playground . 这使您可以执行基本操作,例如请求范围,补充请求和返回令牌 . 此链接似乎偶尔会起作用,在Chrome上我必须安装Oauth Playground应用:

    https://developers.google.com/oauthplayground/

    这是视频中的发言人Tim Bray的教程,解释了如何使用访问令牌从Android应用程序与服务器进行通信 . 这对我很有用,因为我开始了解Google API控制台中的不同内容如何协同工作:

    http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html

    关于问题的实际答案,我想你永远不需要在服务器上缓存访问令牌 . 如上面的从Android验证后端呼叫链接中所述,验证令牌几乎总是一个快速静态调用,这意味着没有理由缓存令牌:

    库可以缓存Google证书,只在需要时刷新它们,因此验证(几乎总是)是一个快速静态调用 .

    最后,您确实可以使用 AccountManager 获取访问令牌 . 但是,Google现在改为鼓励在Play服务库中使用 GoogleAuthUtil 类:

    In a nutshell what's the difference from using OAuth2 request getAuthToken and getToken

    在这里请注意Tim Bray的评论,同样是来自上述链接的人,说他们正在努力进入 GoogleAuthUtil 路线 . 但请注意,这意味着您将仅限于Google身份验证 . 我相信 AccountManager 可以用来获取例如Facebook令牌 - 而不是 GoogleAuthUtil .

  • 0
  • 2

    当我们需要在非Google OAuth服务器上执行类似操作时,我们会将令牌保存在网站上的数据库中 . 然后,应用程序将在需要请求数据时使用Web服务来请求令牌 .

    用户可以在网络或应用上进行OAuth注册 . 他们共享相同的应用程序令牌,因此他们可以共享相同的访问令牌 . 注册后,我们将存储数据库中的访问权限和刷新令牌,以便从需要的任何应用程序中使用 .

相关问题