{"id":16,"date":"2012-03-15T20:03:27","date_gmt":"2012-03-15T20:03:27","guid":{"rendered":"http:\/\/blogs.law.harvard.edu\/acts\/?p=16"},"modified":"2012-03-15T20:03:27","modified_gmt":"2012-03-15T20:03:27","slug":"problems-with-the-facebook-php-sdk","status":"publish","type":"post","link":"https:\/\/archive.blogs.harvard.edu\/acts\/2012\/03\/15\/problems-with-the-facebook-php-sdk\/","title":{"rendered":"Problems with the Facebook PHP SDK"},"content":{"rendered":"<div>There were a few reasons I wanted to add Facebook authentication to the new iteration of Quizmo.\n<\/div>\n<ul>\n<li>I wanted a second form of authentication to help in abstracting authentication.<\/li>\n<li>I needed a second form of authentication because the intention is to open source this project, and I need to provide something other than iSites authentication if I want people to use it.<\/li>\n<li>The process is very similar to Harvard&#8217;s PIN authentication, which I have done before, but probably won&#8217;t be necessary for Quizmo as it will be available through iSites.<\/li>\n<li>&#8220;Everyone&#8221; uses Facebook so it&#8217;s probably something worth knowing.<\/li>\n<\/ul>\n<div>\nThe first minor problem was there is no proxy support. \u00a0The Facebook SDK takes you to a Facebook login page to authenticate, but before it sends you there, it checks if you&#8217;re already logged in. \u00a0This is done through a <a title=\"curl\" href=\"http:\/\/php.net\/manual\/en\/curl.examples-basic.php\">curl<\/a> request. \u00a0The problem comes if you&#8217;re working in a development environment which doesn&#8217;t have a direct outlet to the internets. \u00a0The curl options are set as\n<\/div>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n\r\npublic static $CURL_OPTS = array(\r\nCURLOPT_CONNECTTIMEOUT =&gt; 10,\r\nCURLOPT_RETURNTRANSFER =&gt; true,\r\nCURLOPT_TIMEOUT =&gt; 60,\r\nCURLOPT_USERAGENT =&gt; &#039;facebook-php-3.1&#039;,\r\n);\r\n\r\n<\/pre>\n<div>\nSo this is stored as a static variable in the abstract BaseFacebook class &#8211; which is absurd because that means it can&#8217;t be overridden. \u00a0As such the following line has to be added to the BaseFacebook class:\n<\/div>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n\r\nCURLOPT_PROXY =&gt; &quot;my.proxy.address:myport&quot;,\r\n\r\n<\/pre>\n<div>The larger problem with the Facebook PHP SDK is its inability to handle token errors. \u00a0The tokens are set server side when someone authenticates the first time. \u00a0These tokens then expire and the SDK is unable to handle errors that occur because of this. \u00a0The weirdest thing about this error is that the <a title=\"developers have a solution\" href=\"http:\/\/developers.facebook.com\/blog\/post\/500\/\">developers have a solution<\/a>, they just expect people using their SDK to implement it on their end. \u00a0Regardless, their code did not work for me as advertised and had to be tweaked as such:<\/div>\n<div><\/div>\n<div>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nprivate function checkAccessToken(){\r\n\r\n$app_id = ;\r\n$app_secret = ;\r\n$my_url = ;\r\n\r\n\/\/ known valid access token stored in a database\r\n$access_token = -&gt;getAccessToken();\r\n\r\n$code = @$_REQUEST&#x5B;&quot;code&quot;];\r\n\r\n\/\/ If we get a code, it means that we have re-authed the user\r\n\/\/and can get a valid access_token.\r\nif (isset($code)) {\r\n$token_url=&quot;https:\/\/graph.facebook.com\/oauth\/access_token?client_id=&quot;\r\n. $app_id . &quot;&amp;amp;amp;amp;amp;amp;redirect_uri=&quot; . urlencode($my_url)\r\n. &quot;&amp;amp;amp;amp;amp;amp;client_secret=&quot; . $app_secret\r\n. &quot;&amp;amp;amp;amp;amp;amp;code=&quot; . $code . &quot;&amp;amp;amp;amp;amp;amp;display=popup&quot;;\r\n\r\n\/\/ Now all file stream functions can use this context.\r\n$response = $this-&gt;curl_get_file_contents($token_url);\r\n$params = null;\r\nparse_str($response, $params);\r\n$access_token = @$params&#x5B;&#039;access_token&#039;];\r\n}\r\n\r\n\/\/ Attempt to query the graph:\r\n$graph_url = &quot;https:\/\/graph.facebook.com\/me?&quot;\r\n. &quot;access_token=&quot; . $access_token;\r\n$response = $this-&gt;curl_get_file_contents($graph_url);\r\n$decoded_response = json_decode($response);\r\n\r\n\/\/Check for errors\r\nif (@$decoded_response-&gt;error) {\r\n\/\/ check to see if this is an oAuth error:\r\nif ($decoded_response-&gt;error-&gt;type== &quot;OAuthException&quot;) {\r\n\/\/ Retrieving a valid access token.\r\n$dialog_url= &quot;https:\/\/www.facebook.com\/dialog\/oauth?&quot;\r\n. &quot;client_id=&quot; . $app_id\r\n. &quot;&amp;amp;amp;amp;amp;amp;redirect_uri=&quot; . urlencode($my_url);\r\nerror_log(&quot;top.location.href=&#039;&quot; . $dialog_url);\r\n}\r\nelse {\r\nerror_log(&quot;other error has happened&quot;);\r\n}\r\n}\r\nelse {\r\n\/\/ success\r\n\/\/error_log(&quot;success&quot; . $decoded_response-&gt;name);\r\n\/\/error_log($access_token);\r\n}\r\n\r\nreturn $access_token;\r\n\r\n}\r\n<\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>There were a few reasons I wanted to add Facebook authentication to the new iteration of Quizmo. I wanted a second form of authentication to help in abstracting authentication. I needed a second form of authentication because the intention is to open source this project, and I need to provide something other than iSites authentication [&hellip;]<\/p>\n","protected":false},"author":4571,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63924,3163,63928],"tags":[5741,63933,981,63936,63930,63934,63925],"class_list":["post-16","post","type-post","status-publish","format-standard","hentry","category-atg","category-php","category-quizmo-atg","tag-authentication","tag-curl","tag-facebook","tag-facebook-sdk","tag-php-2","tag-proxy","tag-quizmo"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/users\/4571"}],"replies":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":11,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":29,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/posts\/16\/revisions\/29"}],"wp:attachment":[{"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/acts\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}