我正在使用Spring开发一个通过 OAuth2 保护的REST API,它将从Android应用程序(客户端)中使用。为了访问我的API的任何端点,需要OAuth2访问令牌,并通过授权标头以类似于此的方式移交给端点:
"授权" - " Bearer accesstokenhere"
要获取访问令牌,必须提供用户名和密码,以及客户端ID和客户端密钥(它们代表Android应用程序)。 clientID和客户机密钥以类似于此的方式通过授权标头移交给令牌端点,由Spring指定:
"授权" - "基本clientId:clientSecret"
如果客户端ID和客户端密钥与服务器上定义的客户端匹配,并且用户存在且密码正确,则返回访问令牌和刷新令牌。
现在我的问题是如何在Android应用程序中安全地存储我的clientId和客户端密码,确保有人对我的应用程序进行逆向工程无法访问它们?
另外,如果我要开发一个iOS应用程序(第二个客户端),那么使用来自安全POV的不同clientID和客户端密钥是明智的吗?
答案 0 :(得分:4)
你不能 - 即使有办法,我仍然可以检查线上的有效负载以确定值。请参阅OAuth 2.0 for Native Apps
的第8.5节作为分发给多个用户的应用程序的一部分静态包含的秘密不应被视为机密秘密,因为一个用户可以检查他们的副本并了解共享秘密。出于这个原因,以及[RFC6819]的第5.3.1节中所述,授权服务器不建议使用共享密钥对公共本机应用程序客户端进行客户端身份验证,因为除了客户端识别之外,这几乎没有任何价值。 /> 已经由" client_id"提供请求参数。
您的客户端ID /机密参数只是提供发出请求的应用程序的标识,因此建议您从安全隔离的角度为iOS应用程序创建不同的客户端+对于您想要收集的有关您的应用程序使用情况的任何分析(例如,'您通过客户端ID检索的登录尝试次数是多少?'等等)
然而,威胁演员可以对您的设置进行逆向工程,将您的客户端ID +秘密,然后开始使用用户名/密码组合命中您的令牌端点,以尝试暴力破解您的应用程序。如果端点接受这些值并返回成功/失败代码,则对于试图破坏系统的人来说,这是一个有用的攻击媒介。
目前推荐的方法是使用“授权”代码流程'
在本机应用中授权用户的最佳实践是 在外部用户代理(通常是浏览器)中执行OAuth授权请求,而不是嵌入式用户代理(例如使用Web视图实现的用户代理)。
以前,本机应用程序通常使用嵌入式应用程序 OAuth的用户代理(通常使用Web视图实现) 授权请求。这种方法有许多缺点, 包括主机应用程序能够复制用户凭据和 cookie,以及需要从头开始进行身份验证的用户 应用程序。有关使用嵌入式的更深入分析,请参见第8.12节 OAuth的用户代理。"
有关详细信息,请查看AppAuth for Android