Search code examples
phpauthenticationcurloauthhttp-headers

PHP OAuth Curl: issues passing array values "Uncaught TypeError: curl_setopt(): The CURLOPT_HTTPHEADER option must have an array value"


I'm finalising something for a uni project that requires OAuth Intergration, I'm having issues with Curl, it appears like I've copied my reference material okay but where my lecturers can get this authorisation working I can't seem to, here is the relevant code and stack trace:

Thanks in advance!

Fatal error: Uncaught TypeError: curl_setopt(): The CURLOPT_HTTPHEADER option must have an array value in /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php:11 Stack trace: #0 /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php(11): curl_setopt() #1 /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php(53): CurlHandler->__construct() #2 /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php(151): OAuth->getAuth() #3 /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php(144): ProviderHandler->processCode() #4 /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/index.php(12): ProviderHandler->performAction() #5 {main} thrown in /mnt/sdb1/home/18011506/public_html/BSCHons/WP/A1/OAuth.class.php on line 11

`<?php
require_once('defs.php');

class CurlHandler {
    public $curl;
    public function __construct($url=''){
        $this->curl = curl_init($url);
        curl_setopt($this->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($this->curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, 'Content-Type: application/x-www-form-urlencoded');
        $this->setPost();
    }

    public function setHeader($header) {
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header);
    }

    public function setPost($value = true) {
        curl_setopt($this->curl, CURLOPT_POST, $value);
    }

    public function setQuery($query = []){
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, http_build_query($query));
    }

    public function runCurl() {
        return curl_exec($this->curl);
    }
}

class OAuth {
    public $providername, $authURL, $tokenURL, $apiURL, $revokeURL, $scope;
    protected $secret, $cid;
    public function __construct($providerInfo, $cid, $secret) {
        $this->providername = $providerInfo['providername'];
        $this->authURL = $providerInfo['data']['authURL'];
        $this->tokenURL = $providerInfo['data']['tokenURL'];
        $this->apiURL = $providerInfo['data']['apiURL'];
        $this->revokeURL = $providerInfo['data']['revokeURL'];
        $this->scope = $providerInfo['data']['scope'];
        $this->cid = $cid;
        $this->secret = $secret;
    }

    public function getAuth($code) {
        $curl=new CurlHandler($this->tokenURL);
        $headers[]='Accept: application/json';
        //var_dump($headers);
        $curl->setHeader($headers);
        $params = array(
            'grant_type' => 'authorization_code',
            'client_id' => $this->cid,
            'client_secret' => $this->secret,
            'redirect_uri' => REDIRECTTOKENURI,
            'code' => $code
        );
        $curl->setQuery($params);
        $result = json_decode($curl->runCurl());
        //var_dump($result);
        return $result;
    }

    public function login() {
        $params = array(
            'client_id' => $this->cid,
            'redirect_uri' => REDIRECTURI,
            'response_type' => 'code',
            'scope' => $this->scope
        );
        header('Location: ' . $this->authURL . '?' . http_build_query($params));
        die();
    }

    public function generateLoginText() {
        $result = '<p><a href="index.php?action=login&provider='. $this->providername . '">Login with ' . $this->providername . '</a></p>';
        return $result;
    }

    public function getName() {
        return $this->userinfo->username;
    }

    public function getAvatar() {
        return $this->userinfo->avatar;
    }

    public function getUserID() {
        return $this->userinfo->id;
    }
}

class ProviderHandler {
    public $providerList=[];
    public $action, $activeProvider, $code, $access_token, $status;
    public $providerInstance;

    public function __construct() {
        if(session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        $this->action = $this->getGetParam('action');
        if($this->getGetParam('provider')){
        $this->activeProvider = $this->getGetParam('provider');
        } else {
        $this->activeProvider = $this->getSessionValue('provider');
        }
        $this->code = $this->getGetParam('code');
    }

    public function login() {
        $this->setSessionValue('provider', $this->providerInstance->providername);
        $this->status="logging in";
        $this->providerInstance->login();
    }

    public function logout() {
        echo 'logout stub';
        $this->status="logged out";
        session_unset();
        header('Location: '.$_SERVER['PHP_SELF']);
        die();
    }

    public function generateLogout() {
        return '<p><a href="index.php?action=logout">Logout</a></p>';
    }

    public function performAction() {
        foreach($this->providerList as $provider) {
            if($provider->providername == $this->activeProvider) {
                $this->providerInstance = $provider;
                if($this->action =='login'){
                    $this->login();
                } else if($this->action == 'logout') {
                    $this->logout();
                } else if($this->code){
                    $this->processCode();
                }
            }
        }
    }

    public function processCode() {
        $result = $this->providerInstance->getAuth($this->code);
        if($result->access_token) {
            $this->status = 'logged in';
            $this->setSessionValue('access_token', $result->access_token);
            $this->processToken();
        }
    }

    public function processToken() {
        $this->providerInstance->getAuthConfirm($this->getSessionValue('access_token'));
    }

    public function addProvider($name,$cid,$secret) {
        $providerInfo = $this->getProviderData($name);
        if($providerInfo !== null) {
            array_push($this->providerList, new $providerInfo['data']['class']($providerInfo,$cid,$secret));
        }
    }

    public function getProviderData($name) {
        foreach(PROVIDERLIST as $provider) {
            if($provider['providername'] == $name) {
                return $provider;
            }
            return null;
        }
    }

    public function generateLoginText() {
        $result='';
        foreach($this->providerList as $provider){
            $result.=$provider->generateLoginText();
        }
        return $result;
    }

    public function getGetParam($key, $default=null) {
        return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
    }

    public function getSessionValue($key, $default=null) {
        return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
    }

    public function setSessionValue($key, $value) {
        $_SESSION[$key] = $value;
    }
}
?>

I have tried the following and neither have worked

<?php
    public function getAuth($code) {
    $curl = new CurlHandler($this->tokenURL);
    $headers = array('Accept: application/json');
    $curl->setHeader($headers);
    // Rest of the code...
}

public function setHeader($header) {
    if (is_array($header)) {
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header);
    } else {
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, array($header));
    }
}


?>`

Solution

  • You are passing curl header as value. But it should be passed as key-value pair that means array with key value should be passed there. You can try the value code

    class CurlHandler {
        public $curl;
        public function __construct($url=''){
            $this->curl = curl_init($url);
            curl_setopt($this->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($this->curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
            //curl_setopt($this->curl, CURLOPT_HTTPHEADER, 'Content-Type: application/x-www-form-urlencoded');
            $this->setPost();
        }
    
        public function setHeader($header) {
            curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header);
        }
    
        public function setPost($value = true) {
            curl_setopt($this->curl, CURLOPT_POST, $value);
        }
    
        public function setQuery($query = []){
            curl_setopt($this->curl, CURLOPT_POSTFIELDS, http_build_query($query));
        }
    
        public function runCurl() {
            return curl_exec($this->curl);
        }
    }
    

    Now call the CurlHandler class by passing headers in setHeader() method.

    $curl = new CurlHandler($this->tokenURL);
        $headers = array(
            'Content-Type: application/x-www-form-urlencoded',
        );
    
        $curl->setHeader($headers);