ChatGPT解决这个技术问题 Extra ChatGPT

OAuth 2 如何使用安全令牌防止诸如重放攻击之类的事情?

据我了解,为了让 Site-ASite-B 访问 用户 信息,OAuth 2 中发生了以下事件链。

Site-A 在 Site-B 上注册,并获得一个 Secret 和一个 ID。当用户告诉站点 A 访问站点 B 时,用户将被发送到站点 B,在那里他们告诉站点 B 他们确实希望授予站点 A 对特定信息的权限。站点 B 将用户重定向回站点 A,并附有授权代码。然后,站点 A 将该授权代码连同其秘密一起传递回站点 B,以换取安全令牌。然后,站点 A 通过将安全令牌与请求捆绑在一起,代表用户向站点 B 发出请求。

所有这些在安全和加密方面是如何工作的? OAuth 2 如何使用安全令牌防止诸如重放攻击之类的事情?

oauth2 在这里简单解释:gist.github.com/mziwisky/10079157
阅读规范:tools.ietf.org/html/rfc6749您可能会惊讶于它的易懂程度。这也是正确的,可能还不错。
这个问题及其(当前)答案都集中在 OAuth 2.0 中的一种特定“授权类型”(即 code),但 OAuth 2.0 中定义了与不同用例相关的其他授权类型(例如非用户相关的授权类型) )。
哦,为什么不用像“IdProvider Site”这样更易读的东西来代替“Site B”呢?

L
Luis Perez

OAuth 2.0 在现实生活中的工作原理:

当我在上班的路上开车经过奥拉夫的面包店时,我看到橱窗里有最美味的甜甜圈——我的意思是,那东西正滴着巧克力味。所以我进去并要求“我必须有那个甜甜圈!”。他说“当然是30美元。”

是的,我知道,一个甜甜圈30美元!一定很好吃!当我突然听到厨师大喊“不!不要给你甜甜圈”时,我伸手去拿我的钱包。我问:为什么?他说他只接受银行转账。

严重地?是的,他是认真的。我差点就走开了,但随后甜甜圈对我喊道:“吃我,我很好吃……”。我有什么资格违抗甜甜圈的命令?我说了可以。

他递给我一张纸条,上面写着他的名字(厨师,而不是甜甜圈):“告诉他们奥拉夫派你来的”。他的名字已经写在纸条上,所以我不知道这样说有什么意义,但是好吧。

我开车一个半小时到我的银行。我把纸条递给出纳员;我告诉她奥拉夫派我来的。她给了我一个这样的眼神,那种说,“我可以阅读”。

她拿了我的纸条,要了我的身份证,问我可以给他多少钱。我告诉她30美元。她潦草地写了几句,又递给我一张纸条。这个上面有一堆数字,我猜这就是他们记录笔记的方式。

那个时候我饿死了。我冲出那里,一个半小时后我又回来了,站在奥拉夫面前,我的纸条被拉长了。他接过它,看了看,说:“我会回来的。”

我以为他在拿我的甜甜圈,但 30 分钟后我开始怀疑。所以我问柜台后面的人“奥拉夫在哪里?”。他说“他去拿钱”。 “你是什么意思?”。 “他记笔记到银行”。

嗯……所以奥拉夫拿着银行给我的纸条,回到银行从我的账户里取钱。因为他有银行给我的票据,银行知道他就是我说的那个人,因为我和银行谈过,他们知道只给他 30 美元。

我肯定花了很长时间才弄清楚这一点,因为当我抬起头来时,奥拉夫终于站在我面前把我的甜甜圈递给了我。在我离开之前,我不得不问,“奥拉夫,你总是这样卖甜甜圈吗?”。 “不,我以前做的不一样。”

嗯。当我走回我的车时,我的电话响了。我懒得回答,可能是我的工作要求解雇我,我的老板就是这样的***。此外,我还在思考我刚刚经历的过程。

我的意思是想一想:我能够让奥拉夫从我的银行账户中取出 30 美元,而无需向他提供我的账户信息。而且我不必担心他会拿走太多钱,因为我已经告诉银行他只允许拿 30 美元。银行知道他是合适的人选,因为他有他们给我要给奥拉夫的纸条。

好吧,当然我宁愿从口袋里掏出 30 美元给他。但是现在他有了那张纸条,我可以告诉银行让他每周拿 30 美元,然后我可以直接出现在面包店,我不必再去银行了。如果我愿意,我什至可以通过电话订购甜甜圈。

我当然不会那样做——那个甜甜圈真恶心。

我想知道这种方法是否有更广泛的应用。他提到这是他的第二种方法,我可以称之为 Olaf 2.0。不管怎样,我还是回家吧,我得开始找新工作了。但在我从镇上的那个新地方买一份草莓奶昔之前,我需要一些东西来洗去那个甜甜圈的味道。


好吧,实际上,即使您不订购任何甜甜圈,Olaf 也应该可以随时从您的帐户中提取 30 美元。有趣的是,这是真正的 oauth2.0 场景中的主要目标 :) 这当然是一个很好的答案,但无论谁正在阅读这篇文章,请前往 Paolo 在他对问题的评论中提到的 git gist (gist.github.com/mziwisky/10079157)。一个很好的补充阅读,使概念一清二楚。
很好的答案,但要提出 2 点:1. 正如@Samiron 指出的那样,Olaf 可以随时拿 30 美元。 2. 在真正的 OAuth2.0 场景中,Olaf 在从银行取钱之前将无法提供甜甜圈。虽然在这个例子中,他本可以保留支票并简单地将他来之不易的甜甜圈递给 Luis。因此,如果我们更改示例以使我授权奥拉夫从我认识的某个第三方获取面团,那么这将更有意义,因为奥拉夫必须在开始烘烤甜甜圈之前得到面团(假设孤独的甜甜圈奥拉夫had 仅用于展示目的!)。
ticker23,不幸的是,甜甜圈的故事击败了您的技术修正——当我读到它时,我被这个故事所吸引。它是由荷马辛普森写的。
@Prageeth Olaf 总是将纸币装在一个安全的盒子里进出银行,如果被篡改,它会泄漏墨水,恢复纸币需要很多生命。银行还会在客户第一次访问时采集指纹,如果奥拉夫在一次烘焙事故中失去手指,那么他将不得不要求路易斯重新设置银行转账,银行下次必须通过他的破碎面包纹身来识别奥拉夫.
我和下一个人一样喜欢可爱的答案,当他们的可爱有助于使答案更容易获得时,那真是太棒了……但归根结底,Stack Overflow 是关于教育人们的,而这个可爱的故事并没有做到这一点。要理解甜甜圈类比,您必须已经了解 OAuth2 的工作原理,但答案的重点应该是准确地解释这一点。请考虑编辑此(顶部)答案以实际解释这些概念,而不仅仅是在最后倾斜地引用它们……即使那是以一两个笑话为代价的。
P
PeterUstinox

根据我所阅读的内容,这就是它的工作原理:

问题中概述的一般流程是正确的。在第 2 步中,用户 X 已通过身份验证,并且还授权站点 A 访问用户 X 在站点 B 上的信息。在第 4 步中,站点将其 Secret 传递回站点 B,对自身进行身份验证,以及授权代码,指示什么它要求(用户 X 的访问令牌)。

总体而言,OAuth 2 实际上是一个非常简单的安全模型,加密永远不会直接发挥作用。相反,Secret 和 Security Token 本质上都是密码,整个事情只有通过 https 连接的安全性来保护。

OAuth 2 没有针对 Security Token 或 Secret 的重放攻击的保护。相反,它完全依赖于站点 B 对这些项目负责并且不让它们离开,并且依赖于它们在传输过程中通过 https 发送(https 将保护 URL 参数)。

授权码步骤的目的只是为了方便,授权码本身并不是特别敏感。当向站点 B 询问用户 X 的访问令牌时,它为站点 A 的用户 X 的访问令牌提供了一个通用标识符。仅站点 B 上的用户 X 的用户 ID 不会起作用,因为可能有许多未完成的访问令牌等待同时分发给不同的站点。


您忽略了授权码的一个重要功能。为什么不立即返回刷新令牌(您称之为安全令牌),而不是进行交换授权代码的额外步骤?因为捕获刷新令牌将允许重放攻击,而授权码只能使用一次。
好的,@mauricen,这是有道理的....但是重播攻击不能与刷新令牌一样发生吗,因为这是每个请求最终传递的内容?
授权代码是通过用户传递的,因此(例如)可以存储为 cookie(参见 stackoverflow.com/questions/4065657/…)。刷新令牌直接在两个站点之间传递,因此不易受到攻击。
出于好奇,OAuth 是否返回任何唯一标识符供程序使用?例如,我目前依靠 MAC 地址进行用户识别,但话虽如此,MAC 是不可靠的/容易被欺骗/等等。如果它确实允许我唯一地识别用户,我可能会放弃 MAC 地址识别机制并使用 OAuth。
请注意此图中:tools.ietf.org/html/rfc6749#section-4.1 未显示“秘密”,仅显示客户端标识符(问题中的 ID)。为什么秘密很重要,为什么它没有包含在 RFC 中?同样在问题中,还有建议在客户端 ID (A) 的初始传输中传递的本地状态,以及与授权代码一起重定向回客户端以防止 XSSF。
r
rogerdpack

OAuth 是一种协议,3 方应用程序可以使用该协议访问您存储在另一个网站中的数据,而无需您的帐户和密码。有关更正式的定义,请参阅 Wiki 或规范。

这是一个用例演示:

我登录 LinkedIn 并想联系我的 Gmail 联系人中的一些朋友。 LinkedIn 支持这一点。它将从 gmail 请求安全资源(我的 gmail 联系人列表)。所以我点击这个按钮:一个网页弹出,它显示 Gmail 登录页面,当我输入我的帐户和密码时:Gmail 然后显示一个同意页面,我点击“接受”:现在 LinkedIn 可以访问我在 Gmail 中的联系人:

下面是上面例子的流程图:

https://i.stack.imgur.com/bt7k0.png

第 1 步:LinkedIn 从 Gmail 的授权服务器请求令牌。

第 2 步:Gmail 授权服务器对资源所有者进行身份验证并向用户显示同意页面。 (如果用户尚未登录,则需要登录 Gmail)

第 3 步:用户授予 LinkedIn 访问 Gmail 数据的请求。

第 4 步:Gmail 授权服务器返回访问令牌。

第 5 步:LinkedIn 使用此访问令牌调用 Gmail API。

第 6 步:如果访问令牌有效,Gmail 资源服务器会返回您的联系人。 (令牌将由 Gmail 资源服务器验证)

您可以从有关 OAuth here 的详细信息中获得更多信息。


你所有的图像都不见了。您有机会将它们加载到 stack.imgur 吗?
这怎么可能是正确的?这个过程不是由坐在浏览器前的用户发起的,而不是由LinkedIn发起的。但是您将其作为第 3 步。这是我没有得到的。
最简单的解释。谢谢,我再也不会买甜甜圈了
第四步,linkedin 返回一个授权令牌。这必须在第 5 步中提供,在这里我们将获得一个访问令牌和一个刷新令牌,它们可以进一步用于受保护的资源。
@amesh 谢谢,你是对的,这就是授权代码流程,这里我只是简单地说明了 OAuth 2 的基本思想。
C
Community

图 1,取自 RFC6750

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

S
Suraj

这就是 Oauth 2.0 的工作原理,在 this article 中有很好的解释

https://i.stack.imgur.com/Mo2wi.jpg


您能否以不使用 facebook 或其他第 3 方的方式描述 OAUTH2,但如果您使用手机应用程序的密钥和 TOTP 令牌来保护 webapp?
Facebook 是本示例中的授权服务器,它向任何客户端颁发访问令牌,以便他们可以访问 Facebook API。如果您想保护您的 API,您需要实现自己的授权服务器。然后,您决定要使用哪种授予类型来获取访问令牌。告诉我你到底想要什么?将解释。
我正在考虑使用 springboot 安全性进行设置。客户端(电话)和 webapp 在注册时交换密码 - 然后使用谷歌身份验证器生成基于时间/密码的代码,以便在登录期间输入密码和密码。
我的最后一条评论对你有启发吗?查看我的个人资料以获取 Twitter 信息
您可以在注册时获取客户 ID 和密码。然后电话向您的 webapp(授权服务器)发出带有客户端 ID 的登录请求。 Web 应用程序验证客户端 ID,并将 OTP 发送到手机。电话向 webapp 发出另一个带有客户端密码的请求,以用访问令牌交换 OTP。手机使用此访问令牌访问 webapp 上的受保护资源。我认为这将是给定场景的 Oauth2 流程。让我知道它是否对您有帮助。
B
Belfield

这是一个宝石:

https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

非常简短的总结:

OAuth 定义了四个角色:

资源所有者客户端资源服务器授权服务器

您(资源所有者)有一部手机。您有多个不同的电子邮件帐户,但您希望所有电子邮件帐户都在一个应用程序中,因此您无需不断切换。因此,您的 GMail(客户端)请求访问(通过 Yahoo 的授权服务器)您的 Yahoo 电子邮件(资源服务器),以便您可以在 GMail 应用程序上阅读这两封电子邮件。

OAuth 存在的原因是因为 GMail 存储您的 Yahoo 用户名和密码是不安全的。

https://i.stack.imgur.com/6CMie.png


C
Community

另一个答案非常详细,解决了 OP 提出的大部分问题。

详细说明,特别是为了解决 OP 的问题“OAuth 2 如何使用安全令牌防止重放攻击?”,在实施 OAuth 2 的官方建议中有两个额外的保护:

代币的有效期通常很短(https://www.rfc-editor.org/rfc/rfc6819#section-5.1.5.3):

令牌的较短到期时间是一种防止以下威胁的方法:重放...

当站点 A 使用令牌时,建议它不会作为 URL 参数显示,而是在授权请求标头字段中显示 (https://www.rfc-editor.org/rfc/rfc6750):

客户端应该使用带有“Bearer”HTTP 授权方案的“Authorization”请求标头字段使用不记名令牌发出经过身份验证的请求。 ...“application/x-www-form-urlencoded”方法不应该被使用,除非在参与的浏览器无权访问“授权”请求头字段的应用程序上下文中。 ... URI 查询参数... 用于记录当前使用情况;不推荐使用它,因为它存在安全缺陷


n
nethsix

这可能是关于 OAuth2 如何适用于所有 4 种授权类型的最简单解释,即应用程序可以获取访问令牌的 4 种不同流程。

相似

所有授权类型的流程都有 2 个部分:

获取访问令牌

使用访问令牌

第二部分“使用访问令牌”对于所有流都是相同的

区别

每种授权类型的“获取访问令牌”流程的第一部分各不相同。

但是,一般来说,“获取访问令牌”部分可以概括为 5 个步骤:

使用 OAuth 提供程序(例如 Twitter 等)预先注册您的应用程序(客户端)以获取客户端 ID/秘密 在您的页面上创建一个带有客户端 ID 和所需范围/权限的社交登录按钮,以便在单击时将用户重定向到 OAuth 提供程序以经过身份验证 OAuth 提供者请求用户向您的应用(客户端)授予权限 OAuth 提供者发出代码 应用(客户端)获取访问令牌

这是一个并排图表,比较了基于 5 个步骤的每种授权类型流程的不同之处。

此图来自 https://blog.oauth.io/introduction-oauth2-flow-diagrams/

https://i.stack.imgur.com/kC8bX.png

每个都有不同级别的实施难度、安全性和用例。根据您的需要和情况,您将不得不使用其中之一。使用哪个?

客户端凭据:如果您的应用只为单个用户提供服务

资源所有者密码凭据:这只能作为最后的手段,因为用户必须将他的凭据交给应用程序,这意味着应用程序可以做用户可以做的所有事情

授权码:获得用户授权的最佳方式

隐式:如果您的应用是移动应用或单页应用

这里有更多关于选择的解释:https://blog.oauth.io/choose-oauth2-flow-grant-types-for-app/


f
fallincode

老实说,在回答“OAuth 2 如何使用安全令牌防止重放攻击之类的事情?”的答案中,我没有找到一个答案,这是主要的问题。

首先,OP 描述的访问方案仅适用于 OAuth 2.0 - Authorization Code Grant 提供的流程之一。还有其他流量。所有流程的共同特征之一是,作为成功认证的结果,客户端会收到一个访问令牌

如何保护自己免受重放攻击?这是可能的(有一些保留),但您需要了解,首先,这需要一套措施(如下所述),其次,您不能仅 100% 保护自己免受此类攻击,有时您可以立即阻止未经授权的访问尝试,有时您只能在发生此类攻击时缩短其持续时间。

那么你需要什么:

使用签名的 JWT 作为您的令牌。对访问令牌使用非常短的到期时间,我认为 10 分钟就足够了。您的授权服务器必须发出刷新令牌,根据标准,这通常是可选的。刷新令牌的过期时间不宜过长,对于每种情况应该以不同的方式解决,例如,对于一个网站,我会将它设置为比普通用户会话长一点。您还可以在用户空闲时实现会话过期,但这适用于应用程序逻辑并且标准未提供(这是一种相当简单的机制,但超出了问题的范围)。您必须将发布的刷新令牌存储在授权服务器数据库中。但是,您不必存储访问令牌数据即可利用自包含 JWT。建议在会话的生命周期内存储有关刷新令牌的数据,即直到刷新令牌过期(实际上,它不会是一个令牌,而是一个系列 - 更多内容如下)。采取一般措施来防止令牌/会话盗窃,它们可能是众所周知的,其中包括:仅使用安全连接;如果您使用 cookie 在最终用户端存储令牌,请设置 cookie 标志以保护它们,更多详细信息请点击此处;实施针对跨站点请求伪造 (CSRF) 的保护,更多详细信息请点击此处。 (现在最有趣的部分开始了)实现刷新令牌轮换。这意味着每次客户端使用刷新令牌获取新的访问令牌时(因为访问令牌已过期),新的刷新令牌必须与新的访问令牌一起发出,并且旧的刷新令牌必须失效。它可能只是数据库中的一个标志,表明刷新令牌无效。每次授权服务器发布刷新令牌时,它必须向其中添加(以及其他必需/推荐的)以下声明:具有唯一令牌 ID 的 jti 和具有任何未分配公共名称的私有声明,例如具有唯一令牌系列 ID 的 fid (一次会议内)。例如,刷新令牌 1 具有 jti 3c30a712-247b-4091-b692-8c3e92b83bb2,fid 4eb44450-84e9-4fbc-830e-33935e20f7e6,在发出刷新令牌 2 而不是刷新令牌 1 之后,它可能具有新的 jti f467cf40-8cd7- 485e-8711-b5c657832fc6 但将具有相同的 fid 4eb44450-84e9-4fbc-830e-33935e20f7e6。您一直在数据库中保留整个刷新令牌系列,直到最后一个(仍然有效的)变为无效,例如,直到它过期。 *您可以不使用 fid 声明,然后您必须使用关系数据库机制链接在同一会话中发布的整个刷新令牌链/系列。为刷新令牌实现绝对过期时间。每次,当同一会话中的授权服务器发出新的刷新令牌而不是先前的刷新令牌时,其 exp 声明的值不应超过第一个刷新令牌的到期时间。例如,如果刷新令牌 1 的 exp 声明值为 1643384057,则每个后续刷新令牌(例如刷新令牌 5)在 exp 声明中也应包含相同的值 1643384057。实施刷新令牌重放(重用)检测。也许您已经猜到下一步该做什么了。每次授权服务器接收到发布访问令牌的请求时,授权服务器必须检查所提供的刷新令牌是否来自现有链/家族并且未被标记为无效。如果授权服务器接收到无效的刷新令牌,该令牌属于具有有效(最新)刷新令牌的系列,则它必须使最近的刷新令牌无效(没有剩余有效令牌)并且必须拒绝发出访问令牌。

当攻击者窃取令牌/会话并尝试重用它时会发生什么。有几种情况:

攻击者之前使用了令牌/会话,应合法用户的请求,客户端请求发布新的访问和刷新令牌。也就是说,攻击者首先设法做到了。然后,在合法用户的下一次请求时,客户端将向授权服务器发送一个无效的刷新令牌(因为攻击者较早地提出了请求,并且合法用户的刷新令牌已失效)。会话将失效。令牌/会话被合法用户使用,被盗的令牌/会话后来被攻击者使用。在这种情况下,同样的事情也会发生——会话会失效,我认为这是可以理解的。有可能在令牌/会话被盗后,合法用户没有再发送任何请求,那么攻击者将可以访问,直到刷新令牌绝对到期(见第 9 点)。

授权服务器无法知道谁是合法用户,谁是攻击者,因此在这种情况下,最后一个(有效的)刷新令牌总是无效的,从而使会话过期/无效。之后,合法用户可以通过输入密码来验证自己的身份,而攻击者则不能。

了解其工作原理后,您应该选择与您的项目相关的令牌到期相关的值。

我建议您更深入地了解 related standards 以及 OAuth 2.0 Security Best Current Practice。您还会在此处找到 Token Replay Prevention section


m
mnj

OAuth2 本身并不能保护您免受重放攻击。但是,可以使用 MTLS 或 DPoP 等“扩展”。您可以在 https://marcinjahn.com/technologies/security/oauth2/sender-constraint.html 了解更多信息


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅