PHP SDK:如何在用户身份验证应用程序后捕获访问令牌? [英] PHP SDK: How do I capture the access token after user auths app?

查看:24
本文介绍了PHP SDK:如何在用户身份验证应用程序后捕获访问令牌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是用于 Facebook 平台上的画布应用程序,使用新的(est)Facebook PHP SDK.

我们使用 Facebook 教程 (https://developers.facebook.com/docs/appsonfacebook/tutorial/) 中的 PHP 示例来触发 OAuth 对话框并使测试用户转到重定向 URL.

在重定向 URL 中,我们使用 Facebook 签名请求文档页面 (https://developers.facebook.com/docs/authentication/signed_request/) 中的 PHP 示例,我们的测试用户可以成功授权应用程序.

但是,在测试用户对应用进行身份验证后,我们无法捕获访问令牌及其到期时间.我们可以在附加到重定向 URL 的地址栏中看到它,但它没有出现在 $_REQUEST 数组中.如果我们将 {$access_token = $facebook->getAccessToken();} 添加到重定向 URL 页面,它会显示访问令牌的值,但它显示的值不是我们单击 Show 时看到的完整令牌字符串测试用户角色页面中的令牌(我们认为这是测试用户的正确访问令牌).

以下是附加了访问令牌的重定向 URL 示例:_qca"]=> string(26) "P0-709927483-1291994912966" ["__switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "euois02ead39ijumca7nffblh2" }

我们不知道为什么 $_REQUEST 数组与附加到 URL 的值不同,更重要的是 - 如何捕获访问令牌及其到期日期.

有人可以向我们展示在重定向页面上运行 parse_signed_request($signed_request, $secret) 函数后如何捕获这些数据的工作示例吗?谢谢!

附加信息:

这是来自 A) 我们的测试索引页面和 B) 我们的测试重定向页面的相关代码.如果我们使用我们的文本索引页面作为重定向 url,它就会陷入无限循环——因为用户永远不会被识别.

A) 索引页

//创建 kk-fb 应用实例$facebook = 新 Facebook(数组('appId' =>KKFB_ID,'秘密' =>KKFB_KY,'oauth' =>真的,));$app_id = KKFB_ID;$secret = KKFB_KY;$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';$auth_url = "https://www.facebook.com/dialog/oauth?".client_id=".$app_id.&redirect_uri=".urlencode($canvas_auth).&response_type=token"."&scope=email,publish_stream";$signed_request = $_REQUEST["signed_request"];列表($encoded_sig, $payload) = expand('.', $signed_request, 2);$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);如果(空($数据[user_id"])){echo("<script> top.location.href='" . $auth_url . "'</script>");} 别的 {echo ("欢迎用户:" . $data["user_id"]);}

B) 重定向页面

//创建 kk-fb 应用实例$facebook = 新 Facebook(数组('appId' =>KKFB_ID,'秘密' =>KKFB_KY,'oauth' =>真的,));$app_id = KKFB_ID;$secret = KKFB_KY;$signed_request = $_REQUEST["signed_request"];列表($encoded_sig, $payload) = expand('.', $signed_request, 2);$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);$user = $facebook->getUser();$access_token = $facebook->getAccessToken();echo "用户: $user 
";echo "访问令牌:$access_token
";echo "签名请求:$signed_request
";var_dump($_REQUEST);

以下是这些回声结果的显示:

用户:0访问令牌:126736467765|**SECRET**签名请求:array(3) { ["_qca"]=> string(26) "P0-709927483-1291994912966" ["_switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "frugi545cdl15gjind1fnv6pq1" }

有趣的是,当测试用户返回索引页面时,if 条件满足,我们可以获得正确的访问令牌:

欢迎用户:100002908746828访问令牌:126736467765|2.AQBgcyzfu75IMCjw.3600.1315544400.1-100002908746828|m5IYEm976tJAkbTLdxHAhhgKmz8

显然,我们还缺少一些东西!?此外,我们还需要学习如何将到期时间作为变量获取,以便我们可以将这两者存储在我们的数据库中.

好的,让我们再试一次.

服务器端与客户端身份验证

您专门使用 PHP SDK,因此您想要进行服务器端身份验证,其中身份验证代码通过 URL 通过 HTTP 发送到服务器.这将允许您在身份验证后的第一个页面加载时为用户获取访问令牌(在您的情况下,重定向页面).您当前正在构建的 auth_url 正在设置 response_type=token,这会强制重定向使用客户端身份验证模式并在 URL 片段中而不是在查询中设置令牌.您应该完全删除该参数.事实上,我强烈建议您只使用 PHP SDK,而不是自己构建该 URL.请参阅下面的示例.

应用程序访问令牌

奇怪的访问令牌 126736467765|SECRET 是您的应用程序访问令牌,它由您的应用程序 ID 和密钥组成.如果没有可用的用户访问令牌(因为某些 API 调用至少需要某种访问令牌),则应用程序访问令牌由 getAccessToken() 返回.这也意味着您已经通过这篇博文向全世界公开了您的密钥,因此您应该重置您的应用机密 否则任何人都可以代表您进行 API 调用.如果您与他人共享,我强烈建议您省略部分访问令牌.

令牌到期

PHP SDK 的 OAuth 2.0 流程和 v3.1.1 并没有让确定令牌的到期时间变得那么容易.我建议尝试进行 API 调用,然后 刷新令牌 如果 API 调用失败并显示 OAuthException.即使令牌尚未过期,它们也可能无效,因此这涉及更多情况.但是,如果您仍然希望保留到期日期,您可能只想从令牌本身中提取它.如果您有到期令牌,则到期时间戳将包含在该字符串中.这是我快速组合起来提取的一个函数:

function extractExpirationFromToken($access_token) {$segments = expand('|', $access_token);if(count($segments) < 2) { return 0;}$segments = expand('.', $segments[1]);if(count($segments) <4) { return 0;}$expires = $segments[3];$dash_pos = strrpos($expires, '-');如果($dash_pos !== 假){$expires = substr($expires, 0, $dash_pos);}返回 $expires;}

新索引页面代码

//创建 kk-fb 应用实例$facebook = 新 Facebook(数组('appId' =>KKFB_ID,'秘密' =>KKFB_KY,));$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';$auth_url = $facebook->getLoginUrl(array('范围' =>'电子邮件,publish_stream','redirect_uri' =>$canvas_auth,//你可以重定向回这个索引页面));$user = $facebook->getUser();如果(空($用户)){echo("<script> top.location.href='" . $auth_url . "'</script>");} 别的 {echo ("欢迎用户:" . $user);}

重定向页面

我认为您根本不需要这个页面.您可以将用户重定向回原始索引页面.

//创建 kk-fb 应用实例$facebook = 新 Facebook(数组('appId' =>KKFB_ID,'秘密' =>KKFB_KY,));$user = $facebook->getUser();$access_token = $facebook->getAccessToken();//也复制前面给出的函数定义$expiration = extractExpirationFromToken($access_token);echo "用户: $user 
";echo "访问令牌:$access_token
";echo "过期: $expiration <br>";echo "请求:<br>";var_dump($_REQUEST);

This is for a canvas app on the Facebook Platform using the new(est) Facebook PHP SDK.

We are using the PHP example from the Facebook tutorial (https://developers.facebook.com/docs/appsonfacebook/tutorial/) to trigger the OAuth dialog and get the test user to the redirect URL.

At the redirect URL, we use the PHP example from the Facebook signed request docs page (https://developers.facebook.com/docs/authentication/signed_request/) and our test users can successfully authorize the app.

However, after the test user auths the app, we are not able to capture the access token and its expiration. We can see it in the address bar appended to the redirect URL, but it does not show up in the $_REQUEST array. If we add {$access_token = $facebook->getAccessToken();} to the redirect URL page, it shows a value for the access token, but the value it shows is not the full token string that we see when we click on Show Token in the Test User Roles page (which we believe is the correct access token for the test user).

Here is an example of the redirect URL with an access token appended: http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php#access_token=126736467765%7C2.AQDavId8oL80P5t9.3600.1315522800.1-100002908746828%7CJICJwM1P_97tKmqkEO5pXDCf-7Y&expires_in=6008

Here is what var_dump shows for the $REQUEST array for that same page: array(3) { ["_qca"]=> string(26) "P0-709927483-1291994912966" ["__switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "euois02ead39ijumca7nffblh2" }

We have no idea why the $_REQUEST array varies from the values appended to the URL, and more importantly -- how to capture the access token and its expiration date.

Can someone show us a working example of how they capture this data after running the parse_signed_request($signed_request, $secret) function on the redirect page? Thanks!

ADDITIONAL INFO:

Here is the pertinent code from A) our test index page, and B) our test redirect page. If we use our text index page as the redirect url it gets stuck in an endless loop -- because the user is never identified.

A) Index Page

// Create kk-fb app instance
$facebook = new Facebook(array(
    'appId'  => KKFB_ID,
    'secret' => KKFB_KY,
    'oauth' => true,
));

$app_id = KKFB_ID;
$secret = KKFB_KY;
$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';

$auth_url = "https://www.facebook.com/dialog/oauth?" 
                . "client_id=" . $app_id 
                . "&redirect_uri=" . urlencode($canvas_auth) 
                . "&response_type=token" 
                . "&scope=email,publish_stream";

$signed_request = $_REQUEST["signed_request"];

list($encoded_sig, $payload) = explode('.', $signed_request, 2); 

$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);

if (empty($data["user_id"])) {
    echo("<script> top.location.href='" . $auth_url . "'</script>");
} else {
    echo ("Welcome User: " . $data["user_id"]);
}

B) Redirect Page

// Create kk-fb app instance
$facebook = new Facebook(array(
    'appId'  => KKFB_ID,
    'secret' => KKFB_KY,
    'oauth' => true,
));

$app_id = KKFB_ID;
$secret = KKFB_KY;

$signed_request = $_REQUEST["signed_request"];

list($encoded_sig, $payload) = explode('.', $signed_request, 2); 

$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);

$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();

echo "User: $user <br>";
echo "Access Token: $access_token <br>";
echo "Signed Request: $signed_request <br>";
var_dump($_REQUEST);

Here is what shows up as these echo results:

User: 0 Access Token: 126736467765|**SECRET** Signed Request: array(3) { ["_qca"]=> string(26) "P0-709927483-1291994912966" ["_switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "frugi545cdl15gjind1fnv6pq1" }

Interestingly, when the test user goes back to the index page the if condition is satisfied and we can get the correct access token:

Welcome User: 100002908746828 Access Token: 126736467765|2.AQBgcyzfu75IMCjw.3600.1315544400.1-100002908746828|m5IYEm976tJAkbTLdxHAhhgKmz8

Obviously, we are still missing something!? Also, we need to learn how to get the expiration time as a variable too so we can store both of these in our database.

解决方案

OK, let's try this again.

Server-side vs Client-side Authentication

You are exclusively using the PHP SDK, so you want to do server-side authentication, where the authentication code is sent to the server over HTTP via the URL. This will allow you to fetch an access token for the user on the first page load after auth (in your case, the redirect page). The auth_url you are currently constructing is setting response_type=token, which forces the redirect to use client-side auth mode and set the token in the URL fragment instead of in the query. You should remove that parameter completely. In fact, I highly recommend you just use the PHP SDK instead of constructing that URL yourself. See example below.

Application Access Tokens

The odd-looking access token 126736467765|SECRET is your application access token, which is composed of your app ID and secret key. The application access token is returned by getAccessToken() if no user access token is available (because some API calls require at least some sort of access token). This also means that you've revealed your secret key to the world via this blog post, so you should reset your app secret otherwise anyone will be able to make API calls on your behalf. I highly recommend you elide parts of your access tokens if you share them with others.

Token Expiration

The OAuth 2.0 flow and v3.1.1 of the PHP SDK don't make determining the expiration time of a token all that easy. I would suggest attempting to make the API call, and then refreshing the token if the API call fails with an OAuthException. Tokens can be invalid even if they haven't expired, so this deals with more cases. However, if you still want to maintain the expiration date on your end, you might just want to extract it from the token itself. If you have an expiring token, then the expiration timestamp will be contained within that string. Here's a function I put together quickly to extract that:

function extractExpirationFromToken($access_token) {
    $segments = explode('|', $access_token);
    if(count($segments) < 2) { return 0; }

    $segments = explode('.', $segments[1]);
    if(count($segments) < 4) { return 0; }

    $expires = $segments[3];
    $dash_pos = strrpos($expires, '-');
    if($dash_pos !== false) {
        $expires = substr($expires, 0, $dash_pos);
    }
    return $expires;
}

New Index Page Code

// Create kk-fb app instance
$facebook = new Facebook(array(
    'appId'  => KKFB_ID,
    'secret' => KKFB_KY,
));

$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';

$auth_url = $facebook->getLoginUrl(array(
    'scope' => 'email,publish_stream',
    'redirect_uri' => $canvas_auth, // you could just redirect back to this index page though
));

$user = $facebook->getUser();

if (empty($user)) {
    echo("<script> top.location.href='" . $auth_url . "'</script>");
} else {
    echo ("Welcome User: " . $user);
}

Redirect Page

I don't think you need this page at all. You could just redirect the user back to your original index page.

// Create kk-fb app instance
$facebook = new Facebook(array(
    'appId'  => KKFB_ID,
    'secret' => KKFB_KY,
));

$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();
// also copy the function definition given earlier
$expiration = extractExpirationFromToken($access_token);

echo "User: $user <br>";
echo "Access Token: $access_token <br>";
echo "Expiration: $expiration <br>";
echo "Request: <br>";
var_dump($_REQUEST);

这篇关于PHP SDK:如何在用户身份验证应用程序后捕获访问令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆