Facebook PHP SDK è§£äœæ°æž 第5åãJavaScript SDK ãšé£æºããŠãéã«é©åã« Access Token ãååŸã§ããªãåé¡ã«ã€ããŠã
ããã«ã¡ã¯ã @sotarok ã§ãã Facebook PHP SDK ã«ã€ããŠæ·±ãã解説ããããè§£äœæ°æžãã·ãªãŒãºã仿¥ã¯ãããŠæžããã§ãããããªã第5åããè¡ã£ãŠã¿ãããšæããŸãã
ãšããããã§ã衚é¡ã®éãããJavaScript SDK ãšé£æºããŠãéã«é©åã« Access Token ãååŸã§ããªãåé¡ã«ã€ããŠãã®ã話ãããŸãã
â» ã¡ãªã¿ã«å·ç次ç¹ã§ãªãªãŒã¹ãããŠãã Facebook PHP SDK v.3.1.1 ãããŒã¹ãšããŠããŸãã
è£è¶³ã®åæç¥èãJavaScript SDK ãš PHP SDK ã®é£æº
Facebook PHP SDK ã¯ãJavaScript SDK ãšãç¹ã«äœãæèããã« COOKIE ãä»ããŠé£æºããŠããŸããå
·äœçã«ã¯ãJS ã§ FB.init() ãããéã«çæããã fbsr_xxxxx ãšãã COOKIE ã PHP SDK ãèªã¿åãããã®æ
å ± (Signed Request çžåœã®ããŒã¿ãæ ŒçŽãããŠããŸã) ãå
ã« PHP SDK äžã§ããã°ã€ã³ããããšãã§ããããã«ãªã£ãŠããŸãã
çªç¶çºçãã¯ããããšã©ãŒ
Facebook ã§ã¯ããããããšã§ãããä»ãŸã§åããŠããã³ãŒãããAPIãµãŒããŒåŽã«æœãããäœãã«ãã£ãŠåããªããªããšèšãããšããããŸãã ã§ã仿¥åºäŒã£ãã®ã¯ã
$facebook->getAccessToken();
ãåããªãïŒãšããåé¡ã§ããç¹ã«èªèšŒåšãäœãããã£ãŠããªãã®ã«ã次ã®ãã㪠OAuthException ãçºçããããã«ãªããŸããã
This authorization code has expired.
人ã«ãã£ãŠçºçãããããªãã£ãã
ã¢ããªã«ãã£ãŠçºçãããããªãã£ãã
ãšããç¶æ³ã§ããããããªé°å²æ°ãåºãŠããŸããããã£ãããããããããã¿ã€ãã«ã§èšäºãæžããŠããŸãããJavaScript SDK ãšé£æºããŠããããã§çºçããŠãããšã©ãŒã ãšããããšã«æ°ã¥ããã®ã¯ã»ãšãã©è§£æ±ºããçŽåã§ããã
ãã®ãšã©ãŒã¯ã getAccessToken() ãåŒãã éã«çºçããŠããã®ã§ããããããçºèŠããã«è³ã£ãçµç·¯ãå«ããã詳ããèŠãŠããããšã«ããŸãã
ã³ãŒã«ãããAPIãšãã®çµæ
éçºç°å¢ã§åçŸæ¡ä»¶ãæ¢ããªãã§ãæé ãæå°éã«ãããããæ¬¡ã®ãããªç»é¢é·ç§»ã®ã¿ã«çµã£ãŠæ€èšŒãããŸããã
PHP SDK ã® getLoginUrl() ã¡ãœããã§ååŸã§ãã URL ã«ãžã£ã³ã (ãåãã®éããé£ã³å
㯠Facebook ã®èªèšŒç»é¢)
æ»ã£ãŠããããŒãžã§ getAccessToken() ã¡ãœããã§ Access Token ãååŸ
ã€ãŸããHTTPãªã¯ãšã¹ãçã«ã¯ã
ãã¡ã®ã¢ããªã§ãã°ã€ã³çšURLã®çæ
ãã¡ã®ã¢ããªã« code ãã©ã¡ãŒã¿ä»ãã§æ»ã£ãŠããããããå
ã« Access Token ãååŸ
ãšããé·ç§»ãããŸããäžå¿åŒç€Ÿã®ã©ã€ãã©ãªã§ã¯ãFacebook PHP SDK ããªã¯ãšã¹ãé£ã°ãéšåã«æããããŠã
ã©ããªãªã¯ãšã¹ããé£ãã§ã
ã©ããªçµæãè¿ã£ãŠããŠããã®ãã
ããã¹ãŠãã°ã«åºããããã«ãªã£ãŠããŸãããã®ãšãçºçãããã°ã¯ãã2.ãã®ã¿ã€ãã³ã°ã§ã
[2012-07-10 17:26:42] app.DEBUG: Facebook API[1]: https://graph.facebook.com/oauth/access_token - {"client_id":"10472078961xxxx","client_secret":"daa8a082d4db023bf1316f2e49dfxxxx","redirect_uri":"","code":"2.AQCOriuA5Anxxxxx.3600.1341910800.1-58888xxxx|1341905535|iOoQHNn-ZPesX6RsXBwUCibxxxx"} (10472078961xxxx|daa8a082d4db023bf1316f2e49dxxxxx) [] [] [2012-07-10 17:26:43] app.DEBUG: Facebook API[1] result: {"error":{"message":"This authorization code has expired.","type":"OAuthException","code":100}} [] []
ãšãããã°ãåºãŠããŸããããã®ãšããFacebookããã©ãããããã©ã¡ãŒã¿ä»ãã§æ»ã£ãŠããããšãããšãæ£åžžã«èªèšŒãå®äºãã /login/check?state=xxxxxxxxx&code=XXXXXXXXXXXXX ã®ããã«ãCSRFãã§ãã¯çštokenã§ããstate (ä»åã¯è©³ããã¯èšåããŸãã) ãš Access Token ååŸã®ããã® code ã query string ã«ä»äžããŠæ»ã£ãŠããŠããŸããã ã§ããã®ç»é¢ã§ã/oauth/access_token ã« code ãã€ããŠãªã¯ãšã¹ããéã£ãã¿ã€ãã³ã°ã§ãOAuthException ã® "This authorization code has expired." ãçºçããããšããããšã§ãã
æå°ã®æé ã§ãããçºçãããšããããšã¯ããã getAccessToken() ãæªãããŠããããããŸããããšããããšã§ããã®ã¡ãœããã®äžèº«ãèŠãŠãããŸãã
getAccessToken() ãããããš
public function getAccessToken() { if ($this->accessToken !== null) { return $this->accessToken; } $this->setAccessToken($this->getApplicationAccessToken()); $user_access_token = $this->getUserAccessToken(); if ($user_access_token) { $this->setAccessToken($user_access_token); } return $this->accessToken; }
ããããã¡ãœããã§ãã€ãŸãã
$this->access_token ãã»ãããããŠãããããã€ãè¿ã
ããã©ã«ãå€ãšããŠãšãããã Application Access Token ãã»ãããã
ããã¯ã APP_ID ãš APP_SECRET ããã€ã | ã§ã€ãªãã ãã®ã§ã
User Access Token ãååŸã§ããããããã€ãã»ãããã
ã§ããã®äžã§æªããã®ã¯ããšãããã/oauth/access_token ã«ãªã¯ãšã¹ããé£ã°ãã®ã¯ãæããã« getUserAccessToken() ã§ãã
getUserAccessToken() ãããããš
ã¡ãœããã¯ã次ã®ããã«ãªã£ãŠããŸãã
protected function getUserAccessToken() { // first, consider a signed request if it's supplied. // if there is a signed request, then it alone determines // the access token. $signed_request = $this->getSignedRequest(); if ($signed_request) { // apps.facebook.com hands the access_token in the signed_request if (array_key_exists('oauth_token', $signed_request)) { $access_token = $signed_request['oauth_token']; $this->setPersistentData('access_token', $access_token); return $access_token; } // the JS SDK puts a code in with the redirect_uri of '' if (array_key_exists('code', $signed_request)) { $code = $signed_request['code']; $access_token = $this->getAccessTokenFromCode($code, ''); if ($access_token) { $this->setPersistentData('code', $code); $this->setPersistentData('access_token', $access_token); return $access_token; } } // signed request states there's no access token, so anything // stored should be cleared. $this->clearAllPersistentData(); return false; // respect the signed request's data, even // if there's an authorization code or something else } $code = $this->getCode(); if ($code && $code != $this->getPersistentData('code')) { $access_token = $this->getAccessTokenFromCode($code); if ($access_token) { $this->setPersistentData('code', $code); $this->setPersistentData('access_token', $access_token); return $access_token; } // code was bogus, so everything based on it should be invalidated. $this->clearAllPersistentData(); return false; } // as a fallback, just return whatever is in the persistent // store, knowing nothing explicit (signed request, authorization // code, etc.) was present to shadow it (or we saw a code in $_REQUEST, // but it's the same as what's in the persistent store) return $this->getPersistentData('access_token'); }
ã³ãŒãäžã®ã³ã¡ã³ãã解説ããŠãããŠããŸãããä»åç»é¢é·ç§»ã®å ŽåãšããããŠè§£èª¬ãããšã
Signed Request ããã£ããããã䜿ã£ãŠ access token ããšãã«ããã
Signed Request ã¯ãFacebook App Canvas ã Page App ã® Canvas ã§éãããšããiframe ããã«ãããªã¯ãšã¹ããªã®ã§ãä»åã®ãããªãApp Canvas å
ã§ã¯ãªãå Žæã§å©çšããŠããã¢ããªã§ã¯åºæ¬çã«é¢ä¿ãªãïŒã¯ãã§ããïŒ
ãããããªãã£ãã code ã䜿ã£ãŠãAccess Token ãååŸãã«ããã
ä»åã®å ŽåãFacebookã®èªèšŒç»é¢ãã code ä»ãã§æ»ã£ãŠããã®ã§ããã£ã¡ã§ãªã¯ãšã¹ããé£ã¶ã¯ãã§ãã
Signed Request ããªããŠãcode ããªãã£ãããäžå¿æåŸã«ãPersistent Data (ã»ãã·ã§ã³ã§ã) ã«å
¥ã£ãŠã access token ãè¿ãã
ä»åã¯ããã«ã¯ããªãã¯ã
ãšããåŠçã«ãªã£ãŠããŸãã
ãšã©ãŒã¡ãã»ãŒãžããThis authorization code has expired.ããªã®ã§ã/oauth/access_token ã«å¯Ÿã㊠Access Token ã®çºè¡ã®ãªã¯ãšã¹ããé£ã°ãã¿ã€ãã³ã°ã§ã€ããŠãã code ã expire ããŠããã£ãŠããšã£ãœãã®ã§ããŸããã©ã㪠code ã䜿ã£ãŠãã®ãã確èªããŸãã ããããå Žåã¯åœç¶å¿
殺ã®ãvar_dump()ãšexitããªã®ã§ã次ã®ããã«ãcode ãåºåããŠã¿ãŸãã
$code = $this->getCode(); var_dump($code);exit;
ãã®ç¶æ
ã§ãåãé·ç§»ããã¹ããããš ...
ã ... code ãåºåãããªãïŒ
ãããcode ã®ãšããã«æ¥ãŠãªãïŒã£ãŠããšã¯ signed_request ã«äœãå
¥ã£ãŠããã ã£ãïŒãšããçãã®ããšã以äžã®ããã«ãããã°ã³ãŒããä»èŸŒããš ...
$signed_request = $this->getSignedRequest(); error_log(var_export($signed_request, true));
[10-Jul-2012 08:31:36 UTC] array ( 'algorithm' => 'HMAC-SHA256', 'code' => '2.AQCOriuA5Anxxxxx.3600.1341910800.1-58888xxxx|1341905535|iOoQHNn-ZPesX6RsXBwUCibxxxx', 'issued_at' => '1341909094', 'user_id' => '58888xxxx', )
èŠäºã«ãå
¥ã£ãŠããŸããããã®ãšããããšããã®ã§ãããããã¯ãJavaScript SDK ã«ãã£ãŠå
¥ãããããã®ã§ãã getSignedRequest() ã®äžèº«ã¯ä»åã¯ç޹ä»ããŸãããã倧ãŸãã«ãããšãPOST ãªã¯ãšã¹ãã§ Signed Request ã®ããŒã¿ãæž¡ãããŠããã°ããããããããªããã° COOKIE ãã埩å
ãšããæé ã§ Signed Request ãè¿ããŠããŠããããã§ãã
ã€ãŸããèªèšŒæé ã§ Facebook ãã code ãè¿ãããŠããã«ãããããããããã䜿ãããããããå€ãã«JSã§èšå®ããã Signed Request å
ã® code ã䜿ã£ãŠ access token ããšãã«ãããã expire ããŠãŸãã ããšãã話ã§ããïŒ ãããç¡èŠããŠãã¯ãšãªã§æž¡ããã code ã䜿ã£ãŠèªèšŒããã°ãæ£åžžã« Access Token ãååŸããããšãã§ããŸããã
人ã«ãã£ãŠã»ã¢ããªã«ãã£ãŠçºçãããããªãã£ããããã®ã¯ããã®äººã® COOKIE ã«ãã®ã¢ããªã®ããŒã¿ãæ®ã£ãŠãããã©ããã«ããããã§ããã
仿¥çªç¶èµ·ããããã«ãªã£ãããšã«å¯Ÿããæ³å
ä»ãŸã§ã¯ãcode ã«å¯Ÿãã expire ã®ãã§ãã¯ãããŠããªãã£ãã®ã§ã¯ãªãã
ã€ãŸããJavaScript SDK ã«ãã£ãŠ COOKIE ã«ã€ã£ããŸããå€ã code ãå
ã« Access Token ã®çºè¡ãã§ãã
ãããããŸããããããšããã£ãäžã®äººãã€ãã« expire ã®ãã§ãã¯ãããããã«ãªã£ã
ãããããã®ããã«ã
query string ãªã©ã« code ãåãåã£ãŠããŠããSigned Request ããã£ãããããæåªå
ã§èªèšŒã«äœ¿ã
Signed Request 㯠JavaScript SDK ã«ãã£ãŠã»ãããããå¯èœæ§ããã
ãšãã仿§ã«ãªã£ãŠããã®ã§ããã°ããSigned Request ãå
ã« Access Token ãåãã«è¡ãããšããã®ã¯ãå¿
èŠã ãšããŠãæ£èŠã®èªèšŒçµè·¯ã§æ»ã£ãŠã㊠code ã query string ã«æž¡ãããŠããŠããã€ãJavaScript SDK ã«ãã£ãŠ COOKIE ã« Signed Request ãã»ãããããŠããããšããå Žåãååšããã®ã§ã Signed Request ãå
ã« access token ãååŸãã«ãã£ãŠãã ããªã query string ã«æž¡ããã code ãå
ã« Access Token ããšãã«ãããšãã fallback åŠçãããã¹ããªã®ã§ã¯ãªããããšããæãã§ãã Signed Request ã Signed Request ã«ãããã®ãªã®ããJavaScript SDKã«ãããã®ãªã®ãåºå¥ãããŠããªãã®ã§ã
ãšããã§ããã®åé¡ã¯ã以äžã®æ¡ä»¶äžã§çºçããŸãã
ã©ããã§ãã®ã¢ããªã FB.init ãããããšãããããã®æç¹ããäžå®æéãçµéããŠãã (expire ããçšåºŠã«ã¯)
getLoginUrl() ãã³ãŒã«ãã㊠Facebook ã«ãžã£ã³ãããåã« FB.init() ãããå Žæãç¡ããCOOKIE ãçããŠãã
ãã®æ¡ä»¶ãæºãããªãå Žåã¯åé¿ã§ããã§ãããã(ããšãã°ãgetLoginUrl() ã®URLã«ãžã£ã³ãããçŽåã®ç»é¢ã§ JS ã§ FB.init() ãããŠãããšã)
ã¡ãªã¿ã«ãAuthorization Request ã® code ã«é¢ããŠã¯ãOAuth 2.0 ã®ææ°ã® proposal ã«ã¯ã以äžã®ãããªèšè¿°ããããŸãã
4.1.2. Authorization Response
code REQUIRED. The authorization code generated by the authorization server. The authorization code MUST expire shortly after it is issued to mitigate the risk of leaks. A maximum authorization code lifetime of 10 minutes is RECOMMENDED. The client MUST NOT use the authorization code more than once.
code ã® lifetime ã¯æå€§ã§ã 10 åãæãŸãã
client ã¯ãauthorization code ã¯1åããã€ãã£ã¡ãã ã
ãã®ãããããã¡ãããšãã§ãã¯ããããã«ãªã£ããã§ããã(ããŸãŸã§ãã£ãŠãªãã£ã...?)ã
FB.init() ããç»é¢ãæã
èªèšŒã®ãªã¯ãšã¹ãåã« COOKIE æ¶ã
getUserAccessToken() ã« Signed Request â code ã® fallback åŠçãå
¥ãã
ãšãã£ããã®ãèããããŸãããä»åã¯ã¢ããªã®ç»é¢é·ç§»ã®ç¹æ§äžãCOOKIE æ¶ãããšã«ããŸããããšããããdestroySession() ã¡ãœãããåŒã¶ããšã«ããŸãã
æ¬æ¥ãCOOKIE ã PHP ã«ãšã£ãŠ Persistent Data ã«è¿ãååšãšããŠæ±ãããã®ã§ãclearAllPersistentData() ã®ã¿ã€ãã³ã°ã§ COOKIE ãæ¶ãã¹ããªããããªãããªãŒãšæã£ãŠããŸãããåŸæ¥ãã®ãžãã®ã¢ã€ãã¢ããŸãšã㊠SDK ã®ä¿®æ£æ¡ã Pull Request ã§ãããŠã¿ãããšæããŸãã ããã°æžããŠããç²ããã®ã§ãŸãåŸæ¥ ...
JS SDK ãšé£æºããŠããšãCOOKIE ã§æå€ãšããã
çªç¶ãšã©ãŒã«ãªã£ãããã
ãŸãã ãããã³ãŒãã«æžããŠããã®ã§1ã€ãã€è¿œãã°åå ã¯ããã
ã§ã¯ã第1ã4åãš6å以éããæåŸ
ãã ããã æ¬¡åã¯ãJS SDK ãšé£æºããŠããéã«ãŠãŒã¶ã®åãæ¿ãããæ€ç¥ã§ããªãåé¡ã«ã€ããŠãããå±ãããäºå®ã§ãã