站点A
能够从站点B
访问用户的信息,以下事件链将会发生:
站点A
在站点B
上注册,并获得一个密钥和一个标识符。- 当用户告诉
站点A
要访问站点B
时,用户被发送到站点B
,并告诉站点B
他们确实想授予站点A
对特定信息的权限。 站点B
将用户重定向回站点A
,同时附带一个授权码。站点A
然后将该授权码与其密钥一起传递回站点B
,以换取安全令牌。站点A
随后将安全令牌与请求捆绑在一起,代表用户向站点B
提出请求。
站点A
能够从站点B
访问用户的信息,以下事件链将会发生:
站点A
在站点B
上注册,并获得一个密钥和一个标识符。站点A
要访问站点B
时,用户被发送到站点B
,并告诉站点B
他们确实想授予站点A
对特定信息的权限。站点B
将用户重定向回站点A
,同时附带一个授权码。站点A
然后将该授权码与其密钥一起传递回站点B
,以换取安全令牌。站点A
随后将安全令牌与请求捆绑在一起,代表用户向站点B
提出请求。OAuth 2.0在现实生活中的应用:
我上班路过Olaf面包店时,看到了橱窗里最美味的甜甜圈——它滴着巧克力酱,让人垂涎欲滴。于是我走进去,要求买下那个甜甜圈!他说:“好的,价钱是30美元。”
是的,我知道,一只甜甜圈竟然卖30美元!一定很好吃吧!我拿出钱包时,突然听到主厨大喊:“不可以!你不能买这个甜甜圈!” 我问为什么?他说他只接受银行转账。
真的吗?是的,他说得很认真。我当时差点就走了,但是这个甜甜圈叫唤着我:“请享用我,我非常美味……”我怎么能违抗一个甜甜圈的命令呢?于是我答应了。
他递给我一张写有他名字的纸条(是主厨的名字,不是甜甜圈的),上面写着“告诉他们是Olaf派你来的”。上面已经有他的名字了,我不知道为什么还要这样写,但是好吧。
我驱车一个半小时到达我的银行。我把纸条交给了出纳员,告诉她Olaf派我来的。她瞪了我一眼,那种意味深长的眼神,就好像在说:“我会读懂的。”
她拿走我的纸条,要求我出示身份证,并问我打算汇多少钱给他。我告诉她30美元。她做了些记录,递给了我另一张纸条。上面有一堆数字,我猜那是他们追踪订单的方式。
当时我已经饿极了。我匆匆离开银行,在一个半小时之后回到Olaf面前,递给他我的纸条。他拿过去看了一下,说:“我待会儿回来。”
我以为他去拿我的甜甜圈,但是等了30分钟后我开始怀疑。于是我问柜台后面的人:“Olaf去哪里了?”他说:“他去取钱了。”“什么意思?”“他带着纸条去银行了。”
哦,原来 Olaf 拿了银行给我的便条回到银行里取钱。既然他有那张银行给我的便条,银行就知道他是我说的那个人,而且因为我已经和银行交谈过了,所以他们知道只要给他 30 美元。根据我所了解的,这就是整个流程:
问题中概述的一般流程是正确的。在第2步中,用户X将被认证,并授权站点A访问其在站点B上的信息。在第4步中,该站点将其密钥传回站点B,对自身进行认证,以及授权码,表示它正在请求什么(用户X的访问令牌)。
总体而言,OAuth 2实际上是一个非常简单的安全模型,加密没有直接参与其中。相反,密钥和安全令牌本质上都是密码,整个过程仅由https连接的安全性保护。
OAuth 2没有保护安全令牌或密钥的重放攻击。相反,它完全依赖于站点B对这些项目的负责和不让它们泄漏,以及在传输过程中通过https发送它们(https将保护URL参数)。
授权代码步骤的目的只是为了方便,授权代码本身并不特别敏感。当要求站点B提供用户X的访问令牌时,它为站点A提供了一个公共标识符。仅使用站点B上的用户X用户ID将无法起作用,因为可能有许多未解决的访问令牌正在等待同时交给不同的站点。
OAuth是一种协议,允许第三方应用在没有您的账号和密码的情况下访问另一个网站上存储的数据。如需更正式的定义,请参考Wiki或规范。
以下是一个使用案例演示:
我登录LinkedIn并想要连接一些在我的Gmail联系人中的朋友。 LinkedIn支持此功能。它将从Gmail请求安全资源(我的Gmail联系人列表)。 因此,我单击此按钮:
弹出一个网页,显示Gmail登录页面,当我输入我的账号和密码时:
Gmail随后显示同意页面,我点击“接受”:
现在LinkedIn可以访问我的Gmail联系人:
以下是上述示例的流程图:
步骤1:LinkedIn从Gmail的授权服务器请求令牌。
步骤2:Gmail授权服务器验证资源所有者并显示同意页面。(如果用户尚未登录Gmail,则需要登录)
步骤3:用户授予LinkedIn访问Gmail数据的请求。
步骤4:Gmail授权服务器用访问令牌回复。
步骤5:LinkedIn使用此访问令牌调用Gmail API。
步骤6:如果访问令牌有效,则Gmail资源服务器返回联系人。(Gmail资源服务器将验证令牌)
您可以在这里获取有关OAuth的更多详细信息。
图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 ---| |
+--------+ +---------------+
下面是 OAuth 2.0 的工作原理,这篇文章有详细解释。
这是一篇宝贵的资料:
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
非常简要的概述:
OAuth 定义了四个角色:
你(资源拥有者)有一个手机。你有几个不同的电子邮件账户,但你想把所有的电子邮件账户都放在一个应用程序中,这样你就不需要不停地切换。因此,你的 GMail(客户端)请求访问(通过 Yahoo 的授权服务器)你的 Yahoo 邮件(资源服务器),以便你可以在 GMail 应用程序中读取两封邮件。
OAuth 存在的原因是为了避免 GMail 存储你的 Yahoo 用户名和密码造成不安全的情况。
令牌的短暂过期时间是防范以下威胁的一种手段:
- 重放攻击...
客户端应该使用带有“Bearer” HTTP授权方案的“Authorization”请求头字段和令牌对进行认证请求。
除非参与浏览器没有访问“Authorization”请求头字段的应用程序上下文,否则不应使用“application/x-www-form-urlencoded”方法。
URI查询参数包含在文档中以记录当前使用情况;由于其安全性缺陷,不建议使用它。
jti
具有唯一的令牌ID和任何未分配的公共名称的私有声明,例如具有唯一令牌家族ID(在一个会话内)。例如,刷新令牌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
声明,然后您将不得不使用关系数据库授权服务器不能知道谁是合法用户,谁是攻击者,所以在这种情况下,最后一个(有效的)刷新令牌始终被作废,使会话过期/无效。在此之后,合法用户可以通过输入密码来验证自己的身份,而攻击者则不能。
了解这是如何工作的,您应选择与您的项目相关的令牌过期值。
我建议您深入了解相关标准以及OAuth 2.0安全最佳实践。在那里,您还将找到令牌重放预防部分。
OAuth2本身并不能防止重放攻击。然而,有一些“扩展”如MTLS或DPoP可以用来增加安全性。您可以在https://marcinjahn.com/technologies/security/oauth2/sender-constraint.html了解更多信息。
code
),但是在OAuth 2.0中还定义了其他授权类型,适用于不同的用例(例如非用户相关的用例)。 - Hans Z.