这个问题是对"在本机应用程序和网站之间共享凭据"的补充,因为我们的目标是在相反的方向上共享机密。
TL; TR:我们如何安全地从Web浏览器应用程序向Native Desktop应用程序共享用户的身份验证/授权状态,因此同一用户不必在Native应用程序中另外进行身份验证?
TS; WM:我们正在研究以下体系结构:Web应用程序(在用户选择的Web浏览器中运行着一些HTML前端UI),本机桌面应用程序(实现自定义协议处理程序),Web API和OAuth2服务,如图所示。
就我个人而言,我看不到如何安全地避免这种额外的身份验证流程。默认情况下,通过自定义应用程序协议进行的通信是不安全的,因为通常这只是调用本机应用程序的命令行参数。与TLS通道不同,它可以被拦截,模拟等。我们可以对自定义协议数据进行加密。尽管如此,无论对本机应用程序进行何种调用来解密(无论是对客户端OS API还是对Web API的一些不受保护的调用),坏的actor /恶意软件也可能能够复制这些内容。
我错过了什么吗?是否有特定于平台的安全解决方案?本机桌面应用程序是Electron应用程序,旨在跨平台。我们的大多数用户都可以使用任何受支持的浏览器(甚至包括IE11)在Windows上运行此程序,但是毫无疑问ActiveX或入侵正在运行的Web浏览器实例。
- 由于您具有本机应用程序,因此您可以在该应用程序中嵌入一个微型localhost Web服务器(在特定端口上),该服务器可以侦听来自浏览器应用程序的HTTP调用(在javascript httprequest中)。您可以在其中将TLS与Web应用程序(客户端)和本机应用程序(服务器)中的证书一起使用。由于浏览器应用必须连接到尚未启动的设备,因此存在时间/重试问题,但似乎可以对其进行适当的调整。
-
@SimonMourier这是一个很好的建议,我应该提到我们最初设计的原型。不幸的是,问题多于收益。 localhost的SSL存在问题,即使我们仅使用被认为"可能可信"的http://127.0.0.1:port,我们也存在Windows默认防火墙设置和某些最受欢迎的第三方防病毒阻止该请求的问题。从浏览器javascript确定侦听本地port是另一个问题。
-
我想您试图用Windows的HttpListener(又名Http.sys)实现Web服务器吗?这行不通,因为它与内核绑定,并且需要配置的管理权限,本地计算机中的服务器证书等。它是用于简单操作的PITA。但是,如果您使用TcpListener SslStream(说.NET)来实现它,则可以使用当前的用户证书(您只需要在应用程序和浏览器之间建立一个公共CA),并且它可以不依赖任何我认为的特定权限或防火墙。对于端口,您可以选择一个通常保留但在您的环境中没有人使用的端口。
-
@ SimonMourier,TcpListener SslStream本地CA是一个有趣的想法,谢谢。我们对此有一个担心,是什么可能阻止恶意应用程序运行类似的本地服务器并侦听WB应用程序的请求,从而将自身伪装成我们的本机应用程序?我们可以进一步加密发送到该通道的内容,但这仍然涉及在不受信任的客户端计算机上使用一些私有加密密钥,不是吗?
-
我已经做了一些测试。唯一的问题(无需防火墙,无需管理员权限,就可以了)是关于带有Chrome / FF的证书的。您可以创建自己的CA和证书,但是FF和Chrome会抱怨证书(或其证书链)是自签名的(IE或Edge都可以),即使您将CA安装在本地计算机证书存储中也是如此。因此,您必须安装满足FF / Chrome(=>公共CA或中间CA,例如globalsign.com/en/certificate-authority-root-signing $$$)的证书,或配置安全警告排除项给他们。
-
但是,即使要在本机应用程序中将SSL提议为服务器,您也必须使用pvk(如.pfx)来运送证书。至于最后一个问题,我想知道您认为什么值得信赖,而不是在计算机上。如果这是您关心的问题,那么您将永远无法安装"安全通道",始终必须以某种方式在本地部署私钥(或等效密钥)。请注意,此讨论在某种程度上适用于您可以考虑的任何其他类似渠道(HTTP,URL,TLS)(私钥存储,currentuser与本地计算机,甚至是硬件等)。
-
@SimonMourier,感谢您为我提供的更多帮助-一如既往,非常感谢!我想我可以创建一个自定义CA并将其安装在该计算机上。但是这样做可能会导致actor应用程序性能下降,然后让浏览器应用程序与之交谈。因此,浏览器应用程序必须以某种方式能够验证此自定义CA是我们的而不是伪造的,并且我不清楚该如何执行。感觉就像是鸡肉和鸡蛋的问题。无论如何,这确实是要在提高入侵者的门槛与应用程序的可用性之间进行权衡,因为没有什么绝对是安全的。
-
无论您要执行什么操作,如果它在我的计算机上运行,??我(拥有硬件的人)都可以对其进行破解。因此,仅需提高标准并精确定位到哪个组件即可。您应该评估一个正式的威胁模型en.wikipedia.org/wiki/Threat_model,以便至少您和您的团队(以及SO的人员:-)就什么是合理的攻击以及如何与之抗衡达成共识。例如,您似乎认为浏览器是隐式安全的,而不是本机应用程序。
-
@noseratio如果可以接受嵌入的机密,则DCR(动态客户端注册)将成为您案例的竞争者。但是,请确保授权服务器支持此功能。另外,请确保具有初始请求签名机制,该机制可为注册请求的真实性提供加密绑定。
-
@KavinduDodanduwa,对不起,我实际上使我有些困惑,也许还有你。看起来DCR在这里并不重要,因为它必须由安装程序完成,并且安装程序本身必须针对注册服务器进行交互身份验证,这对我们来说不是一个选择。
-
@KavinduDodanduwa,我提到的另一个链接"动态客户端身份验证"似乎是有关商业解决方案的促销博客文章。他们的产品以某种方式"证明"了客户端应用程序,并确保它仍然是真实的并且未被篡改,然后以动态等效项client_secret发行。他们声称这是减轻假冒威胁的方法。这很有趣,但是我不知道该说法是否正确以及他们实际上是如何做到的。
-
@noseratio我遇到了DCR,但没有遇到动态客户端身份验证。据博客称,这使用了集中式服务。客户发送请求,如果挑战完成,则客户会收到令牌。该令牌是令牌请求中使用的令牌。如果您可以通过服务最终确定初始挑战机制,则这种方法很有希望
-
示例服务可以利用与客户端ID相关联的质询机制,例如totp(en.wikipedia.org/wiki/Time-based_One-time_Password_algorith??m)。
-
@noseratio这种机制避免的是嵌入客户机密,这可以通过反向工程获得。
-
一切都取决于如何确保本机应用程序确实是本机应用程序,而不是某些黑客的窝点(即使从服务器的angular来看,不仅是Web浏览器的angular)。我认为对于网络浏览器或网络服务器,如果没有在该本机应用程序中安装任何秘密的情况下,可以确保正在与谁进行对话(HTTPS证书需要pkv,客户端证书作为好,等等)。可能会严重提高其他系统(Authenticode,Trusted Platform等)的标准,但不能使用Web浏览器。
最佳解决方案:使用自定义URL方案的单点登录(SSO)
当我检查您的问题时,我想起了我在办公室中使用的Zoom应用程序。它是如何工作的?
我的Gmail帐户已链接到Zoom帐户(这是帐户链接,这不在实施范围之内)。打开"缩放"应用程序时,我可以选择使用Gmail登录的选项。这将打开我的浏览器,并带我到Gmail。如果我登录到Gmail,则会重定向回到要求我启动Zoom应用程序的页面。这个应用程式如何启动?安装应用后,该应用会注册一个自定义URL方案,并且浏览器中的最终重定向将以该URL为目标。并且此URL传递了一个临时机密,Zoom应用程序使用该机密来获取OAuth令牌。并且令牌获取是独立于浏览器完成的,使用SSL直接调用OAuth服务器的令牌端点。
这是本机应用程序的授权代码流。这就是移动应用程序使用OAuth的方式。您的主要问题(不允许用户重新登录)已解决。这是正在执行的SSO。
有一个规范定义了围绕此机制的最佳实践。欢迎您阅读RFC8252-适用于本机应用程序的OAuth 2.0。
挑战
您需要为每个应用程序分发实施特定于OS的本机代码。 Windows,Mac和Linux对自定义URL方案具有不同的实现支持。
建议
对于所有OAuth授予类型,
PKCE是强制性的(应在IETF单词中)。正在进行的草案对此进行了讨论。因此,也应将PKCE包含在您的实现中。
使用PKCE,可以防止重定向/回调响应被窃取。甚至其他一些应用程序也截获了回调,因为PKCE code_verifer存在,所以无法重新创建令牌请求。
此外,请勿使用自定义解决方案,例如通过其他渠道传递机密。在维护方面,这会使事情变得复杂。由于该流已存在于OAuth中,因此您可以受益于库和指南。
--------------------------------------------------- ------
更新:保护令牌请求
尽管自定义URL方案解决了启动本机应用程序的问题,但是保护令牌请求可能是一项挑战。有几个选项可供考虑。
-使用从浏览器共享的机密绑定本机应用程序启动
当基于浏览器的客户端启动本机客户端时,它可以调用自定义API来生成机密。此机密就像是一次性密码(OTP)。用户必须先在本机应用中输入此值,然后才能获取令牌。这是在授权代码流之上的自定义。
-动态客户端注册
-
"并且此URL传递了一个临时机密,Zoom应用程序使用该机密来获取OAuth令牌"是如何工作的,它的安全性如何?这是问题的全部。
-
@SimonMourier您收到的秘密是中间秘密。这在OAuth术语中称为授权代码。保护这一点的方法是通过PKCE。浏览器中进行的第一个调用具有散列的机密。身份验证服务器将身份验证相关联。带有此哈希秘密的代码。令牌请求按原样包含机密。由于现在我们使用SSL,因此无法对其进行拦截。从客户端应用程序生成的机密仅在运行时中。
-
请检查tools.ietf.org/html/rfc7636#section-1以获得解释
-
如果我做对了,这仍然不能消除对两次身份验证和授权的需要:1)每当您登录Gmail帐户时,都可以在Web浏览器中进行; 2)在Zoom应用中(可能只是一个授权步骤),前提是Zoom使用的浏览器类型与gmail使用的浏览器类型相同(可能是默认浏览器类型)。这听起来类似于MS Team的工作方式,除了MS Teams有点作弊,并使用内部WebView弹出窗口托管OAuth2流,而不是默认Web浏览器的实例。
-
在一般意义上,"单一登录"仅表示您在所有应用程序中共享相同的凭据(这就是Zoom和Office 365之类的许多软件所做的事情)。但是用户仍然必须使用某种UI(至少可以简化)至少两次进行身份验证(然后可以将其缓存用于下一个会话,如果Web浏览器与本机应用程序Webview兼容,则可以使用持久性cookie等),因此,一次登录印象)。但这不能回答最初的问题。
-
好吧,从一般意义上讲,SSO意味着一次登录并针对多个应用程序共享相同的身份验证状态。如果您考虑使用SAML,OAuth,SSO是通过一种通用的媒体(浏览器)构建的。而在现代,我们不应该将浏览器视为一种作弊手段。应用程序有理由使用这种方法。如果需要,可以的,您可以继续实施自己的解决方案以解决此问题。我只是分享了我所知道的最好的东西。
-
还有一件事,如果您忽略了我提到的登录部分,那么自定义URL方案应该可以使您了解如何通过浏览器启动您的应用程序。但是通信的秘密是安全的,这将需要一些手动的工作。例如,生成一个相关的机密,需要将其手动粘贴到您的本机应用程序中。完成后,本机应用程序将对照服务器进行交叉检查。发生这种情况时,浏览器应用程序应该已经将机密数据推送到服务器。但这根本不是OAuth或SSO。但是取而代之的是一些从PKCE派生的协议。
-
因此,基本上,您说的是本机应用程序仍必须通过Web API(使用您描述的OAuth2 PKCE流或其他任何方式)以某种方式进行身份验证,然后才能通过自定义协议通过以下方式的超链接验证/信任通过自定义协议接收的任何内容:网络浏览器?
-
同样,SSO只是身份验证的另一种形式。只有在用于运行Web应用程序的Web浏览器和用于身份验证流程的本机应用程序使用的Web浏览器是否相同(即相同的Cookie容器)的情况下,才要求在两个地方都登录。即使对于Microsoft自己的应用程序,情况也很少。例如,Teams是基于Electon的,并且其OAuth2流使用了自己的webview窗口。
-
@noseratio IMO,是的。我们正在谈论在两个不同平台上运行的两个不同应用程序。一个在浏览器上,另一个在本机上。您必须避免诸如针对您的本机应用程序的开放重定向之类的威胁。而且,如果您认为有许多威胁向量应考虑避免(tools.ietf.org/html/rfc6819)。这就是我主张使用辅助验证的原因。
-
理想情况下,@ noseratio OAuth不应使用嵌入式浏览器(tools.ietf.org/html/rfc6819#section-4.1.4
n
n
只是有以下想法。这很简单,虽然不允许完全自动设置Web浏览器应用程序与本机应用程序之间的安全通道,但它可能会大大改善用户体验。
我们可以使用基于时间的一次性密码算法(TOTP)。在某种程度上,它类似于我们将蓝牙键盘与计算机或电话配对的方式。
Web浏览器应用程序(用户已通过身份验证)可以向用户显示基于时间的代码,本机应用程序应要求用户输入该代码作为确认。然后,它将使用该代码针对Web API进行身份验证。这足以在两者之间建立后端通道。频道的生命周期应限制为Web浏览器应用程序中会话的生命周期。首先,这种方法甚至可以消除对自定义协议通信的需求。
仍然欢迎其他想法。
-
您的想法不是完全自动化的事实实际上会带来有益的安全副作用:它要求用户确认您的应用程序是接收代码的应用程序,因为用户必须将OTP值故意输入到批准的应用程序中。
-
@JoeGaggler,但是它仍然不如SMS消息安全,因为它们都发生在同一桌面上。恶意应用程序可能会通过截屏来窃取OTP代码。再说一遍,这就是提高攻击的标准。相同的恶意应用程序可能只是定期用我们旨在保护,安装或记录键盘的数据制作UI的屏幕截图。
-
@noseratio好吧,我刚刚看到了这个,我在回答中的最后一条评论是,使用自定义URL方案应该可以使您自动化。
-
后续跟进:twitter.com/noseratio/status/1291795407182290944?s=20
正如您提到的,使用自定义协议处理程序不是传递秘密的安全方法,因为另一个应用程序可能会处理您的协议并拦截该秘密。
如果您施加严格限制,则本机应用程序与Web应用程序之间的通信通道是从Web应用程序启动的,并且本机应用程序以前未建立安全通道(例如,可以对其他机密进行加密的共享机密) ),则无法将机密安全地传输到本机应用。
想象一下,如果可能的话,那么PKCE在OAuth 2.0代码流中将是多余的,因为服务器可以响应授权请求安全地传输访问令牌,而不需要为code_verifier提供获取访问令牌时授予。
- 在PKCE仍然存在的情况下,可以防止潜在的不良行为者用自己的实现完全替换我们的mynativeapp://协议处理程序,然后仅执行整个OAuth 2.0代码PCKE流,向它们提供自己的code_verifier和我们的client_id OAuth服务器,从而完全模拟了我们的本机应用程序?
-
@noseratio如果是这样的话,那么您的命中注定会失败。这意味着用户的计算机已完全被恶意方超越。如果是这样,为什么还要花时间编写具有相同url方案的应用程序,再从编译的代码中窃取嵌入式客户端ID?如果我是那个恶意方,那么我将只部署一个密钥记录器来窃取用户凭据并使用您的应用程序。我希望你明白了:)
-
归根结底,授权时的用户身份验证起着关键作用。 PKCE只需在基于浏览器的请求和令牌请求之间添加加密绑定。但是,如果用户身份验证被盗,则PKCE无效。这些不在OAuth协议的范围内
-
@noseratio您可能会考虑使用客户端机密来克服令牌请求伪造。这违反了oauth规范。据此,将公共客户视为不能确保机密的客户。因此,不鼓励嵌入式客户端机密。但是,如果将其与私钥嵌入进行比较,则我认为在实现负担方面,您将拥有很多优势。您可能会不时考虑客户端秘密的过渡,以避免进行反向工程。
-
@noseratio感谢您指出。尽管可以在这里考虑DCR,但必须确保授权服务器支持它。同样,当我们第一次分发客户端应用程序时,DCR有效。因此,如果您认为反向工程不是问题,那么可以考虑使用基于DCR的客户端注册来保护带有客户端机密的令牌请求。