移动应用程序的 OAuth2 访问令牌是不是必须过期?

Posted

技术标签:

【中文标题】移动应用程序的 OAuth2 访问令牌是不是必须过期?【英文标题】:Do OAuth2 access tokens for a mobile app have to expire?移动应用程序的 OAuth2 访问令牌是否必须过期? 【发布时间】:2012-07-06 14:46:45 【问题描述】:

这里接受的关于why OAuth2 access tokens expire的答案:

许多提供商都支持不安全的不记名令牌。通过使它们变得短暂并需要刷新,它们限制了攻击者滥用被盗令牌的时间。 (这是什么意思?我认为它的意思是允许在没有 TLS 的情况下进行传输?还有什么?)。 大规模部署不希望在每次 API 调用时都执行数据库查找,因此他们会发布可通过解密验证的自编码访问令牌。但是,这也意味着无法撤销这些令牌,因此它们会在短时间内发行,并且必须刷新。 刷新令牌需要客户端身份验证,这使其更强大。与上述访问令牌不同,它通常通过数据库查找来实现。

假设我们不支持访问令牌的非加密传输处理第一个要点。

假设我们可以针对可撤销的、完全随机的访问令牌进行数据库查找来处理第二个访问令牌。

对于移动应用,客户端认证不能再强了,因为“注册时获取的client_id和client_secret是嵌入到你的应用程序源代码中的。在这种情况下,client_secret显然不被视为秘密。” (Google)。这消除了第三个问题。

那么在这种情况下分离短期访问令牌和长期刷新令牌有什么好处?只发布未过期的访问令牌并忽略整个刷新令牌部分是否“可以”?​​p>

【问题讨论】:

【参考方案1】:

刷新令牌和未过期的访问令牌在安全方面的区别在于对授权服务器的额外调用。

如果攻击者获得了您未过期的访问令牌的访问权限,他可以直接调用您的资源服务器并获取机密数据作为响应。 现在,如果他窃取了您的刷新令牌,他首先必须调用授权服务器并接收访问令牌作为响应。然后他可以向资源服务器查询机密数据。

每次使用刷新令牌从您的授权服务器请求访问令牌时,OAuth 2 规范(至少是目前的最新草案)都要求服务器提供check the client identity and if it is bound to the token,如果可能的话。

由于使用客户端密码的常规方法无法明确识别开放平台上已安装的应用程序,因此运行应用程序的平台必须提供执行此操作的方法。谷歌例如要求开发者对 android 应用程序进行签名。因此,当使用 Google API Console 为 Android 应用程序请求凭据时,您必须指定 the fingerprint of the certificate you used for signing the application 并且仅获取客户端 ID,但没有秘密响应。在颁发令牌时,Google 可以决定应用程序是否已获得开发人员的授权,可以以他的名义请求令牌。

如果您确实无法验证客户端身份,那么至少在某些情况下可以识别出刷新令牌被盗。该规范有一个example for this:

当无法进行客户端身份验证时,授权服务器应该部署其他方法来检测刷新令牌滥用。

例如,授权服务器可以使用刷新令牌轮换,其中每次访问令牌刷新响应都会发出一个新的刷新令牌。先前的刷新令牌已失效,但由授权服务器保留。如果刷新令牌被破坏并随后被攻击者和合法客户端使用,其中一个将提供一个无效的刷新令牌,这将通知授权服务器违规行为。

【讨论】:

“在发行令牌时,Google 可以决定应用程序是否已获得开发人员的授权以他的名义请求令牌。”他们是怎么做到的? Android 操作系统是否以某种方式位于应用程序和网络之间,保证应用程序已正确签名? 在 Android 上,您可以使用 AccountManager 类来处理令牌和授权,Google 的服务已经内置在其中。我不认为他们已经在使用应用程序签名检查,而是使用客户端凭据方法。签名检查在Google I/O 2012 talk by Yaniv Inbar 中公布,有趣的部分在10:41。 项目名为Google Play Services。 查看此处建议的代码,以便从代码中检索您的 Android 证书指纹,以便进行客户端验证***.com/questions/9293019/… @lapin SSL/TLS 仅在传输过程中保护令牌。攻击者还有很多其他方法可以访问这些方法,例如设备上的实施错误、不正确的存储或根漏洞。这一切都是为了向您的layered defense 添加更多层。【参考方案2】:

OAuth2 访问令牌不必过期(或者更确切地说,它们确实会过期,但之后可能会过期很多年)。

访问令牌可用于一次从资源服务器获取某些资源,特别是它允许获取用户批准的那些资源。另一方面,刷新令牌允许重复访问。因此,如果不要求每次访问之间的用户交互,就无法取消刷新令牌。

一般来说,令牌有时会被同一设备上的其他恶意应用程序或手机上的 MITM 攻击窃取。如果可以使电话信任不可靠的证书,则 SSL 是 MITM-able。公司有时需要这样做才能访问内部网络(他们需要接受自签名证书,这允许他们对公司网络上发生的所有加密流量进行 MITM。因此假设发送加密的令牌意味着它们在途中不会被盗是危险。

不记名令牌本身并不比任何其他形式的令牌弱,正如一堆论文中所证明的那样(包括我自己的一篇,我会在我可以挖掘出来的时候发布链接。)但是,不记名令牌仅适用于它们做出的假设有效的情况。令牌可以保密的假设通常是不记名令牌的主要假设。如果这不是真的,那么不记名令牌不会声明任何安全属性(尽管有些仍然持有)。请参阅NIST Level 3 tokens,它定义了承载令牌必须击败的攻击,如OAuth Bearer Tokens 中所述。简而言之,不记名令牌不应该阻止令牌被盗。

不记名令牌不能被撤销,这是真的。然而,鉴于通常的访问模式是在获取后立即使用访问令牌,因此即使当前无法想到滥用案例,也应该相当快地使访问令牌过期以防止潜在的滥用。代币存在的时间越长,被盗的可能性就越大。刷新令牌实际上被盗更危险,因为如果您无法保护客户端 ID,它会在更长的时间范围内提供重复访问。 OAuth2 通常可以提供对资源的访问,因此例如可以用于将 API 公开给客户端一段时间。与单次使用令牌相比,使用刷新令牌可以造成更大的伤害。

实际上可以通过多种方式使客户端身份验证更加安全,例如,在下载时为每个客户端提供不同的密钥。这可以防止在一个设备上对令牌进行逆向工程破坏客户端所有实例的安全性的普遍攻击。其他潜在的技术包括使用 OAuth 来验证客户端与您的服务器,然后使用您希望访问的授权服务器执行 OAuth 协议的第二次运行。这样,您就可以让客户端定期更新其密钥,并让它们都拥有不同的密钥,同时不会对 Facebook 或 Google 拥有的授权服务器所使用的系统造成过度负担。

在使用移动应用时,长期刷新令牌比拥有某种多用途不记名令牌更安全,即使没有采取措施保护客户端。这是因为用户不能使令牌过期。如果刷新令牌没有被盗,并且用户只是希望撤销访问,那么可以这样做。即使用户只是希望撤销访问权限,也不能撤销多用途不记名令牌。多用途数据库引用令牌显然可以被撤销,但这不是协议的设计目的,因此对 OAuth 执行的安全分析并没有说明这个混合系统的安全性。

总之,我建议使用刷新令牌和数据库令牌,因为这最有可能是安全的。如果您可以做任何事情来保护客户,那将是一个额外的好处,但是这可以防止的情况很少。如果您确实想保护客户端的安全,请考虑使用软令牌(la google 身份验证器),因为这是一个可靠的实现,经受住了一些非常聪明的人的分析。

【讨论】:

“一个访问令牌可以使用一次”:你有那个链接吗?我的理解是可以无限次使用直到过期。 “不记名令牌不能撤销,这是真的。”:为什么?如果令牌由数据库中的条目支持,则可以删除该条目。 根据定义,不记名令牌包含从资源服务器访问资源所需的所有信息,而无需检查数据库。这就是不记名令牌的意义所在,它就像一张钞票,只需拥有就足够了,无需进一步验证。如果您正在检查数据库,则它不再是不记名令牌。访问令牌可以使用一次的事实可以从它包含随机数或单次使用值的事实中得出。一些当前的实现不检查这一点,但从技术上讲,它们不符合规范。 如何在没有数据库的情况下检查一次性值?你不需要存储你看到的随机数吗? 是和不是。显然,您确实需要存储所见随机数的数据库,但是昂贵的数据库调用是资源服务器必须与身份验证服务器确认数据时。资源服务器在内部存储看到的 nonce,因此具有非常快速廉价的查找(尤其是在使用类似树结构的 nonce 时。)【参考方案3】:

未过期的访问令牌的最大问题是没有机制来替换被盗的令牌。如果我可以访问您的未过期访问令牌,那么我实际上就是该系统的您。如果令牌是短暂的并且过期了,那么有一种机制可以替换被盗的令牌,并且限制了我必须破解您的令牌的窗口。

假设我需要 3 个小时来破解一个数据包并获取令牌,但访问令牌只有两个小时有效。然后,当我无法侵入您的帐户时,令牌已更改,我必须重新开始。如果令牌未过期,那么我可以完全访问您的帐户,您无法替换它,除非删除令牌并强制重新授权。

【讨论】:

但是同样的问题不也适用于刷新令牌,它的发行、存储和使用方式与访问令牌相同,并且不会很快过期吗?那么额外的安全性从何而来?这种长寿命刷新令牌的存在是否完全破坏了访问令牌短寿命的好处? 刷新令牌仅用于获取新的访问令牌,因此暴露较少。刷新令牌仅在 SSL 加密消息的正文中发送,从不在标头中发送。并且刷新令牌还需要 client_id 和 client_secret 进行额外的身份验证。因此,与访问令牌相比,刷新令牌被泄露的风险更小。 在问题中我已经假设只使用 SSL。此外,client_id 和 client_secret 是移动设备流程中的公共信息。老实说,在这种情况下,我真的看不出刷新令牌比访问令牌更安全(除了它每三十分钟而不是每三十秒使用一次)。 “如果我可以访问您的未过期访问令牌”,那么您不会因为 SSL 开启。因此,从那时起任何进一步的讨论都是无用的。

以上是关于移动应用程序的 OAuth2 访问令牌是不是必须过期?的主要内容,如果未能解决你的问题,请参考以下文章

每个 refreshToken 的 OAuth2 访问令牌限制

客户端是不是应该使用 GET 或 POST 获取 OAuth 2 访问令牌?

了解 Google OAuth2 刷新令牌

什么是移动应用程序的正确 OAuth 2.0 流程

Spring oauth2 验证令牌请求

如何安全地存储 Discord(OAuth2) 用户的访问令牌?