在 Android 上的应用程序之间共享 oauth 令牌 - 共享用户 ID、钥匙串、AccountManager 或其他内容?

Mar*_*rky 6 android oauth sharedpreferences accountmanager android-contentprovider

我正在尝试针对我所处的特定情况找出最佳解决方案,但在找出最佳选择时遇到困难。这是一个棘手的设置,因此对于 Android 专家来说可能是一个有趣的挑战!这是我的情况:

  • 我们已经在 Play 商店上发布了两款 Android 应用程序,并且正在开发另一款应用程序。
  • 这两个已发布的应用程序使用相同的密钥库进行签名,但目前在其清单文件中没有设置sharedUserId。
  • 这两个已发布的应用程序将用户的 oAuth 令牌存储在 SharedPrefs 中,将一些产品/内容数据存储在 SQLite DB 中,并将一些音频/视频内容存储在外部存储中(使用 getExternalFilesDir)。
  • 这些应用程序都是我们服务器的独立 oAuth 客户端/应用程序(即它们都使用不同的客户端 ID 和密钥)。
  • 我们的服务器设置为每个 oAuth 应用程序(即 Android 应用程序)仅允许一个 oAuth 令牌。例如,如果用户在一个设备上登录应用程序 A,然后在另一台设备上登录应用程序 A,则第一个设备的令牌将失效,并且该应用程序将收到 401。
  • 通过启用应用程序之间的共享钥匙串,我们已在 iOS 上成功实现了单点登录系统。如果应用程序检测到组中的另一个应用程序具有有效的 oAuth 令牌,它可以将其发送到我们的服务器并将其交换为该应用程序的有效令牌。
  • 在 iOS 版本中,我们希望确保应用程序不需要使用每个应用程序的硬编码值来了解其他应用程序的存在(例如,如果我们将来发布新应用程序,其他应用程序不需要知道)更新为与其共享/接收令牌),因此我们在钥匙串中创建了一个条目,其中包含一组具有有效令牌的捆绑包 ID,所有应用程序都可以访问这些令牌。当应用程序成功登录或交换令牌时,它们会将自己的捆绑包 ID 添加到该数组中。任何新安装的应用程序都可以从该数组中找到捆绑包 ID,并将其用作加载该应用程序的令牌详细信息的密钥,然后将其交换为自己的新令牌。
  • 我们希望代币交换是自动的,不需要用户输入。

我希望一切都有意义!如果没有,请告诉我。

我现在正在尝试找出在 Android 上存储 oAuth 令牌(以及一些附加数据,例如与之配套的电子邮件地址)的最佳方法,以便我们帐户拥有的其他应用程序可以访问它们以交换新令牌。

我研究过使用以下方法,但不确定最佳路线:

  1. SharedPreferences 以及sharedUserId
  2. 帐户管理器(https://developer.android.com/reference/android/accounts/AccountManager.html
  3. Android 钥匙串(https://developer.android.com/reference/android/security/KeyChain.html
  4. 内容提供商

选项 1. 的问题似乎是在首次发布后设置共享用户 ID 将失去对所有数据的访问权限(请参阅http://java-hamster.blogspot.jp/2010/05/androids-shareduserid.html)。这对于我们的用户来说并不是一件好事。

选项 2.(AccountManager)可能是一个不错的选择,但如果我们想单独存储令牌(每个应用程序),但希望我们制作的任何其他应用程序访问其令牌,我不确定我们会如何做到这一点。

选项 3...是否可以使用 Keychain 完成我们需要的操作?

如果我理解正确的话,选项 4 需要每个应用程序都有自己的 ContentProvider 吗?我不确定这将如何满足我们的要求。

如果有人经历过这种情况并能分享一些见解和建议,我将不胜感激!

Joa*_*usa 4

ContentProvider 可能是您最好的。我无法为您提供完整的代码来执行此操作,但这通常是我认为它的工作方式:

  1. 每个应用程序都会创建一个公开自己的 API 令牌的内容提供者;
  2. 每个应用程序在请求登录之前都会尝试获取和查询(依次直到成功)所有其他内容提供商;
  3. 如果应用程序 X 能够从应用程序 Y 获取并检索令牌(通过 Y 的内容提供商),则将其存储在应用程序 X 中并使用它;

旁注:

  1. 这是非常敏感的信息,因此您应该加强安全保护。您的内容提供程序只能由使用相同密钥签名的其他应用程序访问,它们应该仅具有读取权限,并且您也应该创建自己的自定义权限。
  2. 内容提供者不需要访问 sqlite 数据库。它可以访问您用来存储令牌的任何内容(我希望以安全的方式存储,但我将把它留给您自己的判断)

有用的链接:

  1. 如何创建自定义内容提供商

  2. 如何保护您的内容提供商

  3. 从共享偏好中检索数据的内容提供商示例;