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
Answers
In the end, it was the missing " before signature value. Such a basic error.
You need to base64-encode the hash in its "lower-case hexits" form, not its binary form.
hash_hmac with fourth parameter set to true, gets you the binary form.
is what you need.