我的公司正在构建一个RESTful API,它将返回中等敏感信息(即财务信息,但不包括帐号)。我可以控制RESTful API代码/服务器,也正在构建Android应用程序。我已经设置了API以使用OAuth 2和授权代码授权流程(带有客户端ID和密码),并且我自动批准用户而不必批准客户端,因为我们拥有客户端和提供者。我们使用CAS进行SSO,当用户登录以检索令牌时,我将此作为OAuth 2进程的一部分用于授权服务器。
我正在考虑各种方法来保护Android应用上的数据。我已经得出结论,在设备上存储客户端ID和秘密绝对不会发生,但我认为存储身份验证令牌可能有效,因为它只对个人用户构成风险(并且实际上只有当他们碰巧有根电话。)
以下是我想到的两个选项。它们都要求我拥有一种受CAS保护的代理服务器,与API服务器共舞,并返回身份验证令牌。这消除了在应用程序代码中存储客户端ID和秘密的需要。
以下是我的想法:
1)要求用户输入密码以在每次启动应用程序时访问数据。这绝对是最简单的方法。如果这样做了,我可能想要保存userID以方便使用,但在这种情况下无法使用CAS登录(因为它是基于Web的)。我可以在后端使用无头浏览器将用户登录到CAS并根据他们在Android表单中输入的内容检索令牌,但这看起来很糟糕。保存userID与Chase应用程序的工作方式类似(如果你碰巧使用这个) - 它会在会话之间保存用户ID而不是你的密码。
2)将身份验证令牌存储在Android设备上。这有点不太安全,但几乎万无一失。当用户第一次启动应用程序时,将网页打开到返回令牌的代理服务器的CAS登录名(类似于https://developers.google.com/accounts/docs/MobileApps)。用户登录并将令牌返回给应用程序后,对其进行加密并将其专用于应用程序。此外,使用ProGuard对代码进行模糊处理,使加密算法更难以进行逆向工程。我也可以在令牌刷新中工作,但我认为这更像是一种虚假的安全感。
3)不要使用CAS,而是想出另一种方法来获取服务的身份验证令牌。
关于其他人如何实施类似方案的任何建议(如果已经完成)?
感谢。
答案 0 :(得分:4)
开发OAuth等标准的原因是,不是每个人都必须一次又一次地重新考虑相同的攻击向量。所以大多数情况下,最好选择坚持现有的东西,而不是烘焙自己的东西。
无法秘密存储数据的客户端的第一个问题是某些攻击者可以访问用户的数据。由于技术上不可能阻止这种情况(代码混淆不会帮助您对抗专家攻击者),在短时间内OAuth 2 typically expires中的访问令牌并且不会给出攻击者完全访问权限(以范围为界)。当然,您不应该在这样的设备上存储任何刷新令牌。
第二个问题是client impersonation。攻击者可以窃取您的客户端密钥并在他自己的(可能是恶意的)应用中访问您的API。用户仍然必须自己登录。 OAuth草案要求服务器尽其所能来防止这种情况,但这真的很难。
授权服务器必须尽可能验证客户端。如果授权服务器由于客户端的性质而无法对客户端进行身份验证,则授权服务器必须要求注册用于接收授权响应的任何重定向URI,并且应该利用其他方法来保护资源所有者免受此类潜在恶意客户端的攻击。例如,授权服务器可以让资源所有者参与协助识别客户端及其来源。
我认为谷歌是第一个尝试通过检查应用程序的签名来验证此类设备上的客户端的方法,但是他们尚未准备好迎接黄金时段。如果您想更深入地了解该方法,请参阅my answer here。
目前,您最好的选择是保持OAuth方式,即拥有访问令牌,客户端ID 和客户端密码(在设备上使用授权代码授予流程时,并将服务器配置为执行其他检查。如果你觉得这些变得更加安全,那就去做吧,但总是把它想象成这些价值是公开的。