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

为什么您需要在Facebook OAuth2身份validationstream程中同时使用“代码”和“令牌”,如下所述: https : //developers.facebook.com/docs/authentication/ ?

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

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

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

从Salesforce文档借用无耻:

授权码

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

访问令牌客户端使用访问令牌代表最终用户进行已authentication的请求。 它具有比授权代码更长的使用期限 ,通常为几分钟或几小时。 访问令牌到期时,尝试使用它将失败,并且必须通过刷新令牌获取新的访问令牌。

从OAuth 2.0规范 :

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

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

“令牌”响应主要针对居住在浏览器中的客户端(例如:JavaScript客户端)。

让我们举一个简单的例子来区分authentication码和访问令牌。

您作为用户想要尝试一个名为Highjack的新Facebook应用程序。 所以你点击应用程序和Highjack应用程序。 要求您login到您的Facebook帐户。 完成之后,Facebook会为您生成一个validation码。

然后将这个代码传递给Highjack服务器,该服务器使用自己的FB客户端ID,FB秘密和您的validation代码来获取访问令牌。

在上面的例子中,validation码正在确认您,因为用户是有效的FB用户。 但是第二步说“你作为一个FB用户正在访问某些资源的Highjack应用程序”。

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

由于我们有2方(你和Highjack)与Facebookvalidation我们有这个2折机制。

如果你看看授权码OAuthtypes的stream程 ,是的,有精算师的两个步骤:

 1. <user_session_id, client_id> => authorization_code 2. <client_id, redirect_uri, authorization_code, client_secret> => access_token, refresh_token 

在步骤1中:用户告诉OAuth服务器“我想authentication这个cliet(client_id)来访问我的资源。这里是我的authentication(user_session_id或者其他)”

在步骤2中,客户端(client_id)告诉OAuth服务器“我已经得到了用户授权(authorization_code),请给我一个访问令牌以供以后访问,这是我的authentication(client_id&client_secret)”

你看,如果我们省略步骤2,那么客户端authentication就不能保证。 任何客户端都可以使用不同的client_id调用step1,并获取该client_id的访问令牌而不是自己的。 这就是为什么我们需要step2。

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

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

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

顺便说一句,实际上存在一个隐式授予types ,即:

 <client_id, redirect_uri> => access_token, refresh_token 

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

基本上,作为Lix答案的延伸,访问码路由允许资源所有者(即,Facebook用户)撤销其用户代理(即他们的浏览器)的授权,例如通过注销,而不撤销对离线客户端的授权你的申请)。 如果这不重要,则不需要使用访问码路由。

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

这似乎与select隐含授权代码授权stream程的问题类似。 事实上,这是什么看起来像一个相反的观点? 。

另外,正如德鲁所说 ,

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

另一块是刷新令牌,但我没有看到在FB文档中解释得太好。 如果我是正确的,隐含的授予(直接标记)应该是短暂的,但是这是被强制执行的,FB.js似乎隐藏了很多(这个我没有深入) 。

如果我是正确的, code%20token是允许用户代理具有令牌并允许服务器在单个请求中发起令牌交换过程的优化(因为networkingIO上的任何事情都被认为是昂贵的,特别是对于用户代理)。

混淆是因为用户代表自己而不是客户端应用程序对授权服务器 (即脸书)进行身份validation 。 它很简单,以确保客户端应用程序(与https),然后用户代理(浏览器)。

这里是IETF-oauth的原始公式( http://tools.ietf.org/html/draft-ietf-oauth-v2-reatreatmodel-08#section-3.4 ):

3.4。 授权码

授权码代表成功的最终用户授权过程的中间结果,并由客户端用来获取访问和刷新令牌。 为了两个目的,授权码被发送到客户端的redirectURI而不是令牌。

  1. 基于浏览器的stream通过URI查询参数(HTTP referrer),浏览器caching或日志文件条目将协议参数公开给潜在的攻击者,并且可以重播。 为了减less这种威胁,传递短期授权码而不是令牌,并通过客户端和授权服务器之间更安全的直接连接来交换令牌。

  2. 在客户端和授权服务器之间的直接请求期间,比在间接授权请求的上下文中authentication客户端要简单得多。 后者将需要数字签名。

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

当用户login时,您会收到一个令牌。但是,您在执行其他操作时可能需要更改该令牌。 EG作为您的应用程序/页面发布或作为具有offline_access的用户发布。