OAuth:如何从javascript中隐藏API密钥
OAuth: How to hide API Secret Key from javascript
我们正在迁移基于MVC的服务器应用程序,并制作一个REST-ful API,通过该API处理调用。
我一直在阅读AES加密和OAuth2,并决定实现一个由这些概念发展而来的解决方案,如下所示:
- 客户端发送登录请求,提供用户ID或电子邮件。此请求是使用API密钥的HMAC
- 服务器检查UserID/电子邮件是否与现有帐户匹配,如果找到,则创建并存储服务器随机数,并将其作为响应的一部分发送给客户端
- 客户端创建自己的客户端随机数,并根据API密钥和两个随机数创建新的临时密钥。然后,它发送一个登录请求,并使用这个临时密钥加密密码[以增加熵并避免以明文形式发送密码]
- 服务器使用其在该平台上为该客户端存储的最新随机数[移动客户端和web客户端可以有自己不同的随机数和会话]以及以明文形式发送的客户端随机数来解密密码和HMAC,如果HMAC签出,则根据数据库验证密码[PBKDF2哈希和盐析]
- 如果请求有效且密码和用户ID匹配记录,则会在该平台上为该用户ID创建一个新的会话密钥,并将该密钥发送到客户端,此后该密钥将用于该客户端的每个API请求
- 任何新的非登录请求都将包括根据会话密钥和随机化IV计算的HMAC签名
所有通信都是通过TLS处理的,因此这增加了安全性,而不是唯一的防线。
在移动应用程序上,这将起作用,因为你可以在配置文件中隐藏移动应用程序的密钥,这提供了一些不错的安全措施-[也许不是很多,我不完全确定],但如果我们试图将网页中的所有请求转换为这种形式,这将意味着使用Javascript来处理客户端AES加密和身份验证,以及。。。正如这篇文章清楚地解释的那样,"如果你将API密钥存储在JavaScript web应用程序中,你还可以在主页上用粗体字打印出来,因为全世界现在都可以通过浏览器的开发工具访问它。"
我可以只使用nonce作为API密钥——或者完全放弃对这些请求使用AES加密,并尝试通过其他方式进行验证,如CSRF令牌,并确保所有请求都以某种方式来自我们自己的前端——但如果我们想创建一个允许与其他页面或服务集成的API,我该如何保护客户端的秘密会话密钥?
这篇文章建议生成一次性cookie作为代币,但这是一个有限的解决方案,适用于海报的服务,但不适用于我们。我希望能够使用用户特定的密钥发送HMAC的每个请求,该密钥可以过期并重置,由于该服务最终会处理资金,我希望严格锁定请求身份验证。
那么我有什么选择呢?
既然Javascript注定要失败,我就放弃它吗?是否有某种方法可以存储密钥,而不将其公开为硬编码到.js脚本中的日期?我是否应该生成一个新的临时密钥,仅用于登录调用,并在用户请求服务器nonce时将其发送给用户?
此外,我链接到的帖子首先建议使用cookie来存储客户端的会话密钥,然后从JS访问该密钥。这样可以吗?还是会提供比密封更多的孔?
最好知道哪些措施可以防止哪些安全漏洞。
JavaScript不太适合加密,这是正确的,因为没有地方存储秘密。也没有好的加密库,因为您不应该在JavaScript中进行加密。
会话密钥可以用作身份验证密钥。如果您使用TLS,则连接是安全的,并且攻击者无法知道会话密钥。此外,JavaScript不需要知道会话密钥。默认情况下,每次请求都会发送Cookie。您可以将cookie设置为仅http cookie。您不必这样做,但它确实增加了另一层安全性。
您可以给会话cookie一个很长的过期时间,这样它基本上就像一个秘密的API密钥一样工作。浏览器将负责安全地存储cookie。建议经常轮换会话密钥,通常在每个新会话开始时以及身份验证信息发生更改时(如密码重置)。
CSRF令牌可防止重放攻击。绝对建议使用CSRF令牌来保护修改请求。您不需要对每个请求进行CSRF检查,只需要修改敏感信息(例如您的登录凭据,或者在您的情况下:交易)的请求。对于CSRF令牌,您可以使用与会话密钥相同的方法:将其存储在cookie中。
关键是JavaScript不需要知道这些。
我相信你也意识到了一件重要的事情,那就是你生成的任何密钥或随机数都必须是加密安全的。不要使用低熵函数。
因此:
-
您不需要加密用户ID或电子邮件,TLS已经为您做到了。此外,您也可以发送密码,不需要在步骤3中单独发送。我们不会在JavaScript中进行任何加密。所有加密都由TLS/HTTPS单独处理。
-
如果您有一个单独的身份验证服务器(比如单点登录),这种方法很好。否则你可以跳过这一步。
-
你不需要这个。
-
服务器不需要解密任何内容,加密由TLS处理。如何存储密码是一个单独的话题,但我认为你已经掌握了。
-
好的。同样,客户端不应该加密任何内容。
-
只发送会话密钥。够了。
修订为:
-
客户端发送登录凭据。连接必须安全。
-
服务器验证凭据并将身份验证令牌作为cookie发送,并跟踪身份验证令牌是会话列表。
对于每个请求:
-
客户端包含身份验证令牌。如果您使用cookie,则会自动发生这种情况。
-
服务器验证身份验证令牌,并可能生成一个新的令牌,客户端从此将使用该令牌。
移动应用程序应被视为公共客户端。这意味着他们不应该储存任何秘密。无论您将使用什么加密算法,都不会阻止客户端凭据被泄露。
这就是为什么OAuth2框架协议定义了隐式授权类型流,该流允许公共客户端交互,并且不需要任何客户端身份验证。您还可以考虑使用RFC7636来保护访问令牌的发布。
- 如何隐藏谷歌地图Api 3中InfoBox窗口中的关闭(x)按钮
- Javascript:Google Maps API:如果地图加载在隐藏容器中,则为空白地图
- 我如何从一个无限滚动的网站抓取图像,其中api是隐藏的,我无法通过使用Inspect Element获得它->网络
- 如何对用户隐藏Backbone中的服务器端API
- Wistia Javascript API-设置视频泡沫真实和隐藏社交按钮
- 隐藏Google自定义搜索元素API 2.0的搜索引擎ID
- 谷歌地图API V3-元素不会隐藏点击事件切换
- 谷歌地图API - 通过类别导航隐藏所有信息窗口
- API 调用完成后的离子隐藏启动画面
- 谷歌地图API,根据id显示和隐藏标记
- 我可以在谷歌地图样式API上隐藏非海洋吗?
- 你如何只显示一定数量的Facebook评论,并使用Facebook API隐藏其余的评论
- Facebook Graph API将隐藏时间返回为可读时间格式
- 隐藏客户端API调用
- 谷歌地图API v3.如何根据日期隐藏地图上的标记&时间
- 用于在Google Maps API V3中显示和隐藏驾驶方向上的所有标记的复选框
- 手柄api和隐藏api有多少不同
- OAuth:如何从javascript中隐藏API密钥
- 我需要隐藏API密钥时,使用谷歌地图js API?如果有,怎么做呢?
- 如何使用php隐藏api密钥