Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

<?php
/**
 * OAuth2 Provider
 *
 * @package    CodeIgniter/OAuth2
 * @category   Provider
 * @author     Phil Sturgeon
 * @copyright  (c) 2012 HappyNinjas Ltd
 * @license    http://philsturgeon.co.uk/code/dbad-license
 */

abstract class OAuth2_Provider
{
        /**
         * @var  string  provider name
         */
        public $name;

        /**
         * @var  string  uid key name
         */
        public $uid_key = 'uid';

        /**
         * @var  string  additional request parameters to be used for remote requests
         */
        public $callback;

        /**
         * @var  array  additional request parameters to be used for remote requests
         */
        protected $params = array();

        /**
         * @var  string  the method to use when requesting tokens
         */
        protected $method = 'GET';

        /**
         * @var  string  default scope (useful if a scope is required for user info)
         */
        protected $scope;

        /**
         * @var  string  scope separator, most use "," but some like Google are spaces
         */
        protected $scope_seperator = ',';

        /**
         * Overloads default class properties from the options.
         *
         * Any of the provider options can be set here, such as app_id or secret.
         *
         * @param   array   provider options
         * @return  void
         */
        public function __construct(array $options = array())
        {
                if ( ! $this->name)
                {

                        // Attempt to guess the name from the class name
                        $this->name = strtolower(substr(get_class($this), strlen('OAuth2_Provider_')));

                }

                if (empty($options['id']))
                {

                        throw new Exception('Required option not provided: id');
                }

                $this->client_id = $options['id'];
                
                isset($options['callback']) and $this->callback = $options['callback'];
                isset($options['secret']) and $this->client_secret = $options['secret'];
                isset($options['scope']) and $this->scope = $options['scope'];

                $this->redirect_uri = base_url(get_instance()->uri->uri_string());
                //echo $this->redirect_uri;
        }

        /**
         * Return the value of any protected class variable.
         *
         *     // Get the provider signature
         *     $signature = $provider->signature;
         *
         * @param   string  variable name
         * @return  mixed
         */
        public function __get($key)
        {
                return $this->$key;
        }

        /**
         * Returns the authorization URL for the provider.
         *
         *     $url = $provider->url_authorize();
         *
         * @return  string
         */
        abstract public function url_authorize();

        /**
         * Returns the access token endpoint for the provider.
         *
         *     $url = $provider->url_access_token();
         *
         * @return  string
         */
        abstract public function url_access_token();

        /*
        * Get an authorization code from Facebook.  Redirects to Facebook, which this redirects back to the app using the redirect address you've set.
        */      
        public function authorize($options = array())
        {

                $state = md5(uniqid(rand(), TRUE));
                get_instance()->session->set_userdata('state', $state);


                $params = array(
                        'client_id'             => $this->client_id,
                        'redirect_uri'          => isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri,
                        'state'                         => $state,
                        'scope'                         => is_array($this->scope) ? implode($this->scope_seperator, $this->scope) : $this->scope,
                        'response_type'         => 'code',
                        'approval_prompt'   => 'force' // - google force-recheck
                );
                //print_r($params);
                
                return $this->url_authorize().'?'.http_build_query($params);
        }

        /*
        * Get access to the API
        *
        * @param        string  The access code
        * @return       object  Success or failure along with the response details
        */      
        public function access($code, $options = array())
        {
                $params = array(
                        'client_id'     => $this->client_id,
                        'client_secret' => $this->client_secret,
                        'grant_type'    => isset($options['grant_type']) ? $options['grant_type'] : 'authorization_code',
                );

                switch ($params['grant_type'])
                {
                        case 'authorization_code':
                                $params['code'] = $code;
                                $params['redirect_uri'] = isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri;
                        break;

                        case 'refresh_token':
                                $params['refresh_token'] = $code;
                        break;
                }


                $response = null;       
                $url = $this->url_access_token();

                switch ($this->method)
                {
                        case 'GET':

                                // Need to switch to Request library, but need to test it on one that works
                                $url .= '?'.http_build_query($params);
                                $ch = curl_init($url);                                                                      
                                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");                                                                   
                                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);                                                                       
                                $response = curl_exec($ch);
                                parse_str($response, $return);

                        break;

                        case 'POST':

                                $postdata = http_build_query($params);
                                // $opts = array(
                                //      'http' => array(
                                //              'method'  => 'POST',
                                //              'header'  => 'Content-type: application/x-www-form-urlencoded',
                                //              'content' => $postdata
                                //      )
                                // );
                                $ch = curl_init($url);                                                                      
                                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");                                                                     
                                curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);                                                                  
                                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);                                                                      
                                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));                                                                                                                   
                                $response = curl_exec($ch);
                                //$context  = stream_context_create($opts);
                                //$response = file_get_contents($url, false, $context);

                                $return = get_object_vars(json_decode($response));

                        break;

                        default:
                                throw new OutOfBoundsException("Method '{$this->method}' must be either GET or POST");
                }

                if ( ! empty($return['error']))
                {
                        throw new OAuth2_Exception($return);
                }
                
                return OAuth2_Token::factory('access', $return);
        }

}