ChatGPT解决这个技术问题 Extra ChatGPT

Facebook OAuth 2.0“代码”和“令牌”

为什么您需要 Facebook OAuth2 身份验证流程中的“代码”和“令牌”,如下所述:https://developers.facebook.com/docs/authentication/

如果您查看 OAuth 对话框参考 (https://developers.facebook.com/docs/reference/dialogs/oauth/),您似乎只使用令牌来获取有关用户的信息,如果您将 response_type 参数指定为 tokencode,token,那么您第一时间拿到token。

为什么需要获取“代码”,然后使用代码获取“令牌”而不是直接获取令牌?

我想我误解了有关 OAuth 工作原理的一些基本知识,但如果您第一次通过对话框获得令牌,您似乎完全避免了对 https://graph.facebook.com/oauth/access_token 的请求。


r
rofrol

让我们举一个简单的例子来区分身份验证代码和访问令牌。

作为用户,您想尝试一个名为 Highjack 的新 Facebook 应用程序。因此,您单击该应用程序,Highjack 应用程序会要求您登录您的 Facebook 帐户。完成后,Facebook 会为您生成一个验证码。

然后将此代码传递给使用其自己的 FB 客户端 ID、FB 密码和您的身份验证代码的 Highjack 服务器来获取访问令牌。

在上面的示例中,身份验证代码确认您作为用户是有效的 FB 用户。但是第二步说“作为 FB 用户,您正在授予对某些资源的 Highjack 应用程序的访问权限”。

如果 Highjack 应用程序需要隐式授权(即直接访问令牌),那么您也可以看到访问令牌,因为它正在与浏览器进行交换。这意味着您现在可以使用访问令牌代表 Highjack 调用所有 Facebook API。 (您只能使用访问令牌来获取您的个人信息,但 Facebook 无法知道谁在调用他们的 API。)

由于我们有 2 方(您和 Highjack)使用 Facebook 进行身份验证,因此我们有这种 2 折机制。


一个非常干净的描述!
您是否有一个现实世界的场景,即 Highjack 不希望用户代表它调用 Facebook api?对于一个简单的“使用 Facebook 登录”用例,两种方式都可以,因为 Highack 的服务器只需要来自用户的令牌来检查它是否有效并获取用户的 Facebook id(在数据库中找到它)。在这种情况下,令牌是否也在用户手中并不重要(此令牌的唯一权限是询问“用户的 Facebook id 是什么?”)。正确的?
对此解释有一个澄清,以避免误解。此 OAuth2 流程由两个步骤组成,不是将用户身份验证和客户端授权分开,而是出于安全原因。这是这两个步骤(授权码获取和访问令牌获取)分离的最重要原因。请看下面来自“Michael R”的答案以及 Nate Barbettini 的精彩视频。
@Oren 当第三方想要查看用户分析时,即有人在社交刀片上查看其他人的分析,社交刀片需要访问所述用户分析并且用户不在身边为他们提供访问令牌,因此长期令牌是由社交刀片获取以换取用户的短期令牌并存储在他们的数据库中,因此社交刀片可以随时访问,而无需用户登录 Facebook 并授予他们访问权限(我猜这就是它的工作原理)
对不起,这个答案不是很完整。它没有提到迈克尔 R 回答中的视频中提到的“前通道”和“后通道”之间的重要安全差异。
D
Drew

无耻地从 Salesforce Documentation 借来的:

授权码

授权代码是代表用户访问权限的短期令牌,由授权服务器创建并通过浏览器传递给客户端应用程序。客户端应用程序将授权代码发送到授权服务器以获取访问令牌和可选的刷新令牌。

访问令牌 客户端使用访问令牌代表最终用户发出经过身份验证的请求。它的生命周期比授权代码长,通常为几分钟或几小时。当访问令牌过期时,尝试使用它会失败,并且必须通过刷新令牌获取新的访问令牌。


为什么同时使用两者?各有什么优势?仅仅是因为有生之年吗?请您稍微扩展一下这个答案,因为它并没有真正回答 OP。
@Anoyz,他们有不同的目的。 Web 应用程序需要 Authorization Code 来从授权服务器获取 Access Token,并且它需要 Access Token 来验证其对用户资源的访问权限。
只是从官方网站复制定义根本没有意义。请告诉我们为什么需要授权码来获取访问令牌而不是直接获取访问令牌的原因。
请看下面我的回答,希望对您有所帮助。
@arganzheng 因为如果我们只有一个令牌,这意味着如果有人截获了该令牌,那么他们可以随时随地使用它。但是,当将短期令牌传递给客户端时,客户端随后将使用客户端 id 和客户端机密来传递短期令牌以进行授权,然后才将正确的访问令牌返回给客户端。将其视为进入 1 把锁的 2 把钥匙。
C
Community

OAuth 2.0 Spec

授权代码提供了一些重要的安全优势,例如验证客户端的能力,以及将访问令牌直接传输到客户端而不通过资源所有者的用户代理传递它,从而可能将其暴露给其他人,包括资源所有者.

所以,基本上 - 主要原因是限制获得访问令牌的参与者的数量。

“令牌”响应主要用于浏览器中的客户端(例如:JavaScript 客户端)。


只是为了限制演员的数量??和保护博览会??增加的复杂性真的有意义吗?
那和客户端身份验证。更多背景:tools.ietf.org/html/…
该代码是一种不将 app_secret 写入 JS 客户端的方法。客户端请求代码,将代码发送到请求令牌的 API。将令牌存储在本地并将您的 app_secret 保存到服务器端。远离攻击者。这是安全的又一步。
这并不能回答您为什么要使用 response_type: 'code token' 的问题
r
rofrol

如果您查看flow of Authorization Code OAuth type,是的,有两个精算步骤:

=> 授权码 => access_token, refresh_token

在第 1 步中:用户告诉 OAuth 服务器“我想验证此客户端 (client_id) 以访问我的资源。这是我的验证 (user_session_id 或其他什么)”

在第 2 步中:客户端 (client_id) 告诉 OAuth 服务器“我已获得用户授权 (authorization_code),请给我一个访问令牌以供以后访问。这是我的身份验证 (client_id & ; client_secret)"

你看,如果我们省略第 2 步,则无法保证客户端身份验证。任何客户端都可以使用不同的 client_id 调用 step1 并获取该 client_id 而不是自己的访问令牌。这就是为什么我们需要第二步。

如果你真的想结合 step1 和 step2,你可以这样做:

<client_id, redirect_uri, client_secret> => access_token, refresh_token

我们在我们的开放 API 平台中使用了这种方法,我们还没有发现任何安全问题。

顺便说一句,实际上有一个Implicit Grant type,即:

<client_id, redirect_uri> => access_token, refresh_token

它通常适用于没有服务器后端的仅客户端应用程序。在这种情况下,OAuth 服务器必须确保重定向 URI 属于该客户端(例如,与寄存器 redirect_uri 相同)。


C
Community

混淆是因为用户代表他自己而不是客户端应用程序对授权服务器(即facebook)进行身份验证。保护客户端应用程序(使用 https)然后保护用户代理(浏览器)非常简单。

以下是 IETF-oauth (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-threatmodel-08#section-3.4) 的原始表述:

3.4.授权码

授权码代表成功的最终用户授权过程的中间结果,并被客户端用于获取访问和刷新令牌。授权码被发送到客户端的重定向 URI 而不是令牌有两个目的。

基于浏览器的流通过 URI 查询参数(HTTP 引荐来源网址)、浏览器缓存或日志文件条目向潜在攻击者公开协议参数,并且可以重放。为了减少这种威胁,使用短期授权代码而不是令牌,并通过客户端和授权服务器之间更安全的直接连接交换令牌。在客户端和授权服务器之间的直接请求期间对客户端进行身份验证比在间接授权请求的上下文中简单得多。后者需要数字签名。


M
Michael R

答案)您需要/想要代码和令牌以获得额外的安全性。

根据 Nate Barbettini 的说法,我们需要额外的步骤来交换访问令牌的身份验证码,因为身份验证码可以在前端通道中使用(不太安全),而访问令牌可以在后端通道中使用(更安全) .

因此,安全优势在于访问令牌不会暴露给浏览器,因此无法从浏览器中拦截/获取。我们更信任网络服务器,它通过反向渠道进行通信。访问令牌是秘密的,然后可以保留在 Web 服务器上,并且不会暴露给浏览器(即前端通道)。

有关更多信息,请观看这个精彩的视频:

OAuth 2.0 和 OpenID Connect(简单英语) https://youtu.be/996OiexHze0?t=26m30s(开始 26 分钟)


这是唯一有用的主题答案。
我不明白这部分。客户端交换访问令牌的授权代码,而不向资源所有者用户代理透露令牌。同意。但是用户代理如何在没有访问令牌的情况下请求资源。无论如何,用户代理会知道访问令牌的权利吗?
客户和资源所有者将维护不同的令牌?例如,我在 Stackoverflow 中使用 facebook 登录。 SO 后端将根据我的同意获取访问令牌,并且我和 SO 之间的通信将使用不同的方案/令牌
@SundarRajan,这是我的理解:用户代理通过自己的后端请求资源,后端充当代理。这样,用户代理实际上不必知道访问令牌。但是,应用程序后端必须在为其请求资源之前对用户代理进行身份验证。
A
Amit Kumar Gupta

理论上,

访问令牌无法告诉我们用户是否已通过身份验证,但身份验证代码可以。

不应使用身份验证代码来获取对 API 的访问权限,但应该使用访问令牌。

如果您有一个单页应用程序或移动应用程序,没有后端或后端最少,您的应用程序可能希望直接在前端访问用户的 FB 数据。因此提供了访问令牌。

在另一种情况下,您可能希望用户使用一些外部身份验证服务提供商(如 Facebook、Google 等)注册/登录您的应用程序。在这种情况下,您的前端会将身份验证代码发送到可用于获取访问令牌的后端来自服务器端的 Facebook。现在您的服务器可以从服务器访问用户的 FB 数据。

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


图片的来源是什么?
C
Community

基本上,作为 Lix's answer 的扩展,访问代码路由允许资源所有者(即 Facebook 用户)撤销对其用户代理(即他们的浏览器)的授权,例如通过注销,而不撤销对离线客户端的授权(即您的应用程序)。如果这不重要,则无需使用访问代码路由。

此外,提供访问代码是为了确保提供给服务器的令牌实际注册到资源所有者(即 Facebook 用户),而不是用户代理(或中间人)。

这似乎类似于选择隐式与授权代码授予流程的问题。 In fact, here is what looks like an opposite view point?!

此外,作为 Drew mentioned

当访问令牌过期时,尝试使用它会失败,并且必须通过刷新令牌获取新的访问令牌。

另一部分是刷新令牌,但我认为在 FB Docs 中没有很好地解释这一点。如果我是正确的,隐式授权(直接令牌)应该是非常短暂的,但这是要强制执行的,FB.js 似乎隐藏了很多(这个我没有深入研究) .

如果我是正确的,code%20token 是一种优化,它允许用户代理拥有令牌并允许服务器在单个请求中启动令牌交换过程(因为网络 IO 上的任何东西都被认为是昂贵的,尤其是对于用户代理)。


J
Justin Ehrlich

这是因为使用只有 FB 和客户端知道的共享密钥将访问令牌提供给 AUTHENTICATED 客户端(第三方应用程序)。用户可以直接请求访问令牌的唯一方法是知道共享秘密,这将使秘密公开并可能导致中间人攻击。此外,虽然 FB 可以保证与用户的安全连接,但 FB 不能保证将令牌传递给客户端是安全的。但是,FB(和 OAuth2)确实需要客户端和 FB 之间的安全连接。访问令牌与客户端公共 ID(通常是散列)相关联,这意味着只有原始客户端应用程序可以使用它来请求令牌,因为密钥与授权代码一起发送以获取访问令牌。


A
Ashane.E

在带有 facebook 的 OAuth 2.0 中,整体概念很简单,如下所示。

Step 1. 通过 GET 请求获取“授权码”

request URI: https://www.facebook.com/dialog/oauth
Params:
    response_type=code
    client_id={add your "App id" got by registering app}
    redirect_uri={add redirect uri defined at the registration of app}
    scope={add the scope needed in your app}
Headers: None

Step 2. 通过POST请求发送授权码获取“Access Token”

    URI: https://graph.facebook.com/oauth/access_token
    Params:
        grant_type=authorization_code
        client_id=<add your "App id" got by registering app>
        redirect_uri=<add redirect uri defined at the registration of app>
        code=<obtained authorization code from previous step>
    Headers:
        Authorization:Basic encode <App Id:App Secret> with base64 
        Content-Type:application/json

步骤 3. 使用从上述步骤获得的访问令牌并检索用户资源


L
Lix

当用户登录时,您会收到一个令牌。但您可能希望在执行其他操作时更改该令牌。 EG 作为您的应用/页面发布或使用 offline_access 作为用户发布。


如果你第一次要求你需要的权限,你不能使用相同的令牌吗?如果你有offline_access,那么你可以保存令牌。我仍然对为什么流程中需要代码感到困惑......
您当然可以使用相同的令牌 - 但普通令牌会在一段时间后过期。 TBH 我从来没有手动使用过那个“代码”参数——我所有的登录都是通过从 SDK 的...中检索 loginURL 来完成的。
我认为目前仅在 php sdk 上。在最新的 oauth2 身份验证文档中,如果您想做 php 服务器端以外的任何事情,则需要使用“代码”