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

Source for file DAUM.php

Documentation is available at DAUM.php

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

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