First, a note: My host does not have the PECL OAUTH or HTTP extensions installed.
The purpose of this: I'm hoping to create an interface to easily follow and unfollow a given list of Tumblr names.
Problem: Can't get past the authentication step.
Code:
$request_url = 'http://www.tumblr.com/oauth/request_token';
$consumer_key = COSUMER_KEY;
$consumer_secret = CONSUMER_SECRET;
$oauth_key = urlencode_rfc3986($consumer_secret) . '&';
$time = time();
$nonce = md5(microtime() . mt_rand());
$callback_url = 'http://krisallengallery.com/easyfollowr/index.php';
$params = array('oauth_consumer_key' => $consumer_key,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => $time,
'oauth_nonce' => $nonce,
'oauth_version' => '1.0a',
'oauth_callback' => $callback_url);
uksort($params, 'strcmp');
$oauth_header = 'Authorization: OAuth ';
$raw_signature = 'GET&' . urlencode_rfc3986($request_url) . '&';
$raw_suffix = array();
foreach($params as $key => $param)
{
$raw_suffix[] = $key . '=' . $param;
}
$raw_signature .= urlencode_rfc3986(implode('&', $raw_suffix));
$oauth_signature = urlencode_rfc3986(base64_encode(hash_hmac('sha1', $raw_signature, $oauth_key, true)));
$params['oauth_signature'] = $oauth_signature;
uksort($params, 'strcmp');
$raw_head = array();
foreach($params as $key => $param)
{
$raw_head[] = $key . '="' . $param . '"';
}
$oauth_header .= implode(',', $raw_head);
$session = curl_init($request_url);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
curl_setopt($session, CURLOPT_HEADER, true);
curl_setopt($session, CURLOPT_HTTPHEADER, array($oauth_header));
$response = curl_exec($session);
curl_close($session);
echo $response;
function urlencode_rfc3986($input)
{
return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
}
Any ideas of where I'm going wrong?
ETA: Made some modifications. It's still not working, but the error I'm getting now is oauth_signature does not match expected value
I can't test it so I'll give you a couple of things to try and see if there is any improvement.
'$oauth_timestamp' in your $params array should actually be 'oauth_timestamp' (no $ sign). Also, when generating the query string, you shouldn't be enclosing the values in quotes.
You should change the foreach($params) loop to this instead:
foreach($params as $key => $param)
{
$raw_signature .= $key . '=' . urlencode($param) . '&';
$oauth_header .= $key . '=' . $param . ',';
}
$raw_signature = rtrim($raw_signature, '&');
$oauth_signature = base64_encode(hash_hmac('sha1', $raw_signature, $oauth_key));
$oauth_header .= 'oauth_signature=' . $oauth_signature;
Also, I think you should be using a GET request instead of POST for cURL.
Hope that helps.
I'm not entirely sure what I was doing wrong, but fortunately, I found fangel's OAuth script on GitHub that implements everything I need to generate tokens. It looks like I was on the the right track, though.
ETA: Furthermore, there is jacobbudin's TumblrOAuth library on GitHub, which uses fangel's script and some forked then updated code, that handles all the Tumblr authentication for a user for your application.
I'm sure I'll be back with more questions when I start trying to build my Followr script.
Exclude the 'oauth_callback' => $callback_url from the $params array and its all good. After excluding it server returns a 200 code:
HTTP/1.1 200 OK Server: nginx Date: Fri, 04 Oct 2013 19:52:51 GMT Content-Type: application/x-www-form-urlencoded Transfer-Encoding: chunked Connection: close Set-Cookie: tmgioct=524f1c93c799700263374730; expires=Mon, 02-Oct-2023 19:52:51 GMT; path=/; httponly P3P: CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL" oauth_token=smKHczH7Mt1MTGilqERZ28oNjJ4OP31lVtBHYTRAY8BH3f73hc&oauth_token_secret=4AxBTP8YannLZDdvR9IiTJTJIEKXocPJEHHSDd5TKQOrE6kr0N&oauth_callback_confirmed=true
Related
After getting all the credentials I'm now requesting a resource from Etsy API. It's working fine without query parameters to the url but when I add them I get signature invalid.
Here's what I got working without the query parameters in the url:
// enconding, sorting and creating the base URI
function buildBaseString($baseURI, $method, $params){
$r = array();
ksort($params);
foreach($params as $key=>$value){
$r[] = "$key=" . rawurlencode($value);
}
return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}
// create encoded header
function buildAuthorizationHeader($oauth){
$r = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key=>$value)
$values[] = "$key=\"" . rawurlencode($value) . "\"";
$r .= implode(', ', $values);
return $r;
}
$consumer_key = 'the_key';
$consumer_secret = 'the_secret';
$shop_id = '00000000000';
$oauth_access_token = 'access_token';
$oauth_access_token_secret = 'token_secret';
$receipts_by_status_url = 'https://openapi.etsy.com/v2/shops/'.$shop_id.'/receipts/opens';
$oauth = array(
'oauth_callback' => 'oob',
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => time(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_token' => $oauth_access_token,
'oauth_version' => '1.0',
);
$base_info = buildBaseString($receipts_by_status_url, 'GET', $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;
$header = array(buildAuthorizationHeader($oauth), 'Expect:', 'Content-Type: application/x-www-form-urlencoded');
/*
* Set curl options
*/
//ob_start();
//$curl_log = fopen('php://output', 'w');
$ch = curl_init($receipts_by_status_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 25);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Execute curl
$result_token = curl_exec($ch);
when I add the parameters to the url:
$receipts_by_status_url = 'https://openapi.etsy.com/v2/shops/'.$shop_id.'/receipts/opens/?includes=Listings';
I get signature invalid.
$base info:
'GET&https%3A%2F%2Fopenapi.etsy.com%2Fv2%2Fshops%2F12962774%2Freceipts%2Fopen%3Fincludes%3DListings&oauth_callback%3Doob%26oauth_consumer_key%thekey%26oauth_nonce%3D1607965396%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1607965396%26oauth_token%oauthtoken%26oauth_version%3D1.0'
$oauth signature:
0Dr9wz24LU6NPkO7eKvP//HCOWk=
$header:
0 => string 'Authorization: OAuth oauth_callback="oob", oauth_consumer_key="consumerkey", oauth_nonce="1607965396", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1607965396", oauth_token="oauthtoken", oauth_version="1.0", oauth_signature="0Dr9wz24LU6NPkO7eKvP%2F%2FHCOWk%3D"' (length=301)
1 => string 'Expect:' (length=7)
2 => string 'Content-Type: application/x-www-form-urlencoded
What am I doing wrong?
I got it working.
I Manually created the base string without the function in the question, this was the root of the problem, because when I added parameters to the endpoint it didn't work.
The server takes the parameters in the authrization header and creates an OAuth signature and compares it to yours, if the don't match you'll get invalid signature like in my case.
The base string should be 3 chunks of data concatenated together and rawurlencoded:
Http method '&' url endpoint '&' params
Things to make sure:
Use a url endpoint without query parameters
Make sure the whole base string has only two ampersands.
Sort params alphabetically.
Use Postman and succeed in sending the request there, after that you can compare the signature generated in the header there to yours, when you can match it then it should work.
Make sure you're using the long url (with query params) in cURL, the clean one is only to create the base string.
I didn't notice but Etsy is actually sending the base string they created from the params in the response when the signature is invalid, all I had to do is compare mine to theirs and fix it.
Hope I helped anyone
I'm using a modified php-script I found on the internet to function as a proxy between javascript and twitter api 1.1 (I need to do this because javascript can't do oauth operations and api 1.1 requires exactly that: authentication).
The script works fine - up until I search for a hashtag, then oauth fails.
Here's an example of the curl_info I get from twitter when searching for #z25org
url: http://api.twitter.com/1.1/search/tweets.json?q=%40z25org
content_type: application/json;charset=utf-8
http_code: 200
As you can see this works (http_code: 200). But when I search for a hashtag:
url: http://api.twitter.com/1.1/search/tweets.json?q=%23z25org
content_type: application/json; charset=utf-8
http_code: 401
I get http_code 401: Unauthorized access. The json:
{"errors":[{"message":"Could not authenticate you","code":32}]}
Here's my php code: (well, the biggest part of it)
<?php
// Some characters that need to be replaced
$specialCharacters = array(
"#"=>"%40",
"#"=>"%23",
" "=>"%20",
""=>""
);
/*
* Ok, no more config should really be needed. Yay!
*/
// We'll get the URL from $_GET[]. Make sure the url is url encoded, for example encodeURIComponent('statuses/user_timeline.json?screen_name=MikeRogers0&count=10&include_rts=false&exclude_replies=true')
if(!isset($_GET['url'])){
die('No URL set');
}
$url = $_GET['url'];
// Figure out the URL parmaters
$url_parts = parse_url($url);
parse_str($url_parts['query'], $url_arguments);
$full_url = $config['base_url'].$url; // Url with the query on it.
$base_url = $config['base_url'].$url_parts['path']; // Url without the query.
if (!dbglog(" > ORIGINAL: ".$full_url)) { die("Huh?"); }
// Replace characters
foreach($specialCharacters as $lookup => $replace) {
$full_url = str_replace($lookup,$replace,$full_url);
}
if (!dbglog(" > REPLACED: ".$full_url)) { die("Huh?"); }
/**
* Code below from http://stackoverflow.com/questions/12916539/simplest-php-example-retrieving-user-timeline-with-twitter-api-version-1-1 by Rivers
* with a few modfications by Mike Rogers to support variables in the URL nicely
*/
function buildBaseString($baseURI, $method, $params) {
$r = array();
ksort($params);
foreach($params as $key=>$value){
$r[] = "$key=" . rawurlencode($value);
}
return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}
function buildAuthorizationHeader($oauth) {
$r = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key=>$value)
$values[] = "$key=\"" . rawurlencode($value) . "\"";
$r .= implode(', ', $values);
return $r;
}
// Set up the oauth Authorization array
$oauth = array(
'oauth_consumer_key' => $config['consumer_key'],
'oauth_nonce' => time(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_token' => $config['oauth_access_token'],
'oauth_timestamp' => time(),
'oauth_version' => '1.0'
);
$base_info = buildBaseString($base_url, 'GET', array_merge($oauth, $url_arguments));
$composite_key = rawurlencode($config['consumer_secret']) . '&' . rawurlencode($config['oauth_access_token_secret']);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;
// Make Requests
$header = array(
buildAuthorizationHeader($oauth),
'Expect:'
);
$options = array(
CURLOPT_HTTPHEADER => $header,
//CURLOPT_POSTFIELDS => $postfields,
CURLOPT_HEADER => false,
CURLOPT_URL => $full_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false
);
try {
$feed = curl_init();
curl_setopt_array($feed, $options);
$result = curl_exec($feed);
$info = curl_getinfo($feed);
curl_close($feed);
} catch (Exception $e) {
die("Error: ".$e);
}
// Send suitable headers to the end user.
if(isset($info['content_type']) && isset($info['size_download'])){
header('Content-Type: '.$info['content_type']);
header('Content-Length: '.$info['size_download']);
}
echo($result);
?>
I had this same issue when building this library.
This commit specifically might yield some more information.
The issue that you have basically is that you are URL encoding incorrectly - maybe even twice. If you view the code from the source above (it's very similar, seems like it's been modified there), then it'll work exactly as you wanted.
TLDR: Use the above single file instead, or just copy/paste the code out of it. It's pretty much what you want.
As OP found: he also tried replacing it with %2523 (where %25 = %). It's still advisable to check out the above library.
I'm trying to obtain a request token from Twitter API in order to log in user with his twitter account and I keep getting a 401 response with "Failed to validate oauth signature and token". I'm doing this over PHP. I looked for similar questions but apparently I'm the only one crazy enough to do it from scratch without a library.
In their API documentation they talk about "percent encode" the values sent in the authorization header, I'm doing so with the urlencode() function, not sure if it's right.
To calculate the signature I use hash_hmac( 'SHA1', $signParameters, $hashKey), also not sure if it is the right one to use.
This is the request that gets generated, through cURL:
POST /oauth/request_token HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth oauth_callback="http%3A%2F%2Fwww.soytumascota.com%2Ftwitter%2Fuser.php", oauth_consumer_key="MY_APP_KEY", oauth_nonce="0dde25902bde5f3b280f58ea642047cf", oauth_signature_method="HMAC_SHA1", oauth_timestamp="1334697987", oauth_version="1.0", oauth_signature="8313277875f20cd8a8631966a2ba273a5d13aeda"
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
I would really appreciate any help you can give, thank you.
EDIT: Here's the code i've written so far.
<?php
DEFINE( 'CONSUMER_KEY', 'MY_APP_KEY' );
DEFINE( 'CONSUMER_SECRET', 'MY_APP_SECRET' );
$url = 'https://api.twitter.com/oauth/request_token';
//setting OAuth parameters
$Oauth = Array();
$Oauth['oauth_callback'] = 'http://www.soytumascota.com/twitter/user.php';
$Oauth['oauth_consumer_key'] = CONSUMER_KEY;
$Oauth['oauth_nonce'] = md5( $Oauth['oauth_callback'] . CONSUMER_KEY . time() );
$Oauth['oauth_signature_method'] = 'HMAC_SHA1';
$Oauth['oauth_timestamp'] = (string) time();
$Oauth['oauth_version'] = '1.0';
//signature and authorization header are calculated inside functions
$Oauth['oauth_signature'] = calculateSignature( 'POST', $url, $Oauth );
$authorization = getAuthorizationHeader( $Oauth );
ksort( $Oauth );
//setting and sending request using cURL
$curl_session = curl_init( $url );
curl_setopt( $curl_session, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl_session, CURLOPT_POST, true );
curl_setopt( $curl_session, CURLINFO_HEADER_OUT, true );
curl_setopt( $curl_session, CURLOPT_HTTPHEADER, Array( 'Authorization: ' . $authorization ) );
$result = curl_exec( $curl_session );
function getAuthorizationHeader( $parameters )
{
$authorization = 'OAuth ';
$j = count( $parameters );
foreach( $parameters as $key => $val )
{
$authorization .= $key . '="' . urlencode( $val ) . '"';
if( $j-- > 1 )
{
$authorization .= ', ';
}
}
return $authorization;
}
function calculateSignature( $method, $url, $parameters, $accessToken = '' )
{
foreach( $parameters as $key => $val )
{
$foo = urlencode( $key );
unset( $parameters[$key] );
$parameters[$foo] = urlencode( $val );
}
ksort( $parameters );
$signBase = '';
$j = count( $parameters );
foreach( $parameters as $key => $val )
{
$signBase .= "{$key}={$val}";
if( $j-- > 1 )
{
$signBase .= '&';
}
}
$signBase = strtoupper( $method ) . '&' . urlencode( $url ) . '&' . urlencode( $signBase );
$signKey = urlencode( CONSUMER_SECRET ) . '&' . urlencode( $accessToken );
$signature = hash_hmac( 'SHA1', $signParameters, $hashKey);
return $signature;
}
First, 'oauth_signature_method' must be 'HMAC-SHA1' (or nothing will work).
About "percent encode", they say in their API documentation https://dev.twitter.com/docs/auth/percent-encoding-parameters they require strings to be encoded according to RFC 3986 so you should use rawurlencode instead of urlencode.
To calculate the signature they say here https://dev.twitter.com/docs/auth/creating-signature that you have to use HMAC-SHA1 hashing algorithm and convert the raw output to base64, something like:
$signature = base64_encode(hash_hmac( 'SHA1', $signBase, $signKey, true));
And finally you may need to add
//no content
curl_setopt( $curl_session, CURLOPT_POSTFIELDS, '');
//no verify certs
curl_setopt( $curl_session, CURLOPT_SSL_VERIFYPEER, FALSE);
to the curl options to get the request working.
i have been trying for the last several days to fetch a request from a website but no success.
I keep getting error 301.
Is anyone able to help me grab the content of this page: https://pre.corrupt-net.org/search.php?search=Lasse_Stefanz-Bara_Du-SE-CD-FLAC-1995-LoKET
I am looking forward to your reply.
EDIT:
This is the php function I've used:
function http_request(
$verb = 'GET', /* HTTP Request Method (GET and POST supported) */
$ip, /* Target IP/Hostname */
$port = 80, /* Target TCP port */
$uri = '/', /* Target URI */
$getdata = array(), /* HTTP GET Data ie. array('var1' => 'val1', 'var2' => 'val2') */
$postdata = array(), /* HTTP POST Data ie. array('var1' => 'val1', 'var2' => 'val2') */
$cookie = array(), /* HTTP Cookie Data ie. array('var1' => 'val1', 'var2' => 'val2') */
$custom_headers = array(), /* Custom HTTP headers ie. array('Referer: http://localhost/ */
$timeout = 1000, /* Socket timeout in milliseconds */
$req_hdr = false, /* Include HTTP request headers */
$res_hdr = false /* Include HTTP response headers */
)
{
$ret = '';
$verb = strtoupper($verb);
$cookie_str = '';
$getdata_str = count($getdata) ? '?' : '';
$postdata_str = '';
foreach ($getdata as $k => $v)
$getdata_str .= urlencode($k) .'='. urlencode($v);
foreach ($postdata as $k => $v)
$postdata_str .= urlencode($k) .'='. urlencode($v) .'&';
foreach ($cookie as $k => $v)
$cookie_str .= urlencode($k) .'='. urlencode($v) .'; ';
$crlf = "\r\n";
$req = $verb .' '. $uri . $getdata_str .' HTTP/1.1' . $crlf;
$req .= 'Host: '. $ip . $crlf;
$req .= 'User-Agent: Mozilla/5.0 Firefox/3.6.12' . $crlf;
$req .= 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' . $crlf;
$req .= 'Accept-Language: en-us,en;q=0.5' . $crlf;
$req .= 'Accept-Encoding: deflate' . $crlf;
$req .= 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7' . $crlf;
foreach ($custom_headers as $k => $v)
$req .= $k .': '. $v . $crlf;
if (!empty($cookie_str))
$req .= 'Cookie: '. substr($cookie_str, 0, -2) . $crlf;
if ($verb == 'POST' && !empty($postdata_str)){
$postdata_str = substr($postdata_str, 0, -1);
$req .= 'Content-Type: application/x-www-form-urlencoded' . $crlf;
$req .= 'Content-Length: '. strlen($postdata_str) . $crlf . $crlf;
$req .= $postdata_str;
}
else $req .= $crlf;
if ($req_hdr)
$ret .= $req;
if (($fp = #fsockopen($ip, $port, $errno, $errstr)) == false)
return "Error $errno: $errstr\n";
stream_set_timeout($fp, 0, $timeout * 1000);
fputs($fp, $req);
while ($line = fgets($fp)) $ret .= $line;
fclose($fp);
if (!$res_hdr)
$ret = substr($ret, strpos($ret, "\r\n\r\n") + 4);
return $ret;
}
Firstly, 301 is not an "error" as such, it indicates that you are being redirected. You need to parse the response headers, take the value of the Location: header (which the HTTP protocol specification requires be present in a redirect response) and request that URI as well.
Secondly, the function above does not appear to provide any support for accessing HTTPS URLs. You need the OpenSSL extension installed for your PHP instance to do this, and you also need to actually call it some how. You could use the above function to do so by passing ssl:// or tls:// in front of the address in the $ip parameter, but you cannot simply pass the IP.
Thirdly, the usual way to do things like this is with the cURL extension. You would do something like this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://pre.corrupt-net.org/search.php?search=Lasse_Stefanz-Bara_Du-SE-CD-FLAC-1995-LoKET'); // Set the URL
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // Follow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // Get the result from the execution
if (($result = curl_exec($ch)) === FALSE) { // Execute the request
echo "cURL failed! Error: ".curl_error($ch);
} else {
echo "Success! Result: $result";
}
curl_close($ch);
Alternatively, if cURL is not available or you don't want to use it for some reason, you could have go with my HTTPRequest class, which is PHP4 compliant and requires no extensions (apart from OpenSSL for HTTPS requests). Documented(ish) in comments at the top of the script. You would do something like this:
$request = new httprequest(); // Create an object
// Set the request URL
if (!$request->setRequestURL('https://pre.corrupt-net.org/search.php?search=Lasse_Stefanz-Bara_Du-SE-CD-FLAC-1995-LoKET')) echo "Failed! Error: ".$request->getLastErrorStr()."<br>\r\n";
// Send the request
if (!$request->sendRequest()) echo "Failed! Error: ".$request->getLastErrorStr()."<br>\r\n";
echo "Success! Result: ".$request->getResponseBodyData(TRUE);
On a side note, a lot of the Scene PreDB managers/providers are not too keen on automated scraping, and you may get yourself banned...
I have spent the past couple of hours trying all types of variations but according to the Twitter API this should have worked from step 1!
1 addition I have made to the script below is that I have added in:
$header = array("Expect:");
This I found helped in another question on stackoverflow from getting a denied issue / 100-continue.
Issue:
Failed to validate oauth signature and token is the response EVERY time!!!
Example of my post data:
Array ( [oauth_callback] => http://www.mysite.com//index.php [oauth_consumer_key] => hidden [oauth_nonce] => hidden [oauth_signature_method] => HMAC-SHA1 [oauth_timestamp] => 1301270847 [oauth_version] => 1.0 )
And my header data:
Array ( [0] => Expect: )
Script:
$consumer_key = "hidden";
$consumer_secret = "hidden";
function Post_Data($url,$data,$header){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$data['oauth_callback'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
$data['oauth_consumer_key'] = $consumer_key;
$data['oauth_nonce'] = md5(time());
$data['oauth_signature_method'] = "HMAC-SHA1";
$data['oauth_timestamp'] = time();
$data['oauth_version'] = "1.0";
$header = array("Expect:");
$content = Post_Data("http://api.twitter.com/oauth/request_token",$data,$header);
print_r($content);
Can anybody see an obvious mistake that I may be making here? Preferably I would not like to go with somebody elses code as most examples have full classes & massive functions, I am looking for the most simple approach!
Your problem is that you did not include the OAuth signature in your request.
You can read about the concept on this page.
A working implementation can be found here.
I faced same issue, what I was missing is passing header in to the curl request.
As shown in this question, I was also sending the $header = array('Expect:'), which was the problem in my case. I started sending signature in header with other data as below and it solved the case for me.
$header = calculateHeader($parameters, 'https://api.twitter.com/oauth/request_token');
function calculateHeader(array $parameters, $url)
{
// redefine
$url = (string) $url;
// divide into parts
$parts = parse_url($url);
// init var
$chunks = array();
// process queries
foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', urlencode_rfc3986($key) . '="' . urlencode_rfc3986($value) . '"');
// build return
$return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
$return .= implode(',', $chunks);
// prepend name and OAuth part
return $return;
}
function urlencode_rfc3986($value)
{
if(is_array($value)) return array_map('urlencode_rfc3986', $value);
else
{
$search = array('+', ' ', '%7E', '%');
$replace = array('%20', '%20', '~', '%25');
return str_replace($search, $replace, urlencode($value));
}
}