Post

2 followers Follow
0
Avatar

REST API 2.0 authentication trouble

I'm sure I'm just doing it wrong, but can anyone tell me why this fails? I get either 'did you login', 'internal error', or NULL. I think the latter two are me coding it wrong though. I was messing with the headers.
public function index()
{
$clarizen_obj = new stdClass();

$url = "https://api2.clarizen.com/V2.0/services/authentication/getServerDefinition";
$post = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
$clarizen_obj->server_definition = json_decode($this->curl_post($url, $post));

$url = $url = $clarizen_obj->server_definition->serverLocation . "/authentication/login";
$post = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
$clarizen_obj->server_login = json_decode($this->curl_post($url, $post));

$url = "https://api2.clarizen.com/v2.0/services/authentication/GetSessionInfo";
$post = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
$optional_header = array('Authorization:Session ' . $clarizen_obj->server_login->sessionId);
var_dump(json_decode($this->curl_post($url, $post, array(), $optional_header)));

}

/**
* Send a POST requst using cURL
* @param string $url to request
* @param array $post values to send
* @param array $options for cURL
* @return string
*/
function curl_post($url, array $post = NULL, array $options = array(), $optional_header = array())
{
$defaults = array(
CURLOPT_HTTPHEADER => $optional_header,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_URL => $url,
CURLOPT_FRESH_CONNECT => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FORBID_REUSE => 1,
CURLOPT_TIMEOUT => 4,
CURLOPT_POSTFIELDS => http_build_query($post)
);
$ch = curl_init();
curl_setopt_array($ch, ($options + $defaults));
if( ! $result = curl_exec($ch))
{
trigger_error(curl_error($ch));
}
curl_close($ch);
return $result;
}

Marketing Mojo IT Answered

Please sign in to leave a comment.

9 comments

0
Avatar

Post data should be in JSON format:
{
userName: "theUser",
password: "thePassword"
}

if this still doesn't work, please try to get a dump of the request and response you're getting so it's easier to pinpoint the issue.

Eyal Post 0 votes
0
Avatar

Eyal,

The first two segments of code work great. Here’s the output of each returned object, jsondecoded in php then var_dump’d. Do you mean I need to jsonencode the stuff before I put it into my curl function?

object(stdClass)#19 (2) {
["serverLocation"]=>
string(39) "https://api2.clarizen.com/v2.0/services"
["appLocation"]=>
string(34) "https://app2.clarizen.com/Clarizen"
}
object(stdClass)#18 (2) {
["server_definition"]=>
object(stdClass)#19 (2) {
["serverLocation"]=>
string(39) "https://api2.clarizen.com/v2.0/services"
["appLocation"]=>
string(34) "https://app2.clarizen.com/Clarizen"
}
["server_login"]=>
object(stdClass)#20 (5) {
["sessionId"]=>
string(44) "1bf4c5a4-ccf6-4153-b55c-a17342ab3358_1209261"
["userId"]=>
string(36) "c2bc0b50-3fbf-4b21-b214-2fff73302f23"
["organizationId"]=>
string(36) "b26cac75-0087-45d8-bb85-a1d3b9ef192a"
["serverTime"]=>
string(28) "2015-06-30T19:31:28.3026421Z"
["licenseType"]=>
string(4) "Full"
}
}
object(stdClass)#21 (3) {
["errorCode"]=>
string(12) "LoginFailure"
["message"]=>
string(58) "Authentication cookie is missing. Did you forget to login?"
["referenceId"]=>
string(22) "2Wp35NeytTcu8C8JohNat3"
}

Marketing Mojo IT 0 votes
0
Avatar

Responses look good (no JSON encoding needed then).
I need to see a dump of the last request. If you can use some http proxy to dump this it will be great.
The only thing that I suspect is going wrong is the Authorization header

Eyal Post 0 votes
0
Avatar

Yep, I basically can't figure out how to stuff the SessionID into the header in an acceptable way. Is this what you need?

GET /clarizen_gantt HTTP/1.1
Host: dashboard.marketing-mojo.dev
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cookie: __atuvc=4%7C20; _ga=GA1.3.1470472789.1432307129; __ar_v4=3C2FJTIPVNE5HE5H3C6RPK%3A20150521%3A4%7COVFICYN4JVAGDFQRR757EQ%3A20150521%3A4%7CEO3M4YV435D3JDXYO2A4QB%3A20150521%3A4; ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22f9f5373c130fd5477cd450cf34027e3e%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A109%3A%22Mozilla%2F5.0+%28Windows+NT+6.3%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F43.0.2357.130+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1435611941%3B%7D55e730e34d2754d8d17f3ebe5d30ee22

Marketing Mojo IT 0 votes
0
Avatar

Here's a second header, when I pass the optional header with the authentication:sessionId.

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:__atuvc=4%7C20; _ga=GA1.3.1470472789.1432307129; __ar_v4=3C2FJTIPVNE5HE5H3C6RPK%3A20150521%3A4%7COVFICYN4JVAGDFQRR757EQ%3A20150521%3A4%7CEO3M4YV435D3JDXYO2A4QB%3A20150521%3A4; ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22f9f5373c130fd5477cd450cf34027e3e%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A109%3A%22Mozilla%2F5.0+%28Windows+NT+6.3%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F43.0.2357.130+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1435611941%3B%7D55e730e34d2754d8d17f3ebe5d30ee22
Host:dashboard.marketing-mojo.dev
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36

Marketing Mojo IT 0 votes
0
Avatar

That second one should match the code posted here. Here's the response:

object(stdClass)#21 (3) {
["errorCode"]=>
string(8) "Internal"
["message"]=>
string(74) "An internal error has occurred, the error was logged and will be examined."
["referenceId"]=>
string(22) "25NIdQpyAvtfu8JGviYygN"
}

Marketing Mojo IT 0 votes
0
Avatar

Eyal,

Fixed it! I had to explicitly define the header in the curl options, instead of setting it as part of the curl_setopt_array. Here's the working code, in case anyone else needs it. I was able to use this to fire a CZQL query and get some data back.

I do have one last question: I was able to pull an appLogin URL )attempting to use it to not have to send username/password each time), but I couldn't figure out how to assemble the url after that to make a CZQL query. Any insights?

public function index()
{
$clarizen_obj = new stdClass();

    $url = "https://api2.clarizen.com/V2.0/services/authentication/getServerDefinition";
    $post = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
    $clarizen_obj->server_definition = json_decode($this->curl_post($url, $post));      

    $url = $url = $clarizen_obj->server_definition->serverLocation . "/authentication/login";
    $post = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
    $clarizen_obj->server_login = json_decode($this->curl_post($url, $post));   

    /*
    $url = "https://api2.clarizen.com/V2.0/services/utils/appLogin";        
    $get = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
    $clarizen_obj->app_login = json_decode($this->curl_get($url, $get, array("Authorization: Session " . $clarizen_obj->server_login->sessionId) ));
    */
    //makePre($clarizen_obj); die();

    makePre($clarizen_obj);
    $url = "https://api2.clarizen.com/V2.0/services/data/query";
    $select = "SELECT Name, StartDate, Manager
                FROM Task
                WHERE StartDate>2014-01-01
                ORDER BY StartDate DESC";
    $get = array('userName' => 'it@marketing-mojo.com', 'password' => "thepassword");
    $server_query = $this->curl_get($url, $get, array("Authorization: Session " . $clarizen_obj->server_login->sessionId, "q: " . $select));
    makePre($server_query);
}


/** 
* Send a POST requst using cURL 
* @param string $url to request 
* @param array $post values to send 
* @param array $options for cURL 
* @return string 
*/ 
function curl_post($url, array $post = NULL, array $options = array()) 
{ 
    $defaults = array( 
        CURLOPT_SSL_VERIFYPEER => FALSE,
        CURLOPT_POST => 1, 
        CURLOPT_HEADER => 0, 
        CURLOPT_URL => $url, 
        CURLOPT_FRESH_CONNECT => 1, 
        CURLOPT_RETURNTRANSFER => 1, 
        CURLOPT_FORBID_REUSE => 1, 
        CURLOPT_TIMEOUT => 4, 
        CURLOPT_POSTFIELDS => http_build_query($post) 
    ); 
    $ch = curl_init(); 
    curl_setopt_array($ch, ($options + $defaults)); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, $options );
    if( ! $result = curl_exec($ch)) 
    { 
        trigger_error(curl_error($ch)); 
    } 
    curl_close($ch); 
    return $result; 
}


/** 
* Send a GET requst using cURL 
* @param string $url to request 
* @param array $get values to send 
* @param array $options for cURL 
* @return string 
*/ 
function curl_get($url, array $get = NULL, array $options = array()) 
{    
    $defaults = array( 
        CURLOPT_SSL_VERIFYPEER => FALSE,
        CURLOPT_URL => $url. (strpos($url, '?') === FALSE ? '?' : ''). http_build_query($get), 
        CURLOPT_HEADER => 0, 
        CURLOPT_RETURNTRANSFER => TRUE, 
        CURLOPT_TIMEOUT => 4 
    ); 

    $ch = curl_init(); 
    curl_setopt_array($ch, ($options + $defaults)); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, $options );
    if( ! $result = curl_exec($ch)) 
    { 
        trigger_error(curl_error($ch)); 
    } 
    curl_close($ch); 
    return $result; 
} 
Marketing Mojo IT 0 votes
0
Avatar

The purpose of the AppLogin API is to log you in "silently" to the application rather than the API and in any case this URL has a short expiration so you can't really persist it.

Eyal Post 0 votes