根据我的理解,为了Site-A从Site-B访问用户的信息,OAuth 2中发生了以下一系列事件。

Site-A registers on Site-B, and obtains a Secret and an ID. When User tells Site-A to access Site-B, User is sent to Site-B where they tell Site-B that they would indeed like to give Site-A permissions to specific information. Site-B redirects User back to Site-A, along with an Authorization Code. Site-A then passes that Authorization Code along with its Secret back to Site-B in return for a Security Token. Site-A then makes requests to Site-B on behalf of User by bundling the Security Token along with requests.

在高水平上,所有这些在安全和加密方面是如何工作的?OAuth 2如何使用安全令牌防止重放攻击?


当前回答

这是一块宝石:

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

非常简短的总结:

OAuth定义了四个角色:

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

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

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

其他回答

OAuth是一种协议,第三方应用程序可以在不需要您的帐户和密码的情况下访问存储在另一个网站上的数据。有关更正式的定义,请参考Wiki或规范。

下面是一个用例演示:

我登录领英,想联系我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的细节。

这里可能是OAuth2如何为所有4种授权类型工作的最简单的解释,即应用程序可以获得访问令牌的4个不同的流。

相似

所有授权类型流都有两部分:

获取访问令牌 使用访问令牌

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

区别

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

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

预先注册你的应用(客户端)与OAuth提供商,例如,Twitter等,以获得客户端id/秘密 在你的页面上创建一个带有客户端id和所需范围/权限的社交登录按钮,这样当点击用户时就会被重定向到OAuth提供者进行身份验证 OAuth提供商请求用户授予你的应用(客户端)权限 OAuth提供者发布代码 App(客户端)获取访问令牌

下面是一个并排的图表,比较了基于5个步骤的每个拨款类型流程的不同。

这个图表来自https://blog.oauth.io/introduction-oauth2-flow-diagrams/

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

客户端凭证:如果你的应用程序只服务于一个用户

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

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

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

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

这是一块宝石:

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

非常简短的总结:

OAuth定义了四个角色:

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

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

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

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

首先,OP描述的访问方案只适用于OAuth 2.0 -授权码授予提供的一个流。还有其他的流动。所有流的一个共同特征是,作为成功身份验证的结果,客户端会收到一个访问令牌。

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

所以你需要做什么:

Use signed JWT as your tokens. Use a very short expiration time for access tokens, 10 minutes is enough in my opinion. Your authorization server must issue refresh tokens, which is generally optional according to the standard. The expiration time of refresh tokens should not be too long, for each situation it should be solved differently, for example, for a website, I would set it a little longer than a normal user session. You can also implement session expiration when the user is idle, but this applies to the application logic and is not provided for by the standard (this is a fairly simple mechanism, but it's out of the scope of the question). You must store issued refresh tokens in the authorization server database. However, you don't have to store access token data to take advantage of self-contained JWTs. It is advisable to store data about refresh tokens during the lifetime of the session, that is, until the time when the refresh token expires (in fact, it will not be one token, but a family - more on that below). Take general measures to protect against token/session theft, they are probably well-known, among them are the following: use only a secure connection; if you store tokens on the end user side using cookies, set cookie flags to protect them, more details here; implement protection against cross-site request forgery (CSRF), more details here. (Now the most interesting part begins) Implement refresh token rotation. This means that every time a client uses a refresh token to get a new access token (because the access token has expired), a new refresh token must be issued along with the new access token, and the old refresh token must be invalidated. It could just be a flag in the database indicating that the refresh token is invalid. Each time the authorization server issues a refresh token, it must add to it (among other required/recommended) the following claims: jti with a unique token id and a private claim with any unassigned public name, e.g. fid with unique token family id (within one session). For example, refresh token 1 had jti 3c30a712-247b-4091-b692-8c3e92b83bb2, fid 4eb44450-84e9-4fbc-830e-33935e20f7e6, after issuing refresh token 2 instead of refresh token 1, it might have a new jti f467cf40-8cd7-485e-8711-b5c657832fc6 but will have the same fid 4eb44450-84e9-4fbc-830e-33935e20f7e6. You keep holding the entire refresh token family in the database until the last one, the one that is still valid, becomes invalid, for example, until it expires. *You can do without the fid claim, then you will have to link the entire chain / family of refresh tokens issued within the same session using relational database mechanisms. Implement an absolute expiration time for refresh tokens. Each time, when the authorization server within the same session issues a new refresh token instead of the previous refresh token, the value of its exp claim should not exceed the expiration time of the very first refresh token. For example, if refresh token 1 had a value of 1643384057 for exp claim, then each subsequent refresh token, for example refresh token 5, should also contain the same value 1643384057 in the exp claim. Implement refresh token replay (reuse) detection. Perhaps you have already guessed what to do next. Each time the authorization server receives a request to issue an access token, the authorization server, among other things, must check whether the presented refresh token is one from an existing chain / family and is not marked invalid. If an authorization server receives an invalidated refresh token that is in a family that has a valid (latest) refresh token, it MUST invalidate the most recent refresh token (no valid tokens left) and MUST refuse to issue an access token.

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

The token/session was used by the attacker before, at the request of a legitimate user, the client requested the issuance of new access and refresh tokens. That is, the attacker managed to do it first. Then, at the next request of a legitimate user, the client will send an invalid refresh token to the authorization server (because the attacker made the request earlier and the legitimate user's refresh token was invalidated). The session will be invalidated. The token/session was used by a legitimate user, and the stolen token/session was later used by an attacker. In this case, the same thing will happen - the session will be invalidated, I think this is understandable. It is possible that after the token/session was stolen, the legitimate user did not send any more requests, then the attacker will have access until the absolute expiration of the refresh token (see point 9).

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

了解这是如何工作的,您应该选择与令牌过期相关的值,这些值与您的项目相关。

我建议您深入研究相关标准,以及OAuth 2.0安全性最佳当前实践。在那里您还可以找到令牌重放预防部分。

另一个答案非常详细,解决了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):)中显示

客户端应该使用承载令牌进行身份验证请求 “授权”请求头字段与“承载”HTTP 授权方案。 ... 不应该使用"application/x-www-form-urlencoded"方法 除非在应用程序上下文中,其中参与的浏览器不这样做 可以访问“授权”请求头字段。 ... URI查询参数…用于记录当前使用情况;它的用途不是 推荐,由于其安全性不足