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

Source for file GOOGLE.php

Documentation is available at GOOGLE.php

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

Documentation generated on Fri, 30 Aug 2024 06:10:27 +0900 by phpDocumentor 1.4.4