PHP SDK:如何在用户授权应用程序后捕获访问令牌?

时间:2011-09-08 21:51:02

标签: facebook-php-sdk oauth-2.0 access-token facebook-canvas

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

我们正在使用Facebook教程(https://developers.facebook.com/docs/appsonfacebook/tutorial/)中的PHP示例来触发OAuth对话框并让测试用户访问重定向网址。

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

但是,在测试用户验证应用程序后,我们无法捕获访问令牌及其过期。我们可以在附加到重定向URL的地址栏中看到它,但它不会显示在$ _REQUEST数组中。如果我们将{$ access_token = $ facebook-> getAccessToken();}添加到重定向URL页面,它会显示访问令牌的值,但它显示的值不是我们点击时看到的完整令牌字符串在“测试用户角色”页面中显示令牌(我们认为它是测试用户的正确访问令牌)。

以下是附加了访问令牌的重定向网址示例: http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php#access_token=126736467765%7C2.AQDavId8oL80P5t9.3600.1315522800.1-100002908746828%7CJICJwM1P_97tKmqkEO5pXDCf-7Y&expires_in=6008

以下是var_dump为同一页面的$ REQUEST数组显示的内容: array(3){[“ _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)索引页

// 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)重定向页面

// 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);

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

用户:0 访问令牌:126736467765 | ** SECRET ** 签名请求: array(3){[“_ qca”] =&gt; string(26)“P0-709927483-1291994912966”[“ _switchTo5x”] =&gt; string(2)“30”[“PHPSESSID”] =&gt; string(26)“frugi545cdl15gjind1fnv6pq1”}

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

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

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

4 个答案:

答案 0 :(得分:13)

好的,让我们再试一次。

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

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

应用程序访问令牌

奇怪的访问令牌126736467765 | SECRET 是您的应用程序访问令牌,它由您的应用程序ID和密钥组成。如果没有可用的用户访问令牌,则getAccessToken()返回应用程序访问令牌(因为某些API调用至少需要某种访问令牌)。这也意味着您已通过此博客文章向全世界透露了您的密钥,因此您应reset your app secret,否则任何人都可以代表您拨打API电话。如果您与他人分享,我强烈建议您取消访问令牌的部分内容。

令牌过期

PHP SDK的OAuth 2.0流程和v3.1.1无法轻松确定令牌的到期时间。我建议尝试进行API调用,然后refreshing the token如果API调用失败并显示OAuthException。令牌即使没有过期也可能无效,因此处理更多案件。但是,如果您仍希望在结束时维护到期日期,则可能只想从令牌本身中提取它。如果您有一个到期令牌,那么到期时间戳将包含在该字符串中。这是我快速汇总的一个函数,用于提取:

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;
}

新索引页码

// 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);
}

重定向页面

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

// 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);

答案 1 :(得分:2)

您可以在方法getAccessToken()中使用facebook build;

$access_token = $facebook->getAccessToken();

这将为您提供变量的访问令牌,现在如果您将其变为空,请记住首先检查fuid是否正常捕获,如果不是,您可能需要查看您的设置,请确保“ “App Domain”设置正确设置此部分非常重要您需要重置应用程序密钥,然后在您的身份验证代码中设置新值。希望这个帮助,让我知道:)。

概率pd。还要记住在整个php文件或类中保持变量的范围。

答案 2 :(得分:1)

问题

粘贴的网址中的access_token不是查询字符串的一部分,而是包含在网址片段中(在#之后)。 URL片段不会发送到Web服务器,只能由Javascript等客户端代码读取。因此,PHP SDK仅显示http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php,这就是$_REQUEST不包含access_token密钥的原因。

问题/备注

  1. 您对redirect_uri使用了什么?我想你想要使用像http://apps.facebook.com/your_canvas_url/
  2. 这样的东西
  3. 您不需要自己致电parse_signed_request或从已签名的请求页面复制任何代码。 PHP SDK将为您完成。请致电:

    $facebook = new Facebook(array(
        'appId' => '…',
        'secret' => '…',
    ));
    $access_token = $facebook->getAccessToken();
    
  4. 可能的解决方案

    1. 也使用Facebook Javascript SDK。您可以首先在目标网页(kk-fb-auth.php)中添加<script>标记(有关详细信息,请参阅the docs;请不要忘记设置oauth: true)。 JS SDK应该设置一个cookie(名为fbsr_126736467765),PHP SDK可以在后续页面加载时通过$_REQUEST$_COOKIE读取。

答案 3 :(得分:0)

如果您想使用PHP执行此操作,则可以通过redirect_uri单独调用Graph API来获取用户的访问令牌。为此,您需要将索引页中$ auth_url的response_type更改为“code”或“code token”。

然后,在您的重定向页面,Facebook将在查询字符串中添加“代码”参数。此API调用将返回完整的access_token和到期时间:

https://graph.facebook.com/oauth/access_token?
    client_id=YOUR_APP_ID&
    redirect_uri=YOUR_URL&
    client_secret=YOUR_APP_SECRET&
    code=$_REQUEST['code']

有关详细信息,请参阅docs on authentication