Failing to generate correct OAuth 1.0 signature with PHP

56 views Asked by At

I'm trying to use vanilla PHP to get some data from an API with oAuth 1.0 authorization. My code is below, the API keeps responding to it with code 401: Invalid signature. As far as I can see, the method for generating signature conforms with examples from documentation and from Stack Overflow, so I'm not sure what I'm doing wrong. Is there perhaps a problem with my nonce?

const consumer_key = "20CECD28B41A458E9E328BB45C26EACB";
const consumer_secret = "F485B390C5854A69A8DA17554E689D03";
const token = "5F3C117598A14BE8B7136659AB2251C0";
const token_secret = "647E14C4F7EF4DA5AA119D5C60E95114";

function generateNonce($timestamp){
    $TimeReduced = substr($timestamp, 0, -2);
    $string = $TimeReduced;
    $hash = hash('sha1', $string, false);
    return $hash;
}

function generateSignature($request, $timestamp, $nonce){
  $base = $request['method']."&".rawurlencode($request['url'])."&"
      .rawurlencode("oauth_consumer_key=".rawurlencode(consumer_key)
      ."&oauth_nonce=".rawurlencode($nonce)
      ."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
      ."&oauth_timestamp=". rawurlencode($timestamp)
      ."&oauth_token=".rawurlencode(token)
      ."&oauth_version=".rawurlencode("1.0"));

    $key = rawurlencode(consumer_secret).'&'.rawurlencode(token_secret);
    $signature = base64_encode(hash_hmac('SHA1', $base, $key, true));
    return $signature;
}

$ch = curl_init();

$request = array();
$request['url'] = 'https://someniceapi.com';
$request['method'] = 'GET';

curl_setopt($ch, CURLOPT_URL, $request['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['method']);

$timestamp = time();
$nonce = generateNonce($timestamp);
$signature = generateSignature($request, $timestamp, $nonce);
$headers = array();
$headers[] = 'Authorization: OAuth oauth_consumer_key="'.consumer_key.'",oauth_token="'.token.'",oauth_signature_method="HMAC-SHA1",oauth_signature='.$signature.'",oauth_timestamp="'.$timestamp.'",oauth_nonce="'.$nonce.'",oauth_version="1.0"';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
2

There are 2 answers

0
PaulJK On BEST ANSWER

In the end, it was the missing " before signature value. Such a basic error.

7
CBroe On

You need to base64-encode the hash in its "lower-case hexits" form, not its binary form.

$signature = base64_encode(hash_hmac('SHA1', $base, $key, true));

hash_hmac with fourth parameter set to true, gets you the binary form.

$signature = base64_encode(hash_hmac('SHA1', $base, $key));

is what you need.