【问题标题】:How to extend access token validity since offline_access deprecation自offline_access弃用以来如何延长访问令牌的有效性
【发布时间】:2012-02-17 09:58:55
【问题描述】:

由于 offline_access Permission 在 Facebook 的 Authentication 流程中已弃用,因此在没有该权限的情况下获取所谓的长期访问令牌时会遇到问题。

Facebook's document about the deprecation 中说,服务器端 OAuth 生成的访问令牌将长期存在,但事实并非如此。

我错过了什么吗?应用程序设置中的某些设置?我需要使用一些特殊代码来延长访问令牌的到期时间?据我了解,对于服务器端身份验证,用户登录时可以通过 PHP SDK 的getAccessToken() 方法访问的访问令牌是长期存在的。

【问题讨论】:

    标签: php facebook-graph-api facebook-php-sdk oauth-2.0 facebook-oauth


    【解决方案1】:

    编辑(2012 年 8 月 14 日):
    一周前官方的 Facebook PHP SDK 更新了。函数名称已更改为 setExtendedAccessToken,我们决定之后确实需要销毁会话,以消除有两个活动会话的风险。
    此外,该函数实际上不再返回令牌,而是将其存储在持久数据中。因此,您可以在之后使用公共函数 getAccessToken 获取新的访问令牌。从official Facebook PHP SDK github page 获取新的 SDK 以确保您是最新的。

    原答案:

    我在 base_facebook.php 文件中添加了一个新的公共函数,它返回一个新的访问令牌,该令牌将在 60 天后到期。收到普通访问令牌后,您可以向此函数发出请求。我还没有测试过,但我认为您还需要在开发者应用程序的高级设置中启用“弃用离线访问”。

    只需将其添加到 facebook 类中的 base_facebook.php 并调用它。它对我有用。

     public function getExtendedAccessToken(){
    
        try {
            // need to circumvent json_decode by calling _oauthRequest
              // directly, since response isn't JSON format.
            $access_token_response =
                $this->_oauthRequest(
                    $this->getUrl('graph', '/oauth/access_token'), array(
                        'client_id' => $this->getAppId(),
                        'client_secret' => $this->getAppSecret(),
                        'grant_type'=>'fb_exchange_token',
                        'fb_exchange_token'=>$this->getAccessToken()
                    )
                );
        } catch (FacebookApiException $e) {
          // most likely that user very recently revoked authorization.
          // In any event, we don't have an access token, so say so.
          return false;
        }
    
        if (empty($access_token_response)) {
          return false;
        }
    
        $response_params = array();
        parse_str($access_token_response, $response_params);
        if (!isset($response_params['access_token'])) {
          return false;
        }
    
        return $response_params['access_token'];
    }
    

    【讨论】:

    • 在我的情况下,我必须将“getAppSecret()”替换为“getApiSecret()”(SDK 版本 3.1.1)
    • 在SDK 3.1.1 中getApiSecret 函数不只是返回getAppSecret 函数,因为getApiSecret 函数已被弃用,将在未来的版本中删除?
    • 有人可以告诉我这是否适用于使用 signed_request 方法获得的访问令牌?因为 facebook 文档似乎说它仅适用于客户端流程?
    • 伙计们,现在有效吗?我尝试了,但得到如下错误:developers.facebook.com/bugs/…
    • 并检查您的 access_token var_dump() 然后将字符串复制并粘贴到:developers.facebook.com/tools/debug/access_token ...您希望看到类似“过期:1347718933(大约 2 个月)”的内容。如果您看到类似“过期:1342540800(大约一个小时)”的内容,那么您没有获得扩展访问令牌。比较 getAccessToken() 与这个答案 getExtendedAccessToken() 的结果。祝你好运!。
    【解决方案2】:

    其实是这么说的:

    如果 access_token 是从服务器端 OAuth 调用生成的,则生成的 access_token 将具有更长的过期时间。如果在该用户仍有有效的 access_token 时进行调用,则第二次调用返回的 access_token 将保持不变,仅延长到期时间。同样,在同一天多次调用它只会导致第一次调用延长到期时间。

    这意味着它将比客户端生成的令牌更长,并且要接收扩展令牌(60 天),您需要通过发出请求手动完成:

    https://graph.facebook.com/oauth/access_token?             
        client_id=APP_ID&
        client_secret=APP_SECRET&
        grant_type=fb_exchange_token&
        fb_exchange_token=EXISTING_ACCESS_TOKEN
    

    由于多种原因,此令牌仍然可能无效,How-To: Handle expired access tokens 博客文章中描述了如何处理此问题。

    更新:
    Aug 07, 2012 开始,您可以使用setExtendedAccessToken 方法来扩展access_token,而不是手动构建URL 和检索详细信息。

    【讨论】:

    • 投票!是否总是提供相同的 access_token 并延长过期时间?或者 access_token 可能会改变?
    • 很确定您将始终获得相同的令牌,因为您正在扩展预先存在的令牌。 Facebook 表示,您可能会在用户更改密码和/或注销并重新登录您的应用时获得新令牌。
    【解决方案3】:

    //使用javascript弹出facebook登录

    FB.login(function(response) {
    
                if (response.authResponse) {
    
                       var accessToken = response.authResponse.accessToken;
    

    //得到1-2小时过期时间的accesstoken

    //把accesstoken拿到一个叫facebook控制器的控制器里

            $request = $this->getRequest();
            $params = $request->getParams();
            $token=$params['accessToken'];
    

    //获取访问令牌延长至60天

            $conf = $this->getConfigs();
            $appid = $conf['fbdetails']['appid'];
            $secret = $conf['fbdetails']['secret'];
            $baseurl = $conf['app']['baseurl'];
    

    //下面的代码执行后,我们会得到一个响应,访问令牌过期时间为60天。

            $token_url = "https://graph.facebook.com/oauth/access_token?client_id=".$appid."&client_secret=".$secret."&grant_type=fb_exchange_token&fb_exchange_token=".$token;
    

    // 以上响应用于解析。

            $c = curl_init();
            curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($c, CURLOPT_URL, $token_url);
            $contents = curl_exec($c);
            $err  = curl_getinfo($c,CURLINFO_HTTP_CODE);
            curl_close($c);
    
            $paramsfb = null;
            parse_str($contents, $paramsfb);
    

    //解析上述执行代码中的内容后,存储新的扩展accesstoken。

            $user_session = new Zend_Session_Namespace('fbuser');
            $user_session->access_token = $paramsfb['access_token'];
    

    //存储到会话中。

            $this->_redirect('/home');
    

    //有一个漂亮的编码

    【讨论】:

      【解决方案4】:

      通过服务器端 OAuth 调用生成的访问令牌将属于扩展(更长)类型,您无需交换它。它已经是一个扩展令牌。 您唯一需要做的就是在您的应用设置中启用“弃用离线访问”。当然,只有在之前禁用“弃用离线访问”时才需要这样做。

      然后,当您通过 Facebook 对用户进行身份验证时,您将收到一个有效期为 60 天的访问令牌。同一天多次认证只会导致第一次认证延长过期时间。

      【讨论】:

      • 我也遇到过这种行为。事实上,调用文档中的端点再次要求我提供一个 redirect_uri,当我提供一个匹配的(来自以前的调用)时,它返回一个错误。我无法成功调用该方法来获取扩展令牌。但是,自从我在服务器端进行 OAuth 调用并将弃用的脱机访问选项选中为启用后,我的令牌确实持续了 60 天。所以我可以提出另一个正常的请求来获得另一个 60 天(我想每天一次)。我真的希望这可以自动化......让用户每 60 次重新验证一次是可怕的。
      • 实际上重新认证对您的用户来说应该是完全透明的。请记住,即使您的访问令牌已过期,他们已经对您的应用程序进行了身份验证。关于延长到期端点 (developers.facebook.com/roadmap/offline-access-removal),您尝试使用它但没有成功 - 它不起作用,因为它只应该用于客户端 OAuth。
      【解决方案5】:

      如果您需要一个 永不PAGE 过期的访问令牌,请参阅我对类似问题的回答 here

      来自开发者页面:

      通过使用长期存在的用户访问令牌,查询 [User ID]/accounts 端点现在将提供 不提供的页面 访问令牌 用户管理的页面过期。

      【讨论】:

        【解决方案6】:

        这是为了将页面访问令牌延长为永不过期,并延长用户访问令牌在 2 个月后到期(“新访问令牌”)的寿命。

        好的,所以花了大约一周的时间进行研究,但这是我的解决方案。 在https://developers.facebook.com/tools/explorer/ 中确保你有manage_page 作为你的access_token 的一部分。之后将此代码与您的应用 ID、密码和重定向一起使用:

        <?php
           app_id = "APP_ID";
           $app_secret = "APP_SECERET";
           $post_login_url = "REDIRECT_URL";
        
        
           $code = $_REQUEST['code'];
        
           //Obtain the access_token with publish_stream permission 
           if(empty($code)){ 
              $dialog_url= "http://www.facebook.com/dialog/oauth?"
               . "client_id=" .  $app_id 
               . "&redirect_uri=" . urlencode( $post_login_url)
               .  "&COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES";
              echo("<script>top.location.href='" . $dialog_url 
              . "'</script>");
             }
            else {
        
        
              $token_url="https://graph.facebook.com/oauth/access_token?"
               . "client_id=" . $app_id 
               . "&redirect_uri=". urlencode($post_login_url)
               . "&client_secret=" . $app_secret
               . "&code=" . $code;
              $response = file_get_contents($token_url);
              $params = null;
              parse_str($response, $params);
              $access_token = $params['access_token'];
              echo 'access token: ' . $access_token.'<br>';
        
                if($access_token){
        
        
                  $token_url="https://graph.facebook.com/oauth/access_token?"
               . "client_id=" . $app_id 
               . "&redirect_uri=". urlencode($post_login_url)
               . "&client_secret=" . $app_secret
               .'&grant_type=fb_exchange_token'
               . "&fb_exchange_token=" . $access_token;
               $response = file_get_contents($token_url);
               $access_token = $params['access_token'];
               echo 'new access token: '.$access_token;
        
                }
            }*/
        
        ?>
        

        之后复制“新访问令牌”并返回https://developers.facebook.com/tools/explorer/,当您通过新访问令牌进入访问令牌字段时。 然后点击提交。之后在节点中,您将看到 +____ 单击此按钮并向下滚动到帐户并单击该按钮。找到您需要访问令牌的页面并将其复制并粘贴到访问密钥字段中。点击调试,你会看到它永远不会过期。保存该令牌,只要您不重置应用密码,它就会一直有效。

        【讨论】:

          【解决方案7】:

          受之前回答的启发,我写了一个简单的代币自我更新程序。首先,只需将您当前的令牌放入“token.sec”文件中即可。

          此程序将从文件中读取一个令牌,如果一切正常,则使用新令牌进行更新。在其他程序中,只需要使用token即可:

          $access_token = file_get_contents("token.sec");
          

          我们在这里:

          <?php
          $app_id = "<your app id>";
          $app_secret = "<your app secret>";
          $access_token = file_get_contents("token.sec");
          
          $token_url="https://graph.facebook.com/oauth/access_token?"
             . "grant_type=fb_exchange_token"
             . "&client_id=" . $app_id 
             . "&client_secret=" . $app_secret
             . "&fb_exchange_token=" . $access_token;
          
          $ch = curl_init($token_url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          
          $response = curl_exec($ch); 
          if($response === false) {
              die ('Curl error: ' . curl_error($ch));
          }
          
          // Close handle
          curl_close($ch);
          
          // parse the output
          parse_str($response, $params);
          if(!isset($params['access_token'])) {
              die("No access token");
          }
          
          echo ("New token: $access_token\n");
          
          // eveything looks OK
          rename("token.sec", "token.sec.back"); // just in case
          $myfile = fopen("token.sec", "w") or die("Unable to open file!");
          fwrite($myfile, $access_token);
          fclose($myfile);
          ?>
          

          最后,我们可以在我们的 crontab 中添加它,以便每月更新一次令牌:

          0 0 1 * * cd /home/<path>; php exchangeToken.php
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-18
            • 1970-01-01
            • 1970-01-01
            • 2012-04-16
            • 2012-02-28
            • 2012-12-28
            相关资源
            最近更新 更多