参考: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
https://www.jianshu.com/p/5b5f84bac6f4
不使用 Facebook SDK 的情况下实施每个步骤:
要在桌面应用中使用“Facebook 登录”,您需要在应用中嵌入网页浏览器(有时称为网页视图)才能执行登录流程。
检查登录状态
使用 Facebook SDK 的应用可以通过内置函数检查用户是否已登录。所有其他应用必须创建自己存储用户已登录状态的方式,如果该指示器不存在,应用应假定用户已退出并继续。如果用户退出,您的应用应在适当的时间将他们重定向至“登录”对话框,例如他们点击“登录”按钮时。
用户登录
无论用户是没有登录应用还是没有登录 Facebook,您都可以使用“登录”对话框来提示他们登录两者。如果用户未登录 Facebook,系统将提示他们登录 Facebook,然后再登录您的应用。系统会自动检测这种情况,您无需执行任何额外操作即可启用此行为。
调用“登录”对话框并设置重定向网址
应用必须启动指向端点的重定向,该端点将显示“登录”对话框:
https://www.facebook.com/v7.0
/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&state={state-param}
该端点具有以下必要参数:
-
client_id
:可在应用面板中找到的应用编号。 -
redirect_uri
:您希望将登录的用户重定向回的网址。该网址将捕获来自“登录”对话框的响应。如果您在桌面应用中的网页视图中使用该网址,则必须将其设置为https://www.facebook.com/connect/login_success.html
。您可以在应用面板中确认是否已针对您的应用设置该网址。在应用面板左侧导航菜单的产品下点击 Facebook 登录,然后点击设置。在 OAuth 客户端设置版块验证有效的 OAuth 重定向 URI。 -
state
:您的应用创建的字符串值,用于维持请求和回调之间的状态。此参数应用于防止跨站请求伪造,并会在重定向 URI 中原样传回给您。
例如,如果您的登录请求如下所示:
https://www.facebook.com/v7.0
/dialog/oauth?
client_id={app-id}
&redirect_uri={"https://www.domain.com/login"}
&state={"{st=state123abc,ds=123456789}"}
则您的重定向 URI 将通过下列代码调用:
https://www.domain.com/login?state="{st=state123abc,ds=123456789}"
另外还有以下可选参数:
response_type
:确定重定向回应用时所包含的响应数据是否存在于网址参数或片段中。请参阅确认身份部分,选择应用应使用的类型。类型可为:-
code
:响应数据作为网址参数纳入,且包含code
参数(每个登录请求独有的加密字符串)。如果未指定此参数,这便是默认行为。当服务器处理口令时,这尤其有用。 -
token
:响应数据作为网址片段纳入,且包含访问口令。桌面应用必须为response_type
选用此设置。当客户端处理口令时,这尤其有用。 -
code%20token
:响应数据作为网址片段纳入,且包含访问口令和code
参数。 -
granted_scopes
:返回用户在登录时授予应用的所有权限的逗号分隔列表。可与其他response_type
值合并。与token
合并时,响应数据作为网址片段纳入;与其他值合并时,响应数据则作为网址参数纳入。
-
-
scope
:要向应用用户请求的权限列表,列表项目以逗号或空格分隔。
适用于 Windows 8 应用
如果您要为 Windows 应用构建登录,可以使用数据包安全识别符作为 redirect_uri
。通过调用 WebAuthenticationBroker.AuthenticateAsync
触发“登录”对话框,并使用“登录”对话框端点作为 requestUri。以下是 JavaScript 中的示例:
var requestUri = new Windows.Foundation.Uri(
"https://www.facebook.com/v7.0
/dialog/oauth?
client_id={app-id}
&display=popup
&response_type=token
&redirect_uri=ms-app://{package-security-identifier}");
Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
options,
requestUri)
.done(function (result) {
// Handle the response from the Login Dialog
}
);
这会将控制流程返回应用,并在成功时附带访问口令,失败时提示错误。
处理“登录”对话框响应
在登录流程的这一阶段,用户会看到“登录”对话框,并可选择取消登录或允许应用访问其数据。
如果应用用户在“登录”对话框中选择“确定”,他们将授予访问公开档案、好友名单的权限,以及应用请求的所有其他权限。
在所有情况下,浏览器均会返回至应用,并会发回表明用户已连接还是已取消的响应数据。当应用使用上述重定向方法时,应用返回至的 redirect_uri
将附加必须予以捕获的网址参数或片段(根据所选的 response_type
)。
网页应用中可以使用多种代码语言组合,因此我们的指南不提供具体示例。但大多数现代语言都能进行网址解析,如下所示:
客户端 JavaScript 可以捕获网址片段(例如 jQuery BBQ),而客户端和服务器端代码均可捕获网址参数(例如 PHP 中的 $_GET
、jQuery BBQ 中的 jQuery.deparam
、Node.js 中的 querystring.parse
或 Python 中的 urlparse
)。Microsoft 提供了 Windows 8 应用连接到“在线提供商”(在本示例中为 Facebook)的指南和示例代码。
使用桌面应用登录时,Facebook 会将用户重定向至上述 redirect_uri
,并在 URI 片段中放置访问口令及一些其他的元数据(例如口令过期时间):
https://www.facebook.com/connect/login_success.html#
access_token=ACCESS_TOKEN...
应用需要检测该重定向,然后使用操作系统及您所用开发框架提供的机制读取 URI 中的访问口令。之后您可以直接跳至检查访问口令步骤。
取消登录
如果应用用户不接受“登录”对话框并点击了“取消”,则将被重定向至以下位置:
YOUR_REDIRECT_URI?
error_reason=user_denied
&error=access_denied
&error_description=Permissions+error.
请参阅处理缺失的权限,详细了解用户拒绝登录时应用应如何操作。
验证身份
由于该重定向流程涉及浏览器从“登录”对话框重定向至应用中的网址,因此流量可以直接访问包含片段或参数的此网址。如果应用假定这些是有效参数,包含的数据可能被应用用于潜在的恶意用途。因此,在为用户生成访问口令前,您的应用应确认应用用户就是响应数据所针对的用户。确认身份可以通过不同的方式完成,具体取决于上述接收到的 response_type
:
-
收到
code
时,需要使用端点将其交换为访问口令。由于调用涉及到应用密钥,因此需采用服务器到服务器形式。(应用密钥绝不能出现在客户端代码中。) -
收到
token
时,需要对其进行验证。您应向检查端点发出 API 调用,以了解口令为谁生成以及由哪个应用生成。由于此 API 调用需要使用应用访问口令,请勿从客户端执行此调用,您应转而从服务器执行此调用,以便安全存储应用密钥。 -
同时收到
code
和token
时,应执行两个步骤。
请注意,您也可以生成自己的 state
参数,并将其用于登录请求,以便提供 CSRF 保护。
用代码交换访问口令
要获取访问口令,请向以下 OAuth 端点发出 HTTP GET 请求:
GET https://graph.facebook.com/v7.0
/oauth/access_token?
client_id={app-id}
&redirect_uri={redirect-uri}
&client_secret={app-secret}
&code={code-parameter}
该端点具有一些必要参数:
-
client_id
:应用编号 -
redirect_uri
:此为必需参数,且必须与开始 OAuth 登录流程时使用的原始request_uri
相同。 -
client_secret
:唯一的应用密钥,显示在应用面板中。绝不能将此应用密钥绝放入可能被反编译的客户端代码或二进制文件中。保持密钥的绝对机密至关重要,因为密钥是应用和所有用户的安全核心。 -
code
:从上述“登录”对话框重定向接收的参数。
注意:从 v2.3 开始,此端点会返回正确的 JSON 响应。如果调用未指定版本,会默认使用最早的可用版本。
响应
您从该端点收到的响应将以 JSON 格式返回,如果成功,将如下方所示:
{
"access_token": {access-token},
"token_type": {type},
"expires_in": {seconds-til-expiration}
}
如果不成功,您将收到一条说明性错误消息。
检查访问口令
无论使用 code
还是 token
作为“登录”对话框的 response_type
,应用都将收到访问口令。您可以使用图谱 API 端点自动检查这些口令:
GET graph.facebook.com/debug_token?
input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
此端点使用以下参数:
-
input_token
:您需要检查的口令。 -
access_token
:应用访问口令,或应用开发者的访问口令。
API 调用的响应为 JSON 数组,其中包含受检查口令的相关数据。例如:
{
"data": {
"app_id": 138483919580948,
"type": "USER",
"application": "Social Cafe",
"expires_at": 1352419328,
"is_valid": true,
"issued_at": 1347235328,
"metadata": {
"sso": "iphone-safari"
},
"scopes": [
"email",
"publish_actions"
],
"user_id": "1207059"
}
}
app_id
和 user_id
字段将协助您的应用验证访问口令是否对用户和您的应用有效。如需其他字段的完整描述,请参阅访问口令信息获取指南。
检查权限
调用 /me/permissions
连线即可检索特定用户授予或拒绝的权限列表。应用可调用此连线,检查其无法使用向特定用户请求的哪些权限。
重新请求被拒绝的权限
“Facebook 登录”允许用户拒绝与应用分享某些权限。“登录”对话框包括如下所示的页面:
用户必须始终授予 public_profile
权限,由于此权限无法禁用,因而选项按钮会显示为灰色。
但在此示例中,如果用户取消勾选 user_likes
(赞),则检查 /me/permissions
以了解被授予的权限时,会生成以下结果:
{
"data":
[
{
"permission":"public_profile",
"status":"granted"
},
{
"permission":"user_likes",
"status":"declined"
}
]
}
注意,user_likes
的状态是被拒绝,而不是已授予。
您可以再一次请求用户向应用授予其曾拒绝的权限。您应该设置一个说明页面,告知用户应该授予相关权限的原因,然后重新请求。但若您像以前一样调用“登录”对话框,则将不会请求该权限。
因为用户拒绝授予某权限后,“登录”对话框便不会重新请求该权限,除非您明确告知对话框要再次请求已拒绝的权限。
只需向“登录”对话框网址添加 auth_type=rerequest
参数即可:
https://www.facebook.com/v7.0
/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&auth_type=rerequest
scope=email
使用此参数时,“登录”对话框会重新请求已拒绝的权限。
存储访问口令和登录状态
在流程的这一阶段,用户已完成身份验证并登录。应用也已准备好代表用户进行 API 调用。执行此操作前,它应存储应用用户的访问口令和登录状态。
存储访问口令
您的应用收到前述步骤的访问口令后应存储口令,以便在它进行 API 调用时可用于应用的所有部分。此部分并无明确的流程,但通常来说,如果您构建的是网页应用,则建议您添加口令作为会话变量,以便识别特定用户与该浏览器进行的会话;如果构建的是原生桌面或移动应用,则应使用应用适用的数据存储库。此外,应用应将口令与 user_id
一起存储到数据库,以供识别。
请参阅我们关于访问口令文档中的访问口令大小的说明。
追踪登录状态
同样,您的应用应存储用户的登录状态,这有助于避免再次调用“登录”对话框。无论您选择的是哪种流程,请修改登录状态检查,纳入此项功能。
用户退出
您可以通过撤销添加的任何登录状态指示器使用户退出应用,例如删除指示用户已登录的会话。您还需要删除已存储的访问口令。
用户退出与撤销登录权限(后者将删除之前认可的验证)不同,撤销登录权限可单独执行。因此,构建应用时,要保证其不会自动强制已退出的用户返回“登录”对话框。
检测用户卸载应用
用户可以通过 Facebook.com 卸载应用,无需与应用互动。为帮助应用检测卸载事件的发生,我们允许应用提供取消授权回调网址,以便在用户卸载时接收信号。
您可以通过应用面板启用取消授权回调。前往应用,依次选择产品、Facebook 登录和设置。您将看到名为取消授权回调网址的文本字段。
当应用用户取消授权时,此网址就会收到一个包含签名请求的 HTTP POST
。请阅读我们的签名请求解析指南了解如何解码,从而找到触发回调网址的用户编号。
响应删除用户数据的请求
用户可以请求应用删除从 Facebook 接收的所有用户相关信息。要响应这些请求,请参阅数据删除请求回调。