oops-OAUTH2
[ class tree: oops-OAUTH2 ] [ index: oops-OAUTH2 ] [ all elements ]

Source for file FACEBOOK.php

Documentation is available at FACEBOOK.php

  1. <?php
  2. /**
  3.  * Project: oops\OAUTH2\FACEBOOK:: Facebook oauth2 pear package<br>
  4.  * File:    FACEBOOK.php<br>
  5.  * Dependency:
  6.  *   - {@link http://pear.oops.org/docs/li_HTTPRelay.html oops/HTTPRelay}
  7.  *   - {@link http://pear.oops.org/docs/li_myException.html oops/myException}
  8.  *
  9.  * oops\OAUTH2\FACEBOOK pear package는 Facebook oauth2 login을 위한
  10.  * pear package이다
  11.  *
  12.  * 이 package를 사용하기 위해서는 먼저 Facebook Developers Console 에서
  13.  * Application ID와 Application Secret을 발급받아야 한다.
  14.  * http://www.facebook.com/developers/createapp.php 에서 생성할 수 있다.
  15.  *
  16.  * @category  HTTP
  17.  * @package   oops\OAUTH2
  18.  * @subpackage   oops\OAUTH2\FACEBOOK
  19.  * @author    JoungKyun.Kim <http://oops.org>
  20.  * @copyright (c) 2019, OOPS.org
  21.  * @license   BSD License
  22.  * @example   OAUTH2/tests/facebook.php FACEBOOK pear package 예제 코드
  23.  * @filesource
  24.  */
  25.  
  26. namespace oops\OAUTH2;
  27.  
  28. /**
  29.  * import HTTPRelay class
  30.  */
  31. require_once 'HTTPRelay.php';
  32.  
  33.  
  34. /**
  35.  * oops\OAUTH2\FACEBOOK pear pcakge의 main class
  36.  *
  37.  * OAuth2를 이용하여 FACEBOOK 로그인을 진행하고, 로그인된 사용자의
  38.  * 정보를 얻어온다.
  39.  *
  40.  * @package   oops\OAUTH2
  41.  * @subpackage   oops\OAUTH2\FACEBOOK
  42.  * @author    JoungKyun.Kim <http://oops.org>
  43.  * @copyright (c) 2019, OOPS.org
  44.  * @license   BSD License
  45.  * @example   OAUTH2/tests/facebook.php FACEBOOK pear 예제 코드
  46.  */
  47. Class FACEBOOK {
  48.     // {{{ properities
  49.     /**#@+
  50.      * @access private
  51.      */
  52.     /**
  53.      * 세션 이름
  54.      * @var string 
  55.      */
  56.     private $sessid   '_OAUTH2_';
  57.     /**
  58.      * login url
  59.      * @var string 
  60.      */
  61.     private $reqAuth  'https://www.facebook.com/dialog/oauth';
  62.     /**
  63.      * token url
  64.      * @var string 
  65.      */
  66.     private $reqToken 'https://graph.facebook.com/v2.11/oauth/access_token';
  67.     /**
  68.      * revoke url
  69.      * @var string 
  70.      */
  71.     private $reqRevoke 'https://www.facebook.com/logout.php';
  72.     /**
  73.      * user information url
  74.      * @var string 
  75.      */
  76.     private $reqUser  'https://graph.facebook.com/v2.11/me';
  77.     /**
  78.      * app information
  79.      * @var stdClass memebr는 다음과 같음
  80.      *    - id     : Facebook login Application ID
  81.      *    - secret : Facebook login Application Secret key
  82.      *    - callback : 이 class를 호출하는 페이지
  83.      */
  84.     private $apps;
  85.     /**
  86.      * SSL type
  87.      * @var string 
  88.      */
  89.     private $proto 'http';
  90.     /**#@-*/
  91.     /**
  92.      * FACEBOOK 로그인에 필요한 session 값
  93.      * @access public
  94.      * @var stdClass 
  95.      */
  96.     public $sess;
  97.     // }}}
  98.  
  99.     // {{{ +-- public (void) __construct ($v)
  100.     /**
  101.      * Facebook 로그인 인증 과정을 수행한다. 인증 과정 중에
  102.      * 에러가 발생하면 myException 으로 에러 메시지를
  103.      * 보낸다.
  104.      *
  105.      * @access public
  106.      * @param stdClass $v 
  107.      *    - id       발급받은 Facebook login Application ID
  108.      *    - secret   발급받은 Facebook login Application Scret key
  109.      *    - callback 이 클래스가 호출되는 url
  110.      *    - popup    true 일 경우, requset URL에 popup login 옵션을 추가
  111.      * @return void 
  112.      */
  113.     function __construct ($v{
  114.         if isset ($_SESSION[$this->sessid]) ) {
  115.             $_SESSION[$this->sessidnew \stdClass;
  116.             $_SESSION[$this->sessid]->appId = (object) $v;
  117.         }
  118.         $this->sess = &$_SESSION[$this->sessid];
  119.         $this->apps = (object) $v;
  120.  
  121.         if isset ($_SERVER['HTTPS']) )
  122.             $this->proto .= 's';
  123.  
  124.         if isset ($_GET['logout']) ) {
  125.             $this->reqLogout ();
  126.             return;
  127.         }
  128.  
  129.         $this->checkError ();
  130.         $this->reqLogin ();
  131.         $this->reqAccessToken ();
  132.     }
  133.     // }}}
  134.  
  135.     // {{{ +-- private (string) mkToken (void)
  136.     /**
  137.      * 세션 유지를 위한 token 값
  138.      *
  139.      * @access private
  140.      * @return string 
  141.      */
  142.     private function mkToken ({
  143.         $mt microtime ();
  144.         $rand mt_rand ();
  145.         return md5 ($mt $rand);
  146.     }
  147.     // }}}
  148.  
  149.     // {{{ +-- private (void) reqLogin (void)
  150.     /**
  151.      * 로그인 창으로 redirect
  152.      *
  153.      * @access private
  154.      * @return void 
  155.      */
  156.     private function reqLogin ({
  157.         $app &$this->apps;
  158.         $this->sess->state $this->mkToken ();
  159.  
  160.         if $_GET['code'|| isset ($this->sess->oauth)  )
  161.             return;
  162.  
  163.         $opt $this->apps->popup '&display=popup' '';
  164.  
  165.         $url sprintf (
  166.             '%s?scope=email&client_id=%s&response_type=code&redirect_uri=%s&state=%s%',
  167.             $this->reqAuth$app->id,
  168.             rawurlencode ($app->callback)$this->sess->state$opt
  169.         );
  170.  
  171.         Header ('Location: ' $url);
  172.         exit;
  173.     }
  174.     // }}}
  175.  
  176.     // {{{ +-- private (void) reqAccessToken (void)
  177.     /**
  178.      * Authorization code를 발급받아 session에 등록
  179.      *
  180.      * FACEBOOK::$sess->oauth 를 stdClass로 생성하고 다음의
  181.      * member를 등록한다.
  182.      *
  183.      *   - access_token:      발급받은 access token. expires_in(초) 이후 만료
  184.      *   - refresh_token:     access token 만료시 재발급 키 (14일 expire)
  185.      *   - token_type:        Bearer or MAC
  186.      *   - expires_in:        access token 유효시간(초)
  187.      *   - error:             error code
  188.      *   - error_description: error 상세값
  189.      *
  190.      * @access private
  191.      * @return void 
  192.      */
  193.     private function reqAccessToken ({
  194.         $sess &$this->sess;
  195.         $app  &$this->apps;
  196.  
  197.         if $_GET['code'|| isset ($sess->oauth) )
  198.             return;
  199.  
  200.         $post array (
  201.             'code' => $_GET['code'],
  202.             'client_id' => $app->id,
  203.             'client_secret' => $app->secret,
  204.             'redirect_uri' => $app->callback
  205.         );
  206.  
  207.         $http new \HTTPRelay;
  208.         $buf $http->fetch ($this->reqToken10''$post);
  209.  
  210.         /* {{{ For graph api 2.0
  211.         parse_str ($buf, $output);
  212.         $r = (object) $output;
  213.         unset ($output);
  214.         }}} */
  215.         // For graph api 2.6
  216.         $r json_decode ($buf);
  217.  
  218.         if $r->error )
  219.             $this->error ($r->error_description);
  220.  
  221.         $sess->oauth = (object) $r;
  222.     }
  223.     // }}}
  224.  
  225.     // {{{ +-- private (void) checkError (void)
  226.     /**
  227.      * 에러 코드가 존재하면 에러 처리를 한다.
  228.      *
  229.      * @access private
  230.      * @return void 
  231.      */
  232.     private function checkError ({
  233.         $sess &$this->sess;
  234.  
  235.         if $_GET['error')
  236.             $this->error ($_GET['error_description']);
  237.  
  238.         if $_GET['state'&& $_GET['state'!= $sess->state )
  239.             $this->error ('Invalude Session state: ' $_GET['state']);
  240.     }
  241.     // }}}
  242.  
  243.     // {{{ +-- private (void) error ($msg)
  244.     /**
  245.      * 에러를 Exception 처리한다.
  246.      *
  247.      * @access private
  248.      * @return void 
  249.      */
  250.     private function error ($msg{
  251.         $msg $_SERVER['HTTP_REFERER'"\n" $msg;
  252.         throw new \myException ($msgE_USER_ERROR);
  253.     }
  254.     // }}}
  255.  
  256.     // {{{ +-- private (string) redirectSelf (void)
  257.     /**
  258.      * 현재 URL에 after argument를 set한다.
  259.      *
  260.      * @access private
  261.      * @return string 
  262.      */
  263.     private function redirectSelf ({
  264.         if trim ($_SERVER['QUERY_STRING']) )
  265.             $qs sprintf ('?%s&after'$_SERVER['QUERY_STRING']);
  266.         else
  267.             $qs '?after';
  268.  
  269.         $req preg_replace ('/\?.*/'''trim ($_SERVER['REQUEST_URI']));
  270.         if $req $req '/';
  271.  
  272.         return sprintf (
  273.             '%s://%s%s%s',
  274.             $this->proto$_SERVER['HTTP_HOST']$req$qs
  275.         );
  276.     }
  277.     // }}}
  278.  
  279.     // {{{ +-- public (stdClass) Profile (void)
  280.     /**
  281.      * 로그인 과정이 완료되면 발급받은 oops\OAUTH2\FACEBOOK::$sess->oauth에
  282.      * 등록된 키를 이용하여 로그인 사용자의 정보를 가져온다.
  283.      *
  284.      * @access public
  285.      * @return stdClass 다음의 object를 반환
  286.      *    - id     사용자 UID
  287.      *    - name   사용자 별칭
  288.      *    - email  이메일
  289.      *    - img    프로필 사진 URL 정보
  290.      *    - r      facebook original profile 정보
  291.      */
  292.     public function Profile ({
  293.         $sess &$this->sess;
  294.  
  295.         if isset ($sess->oauth) )
  296.             return false;
  297.  
  298.         #$req = $sess->oauth->token_type . ' ' . $sess->oauth->access_token;
  299.         #$req = 'HMAC-SHA256 ' . $sess->oauth->access_token;
  300.  
  301.         #$header = array ('Authorization' => $req);
  302.         #$http = new \HTTPRelay ($header);
  303.         #$buf = $http->fetch ($this->reqUser);
  304.         #$r = json_decode ($buf);
  305.  
  306.         $url sprintf (
  307.             '%s?access_token=%s',
  308.             $this->reqUser,
  309.             $sess->oauth->access_token
  310.         );
  311.         $http new \HTTPRelay ();
  312.         $buf $http->fetch ($url);
  313.  
  314.         if $buf )
  315.             $this->error (sprintf ('[OAUTH2] Failed get user profile for %s'__CLASS__));
  316.  
  317.         #stdClass Object
  318.         #(
  319.         #    [id] => 사용자 확인값
  320.         #    [name] => 사용자 이름
  321.         #    [email] => 사용자 email
  322.         #    [gender] => 사용자 성별
  323.         #    [img] => stdClass Object
  324.         #)
  325.         $op json_decode ($buf);
  326.  
  327.         // facebook은 개인 정보가 너무 많아서 좀 줄일 필요가 있음
  328.         if is_object ($op) ) {
  329.             unset ($op->wokr);
  330.             unset ($op->location);
  331.             unset ($op->hometown);
  332.         }
  333.  
  334.         $r array (
  335.             'id' => $op->id,
  336.             'name' => preg_replace ('/[ ]+/'' 'htmlspecialchars ($op->name)),
  337.             'email' => $op->email,
  338.             'img'  => sprintf ('%s://graph.facebook.com/%s/picture'$this->proto$op->id),
  339.             'r' => $op
  340.         );
  341.         unset ($op);
  342.  
  343.         return (object) $r;
  344.     }
  345.     // }}}
  346.  
  347.     // {{{ +-- public (void) reqLogout (void)
  348.     /**
  349.      * Facebook 로그인의 authorization key를 만료 시키고
  350.      * 세션에 등록된 정보(oops\OAUT2\FACEBOOK::$sess)를 제거한다.
  351.      *
  352.      * @access public
  353.      * @return void 
  354.      */
  355.     public function reqLogout ({
  356.         $sess &$this->sess;
  357.         $app  &$this->apps;
  358.  
  359.         if isset ($sess->oauth) )
  360.             return;
  361.  
  362.         if isset ($_GET['after']) ) {
  363.             /*
  364.             $next = sprintf (
  365.                 '%s?logout&after&redirect=%s',
  366.                 $app->callback, $_GET['redirect']
  367.             );
  368.              */
  369.             $url sprintf (
  370.                 '%s?access_token=%s&next=%s',
  371.                 $this->reqRevoke$sess->oauth->access_token,
  372.                 rawurlencode ($this->redirectSelf ())
  373.             );
  374.  
  375.             Header ('Location: ' $url);
  376.             exit;
  377.         }
  378.  
  379.         unset ($_SESSION[$this->sessid]);
  380.     }
  381.     // }}}
  382. }
  383.  
  384. /*
  385.  * Local variables:
  386.  * tab-width: 4
  387.  * c-basic-offset: 4
  388.  * End:
  389.  * vim600: noet sw=4 ts=4 fdm=marker
  390.  * vim<600: noet sw=4 ts=4
  391.  */
  392. ?>

Documentation generated on Tue, 14 May 2019 02:00:01 +0900 by phpDocumentor 1.4.4