【问题标题】:Securing OAuth clientId/clientSecret in AngularJS application在 AngularJS 应用程序中保护 OAuth clientId/clientSecret
【发布时间】:2024-01-13 20:15:02
【问题描述】:

我知道这可能是一个古老的问题,但是......是否有任何最佳实践来保护客户端机密以在 AngularJS 应用程序中执行 OAuth2 身份验证?我一直在绞尽脑汁想出一种解决方案,从现代风格的 Web 应用程序中提供对 API 的真正安全访问(它们不一定是 AngularJS。)根据我的经验,添加抽象层和混淆层确实不行任何提高安全性的方法...它们只会让任何潜在的黑客更难破解安全蛋(但是他们中的许多人更喜欢挑战,所以你真正要做的只是让黑客更有趣。)

除了代码的混淆和卷积等明显无效的解决方案之外,在现代 Web 应用程序中是否有保护客户端机密的最佳实践?我知道这些问题是由桌面客户端应用程序引起的,我不相信除了“最好混淆,这会减慢黑客的速度”之外还有其他解决方案。我们与网络应用程序在同一条船上吗?这个问题没有真正的解决方案吗?

如果没有解决方案...使用 OAuth 保护 REST API 真的有任何意义吗?

【问题讨论】:

    标签: angularjs security oauth token secret-key


    【解决方案1】:

    请记住,OAuth 不是关于防止假冒,而是更多关于保护凭据。第三方为您验证了用户的身份,而不会暴露用户的凭据。由于令牌不是凭证,因此黑客可以造成的伤害量和他的行动窗口是有限的。

    但是 OAuth 对您的应用程序而言并不比常规用户名/密码身份验证更安全。在客户端应用程序上,您的所有代码都可供全世界查看!作为 你提到,客户端加密是一个值得怀疑的策略。


    虽然没有既定的保护客户互动的最佳做法,但这里有一些方法可以最大限度地减少您的风险:

    1) SSL:灵丹妙药?可能是。您在自己的网站和请求中使用 SSL 的次数越多,用户的请求就越安全。老实说,我相信所有特权请求都应该由加密请求发出。

    2) 令牌寿命短:令牌的寿命越短,嗅探它的激励/优势就越小。

    OAuth 2.0 通过将身份验证令牌换成刷新令牌换成身份验证令牌来在身份验证之外创建一个持续的喋喋不休。作为开发人员,您现在正在开发一个聊天应用程序,该应用程序执行很多“你的令牌是什么,这是另一个令牌,向我要一个令牌,这是你的新令牌......所以你想要什么?” ...“哎呀,时间到了,你的刷新令牌呢?”

    如果这听起来很痛苦,那确实是。 OAuth 2.0 旨在使开发人员的流程更轻松。但重要的一点是,代币的寿命越短,黑客就越难维护欺诈身份。 Refresh Token reference

    3) 加强你的领域: 想要减少嗅探者滥用你盔甲缝隙的机会吗?不允许跨域请求!

    当然,我们经常有分布式环境。但是,如果您的 Facade 位于客户的域中,那么您的曝光率就会降低(单词选择有问题)。

    强迫黑客使用你的域名,限制他们的创造力。

    4) 尽可能频繁地使用 3rd 方 API 来维护您的访问权限: GoogleFacebook API 和服务已经过单元测试、实战测试和演进。您越能依靠他们来维护您的用户身份,您所做的工作就越少,获得的机会就越少。

    5) 检查 IP 地址: 几乎任何东西都可以伪造,但黑客必须知道 IP 地址是您验证的一部分。这是所有做法中最不可靠的做法,但结合 1,2 或更多,黑客可利用的差距越来越小,努力的回报也逐渐消失。

    6) 使用“秘密”或第二个参数:您可以传递给用户的不仅仅是令牌。您可以传递自己的 Alter-Token。

    假设它是一个来回传递的 ID 数据。以不明显的方式命名参数。将其设为数字​​(例如年龄、身高、地址)。重要的一点是,您的黑客对对方要求的内容知之甚少或一无所知!

    您可以通过设置 3 个作为安全性的参数来解决问题。

    7) 不要提供错误消息来通知黑客他们已被抓获。给出超时消息而不是“知道了!”如果入侵者没有意识到欺诈行为被抓住了,他们也不会适应。


    我不能说太多——SSL 省去了很多麻烦。

    注意:我见过的所有客户端提供商都允许访问他们的 API 而不会暴露 Secret。 绝不能将秘密暴露给客户端。

    • 客户端上暴露的任何数据都可以闪烁
    • 您使用的任何加密算法都将在客户端上公开。

    【讨论】:

    • 我喜欢你的回答。对于像我这样的菜鸟进入客户端进行 API 通信来说,这是一个很好的解释。在我的情况下,我控制双方。 API 端是一个使用 OAuth 的 python/django API。它接受客户端 ID、客户端密码、用户名和密码,并返回身份验证令牌和刷新令牌。就我而言,客户端机密可见吗?出于某种原因,这对我来说并不容易。
    • @farcrats,你的犹豫是正确的——你的“秘密”永远不应该公开。始终使用 SSL 加密。但是你也可以使用你自己的 psuedo-secret——给每个用户一个你存储的特殊代码。我喜欢使用“身高:12 英寸”、“年龄:53”之类的东西。我以精确的格式存储这些数据,并期待一个“假装参数,如用户的身高或年龄(再次应该与真实数据无关)。这样你就创建了另一种形式的身份验证,黑客甚至不知道是其中的一部分身份验证过程。
    • 谢谢戴夫。我们正在使用 SSL。我会按照你的建议实施一些事情。再次感谢您的帮助。
    • 我完全同意,SSL 省去了很多麻烦。不过,有时这并不是企业想要做的。我试图解释 OAuth 是如何不完全安全的,但我猜它们是按照自己的方式设置的。
    • 似乎没有回答这个问题。这些都不是在浏览器内 javascript 应用程序中正确隐藏客户端机密的方法。 Dave Syer 谈到了实际的解决方案(可能是这里,我认为spring.io/blog/2015/01/12/…),它涉及到暂时打破“纯 JS SPA”模式并加载“受保护”资源(带有客户端密码的文件)从服务器。
    【解决方案2】:

    我来这里是为了寻找这个问题的答案 - 如何在 SPA 中处理秘密/ID。我想出了自己的解决方案,将秘密隐藏在服务器中,但我想确认我所做的是最佳实践。因此,由于答案避免了这种情况,我将解释我的流程,希望它能帮助任何人。

    我们的架构 - 我们有一个 ruby​​ 服务器作为 api 服务器和一个 express 服务器为 Angular 应用程序提供服务。

    通常所有的通信都是通过 api 简单地以 RESTful 方式完成的,因此节点服务器只是提供静态文件而不是真正做很多事情。

    由于我们正在实施登录/注册流程,因此我遇到了 - 对我来说是新的 - OAuth 2.0 如何处理事情的流程。

    在我们可以向服务器发出任何请求并且服务器会认真对待我们之前,我们需要让自己获得 Bearer 令牌。我选择将其实现为节点端点,从而将客户端密码隐藏在节点服务器本身内。

    所以我们的客户已经输入了他们所有有趣的数据,并准备成为我们应用中的用户,他们点击了提交按钮。

    1. 应用程序向节点服务器发出请求,以获取我们可以用作承载者的美味令牌。我选择将客户端 ID 作为 GET 请求查询参数传递。首先,我在节点服务器中同时拥有客户端 ID 和机密,但感觉 ID 可以/应该在客户端上。所以我就这样走了。

    2. 节点服务器通过 GET 请求接收客户端 ID,然后继续将 POST 发送到主机(ruby api)。构造 url + 授权类型 + 客户端 ID + 客户端密码。从而向世界隐藏实施。

    3. ruby 服务器返回一个令牌供我们使用,然后我们将其返回给初始化注册请求的客户端。

    4. SPA 现在有一个不记名令牌,我们可以在注册请求的标头中使用它。

    这样就完成了我们的流程,并拥有了一个不为人知的隐藏的古老秘密。

    由于我们有一个具有特定寿命的令牌,我们还有一个请求错误拦截器,它将捕获已过期的令牌,从而发出新的令牌请求,然后重新触发失败的调用。

    我选择在 Angular 方面使用这个库供用户流使用。

    https://github.com/sahat/satellizer

    它是一个超级方便的库,每次我们希望应用程序通过电子邮件/密码以及通过 oauth 进行身份验证时都必须编写所有无聊的样板代码......非常方便。

    因此,由于这是我自己对如何做这些事情的解释 - 请提供反馈。

    【讨论】:

    • 嗨,Sten,和你一样,我已经阅读了这篇文章,试图找出如何在 SPA 应用程序中保守秘密。我对您的方法有一些疑问(可能是因为我对此也很陌生)。 1. 您只有一个客户端应用程序吗? 2. 当现有用户登录时会发生什么(使用客户端密码?) 3. 如何阻止任何拥有(公共?)客户端 ID 的人尝试登录(因为客户端应用程序似乎永远不会被告知秘密是)? - 这些可能是菜鸟问题,但只是一些我无法从你的文章中弄清楚的东西。谢谢
    • 1 年后 - Oauth 2.0 延迟。只需使用 JSON Web 令牌 (JWT)。通过 Satelizer 将它们用作 Bearer 令牌(如果您使用的是 Angular),它们获得了所有商品,并且个人认为最有意义的是最灵活且不能伪造,因为后端是发行者。在我看来 99.999% 绝对可靠......