-
-
Save kosso/71c957e30a40116e5f98 to your computer and use it in GitHub Desktop.
| <?php | |
| //opcache_reset(); // Disable local dev MAMP cache | |
| /* | |
| WP_API_OAuth_Test_client.php | |
| Tested with Wordpress 4.7.1 | |
| WordPress REST API - OAuth 1.0a Server v.0.3.0 - https://en-gb.wordpress.org/plugins/rest-api-oauth1/ | |
| Description : Simple PHP test to obtain access_token and access_token_secret (Access tokens) from a Wordpress with WP-API and WP-OAuth plugins (and WP-CLI for OAuth consumer/app creation) installed. | |
| Author : @kosso | |
| Date : Nov 07, 2014 | |
| Updated : Nov 22, 2015 | |
| : Jan 16, 2016 | |
| : Mar 06, 2016 | |
| : Oct 11, 2016 | |
| : Jan 23, 2017 | |
| */ | |
| /* | |
| Instructions : After installing the WordPress REST API - OAuth 1.0a Server plugin, you can now create a new client application on wp-admin | |
| ; Go to Dashboard > Users > Applications. | |
| : Set one up, then use the key/secret pair in the settings below. | |
| : Use the url of *this* PHP test script for the callback url. | |
| .. Now edit the config vars below with the server and client info. | |
| */ | |
| // Edit the config to your requirements. | |
| $wp_site_url = 'http://yourWPdomain.com'; | |
| $wp_api_path = '/wp-json/wp/v2'; | |
| $oauth_config = array( | |
| 'key' => '#_YOUR_APP_CLIENT_KEY_#', | |
| 'secret' => '#_YOUR_APP_CLIENT_SECRET#', | |
| 'wp_api_domain' => $wp_site_url, | |
| 'wp_api_path' => $wp_api_path, | |
| 'uri_request' => $wp_site_url.'/oauth1/request', | |
| 'uri_authorize' => $wp_site_url.'/oauth1/authorize', | |
| 'uri_access' => $wp_site_url.'/oauth1/access', | |
| 'uri_user' => $wp_site_url.$wp_api_path.'/users/me?context=edit', // 'embed' context excludes roles and capabilities, so use 'edit' to determine if publishing and uploads are allowed. | |
| 'oauth_callback' => 'http://yourREMOTE.client.domain.com/WP_API_OAuth_Test_client.php' // The url where you will run this test. Point to THIS php file. | |
| ); | |
| // Clear the cookies to log out. | |
| if($_GET['logout']==1){ | |
| setcookie("access_token", $access_token, time() - 1, "/" ); | |
| setcookie("access_token_secret", $access_token_secret, time() - 1, "/" ); | |
| setcookie("user_object", json_encode($user_object), time() - 1, "/" ); | |
| setcookie("oauth_token_secret", "", time() - 1, "/" ); | |
| header('Location: '.$_SERVER['PHP_SELF']); | |
| } | |
| // OK.. Here we go... | |
| $auth = new OAuthWP($oauth_config); | |
| // Pick up url query params after the oauth_callback after request token generation. (Also added check to make sure we're coming back from the OAuth server host) | |
| //if(isset( $_REQUEST['oauth_token'] ) && isset( $_REQUEST['oauth_verifier'] ) && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) == parse_url($oauth_config['uri_request'], PHP_URL_HOST) ){ | |
| if(isset( $_REQUEST['oauth_token'] ) && isset( $_REQUEST['oauth_verifier'] )) { | |
| // Back from Authorisation. Now Generate Access Tokens for this user | |
| // Generate access tokens param string | |
| // Add the required 'oauth_verifier' parameter | |
| $request_data = array( | |
| 'oauth_verifier' => $_REQUEST['oauth_verifier'] | |
| ); | |
| $temp_secret = $_COOKIE['oauth_token_secret']; // from /request token leg | |
| $access_token_string = $auth->oauthRequest($oauth_config['uri_access'],'POST', $_REQUEST['oauth_token'], $temp_secret, $request_data); // no token secret yet... | |
| parse_str($access_token_string, $access_tokens); | |
| if(!isset($access_tokens['oauth_token'])){ | |
| echo '<h3>ERROR: Failed to get access tokens</h3>'; | |
| print_r($access_tokens); | |
| echo '<hr>'; | |
| print_r($access_token_string); | |
| exit; | |
| } | |
| $access_token = $access_tokens['oauth_token']; | |
| $access_token_secret = $access_tokens['oauth_token_secret']; | |
| // Verify user by getting currently looged in user daya from /wp-json/users/me | |
| $user_object = json_decode($auth->oauthRequest($oauth_config['uri_user'],'GET', $access_token, $access_token_secret)); | |
| // Store information in a cookie for when the page is reloaded | |
| setcookie("access_token", $access_token, time() + (3600 * 72), "/" ); // expire in 72 hours... | |
| setcookie("access_token_secret", $access_token_secret, time() + (3600 * 72), "/" ); // expire in 72 hours... | |
| setcookie("user_object", json_encode($user_object), time() + (3600 * 72), "/" ); // expire in 72 hours... | |
| // Clear the temp cookie | |
| setcookie("oauth_token_secret", "", time() - 1, "/" ); | |
| // Reload the page | |
| header('Location: '.$_SERVER['PHP_SELF']); | |
| exit; | |
| } | |
| if(isset($_COOKIE['access_token']) && isset($_COOKIE['access_token_secret']) && isset($_COOKIE['user_object'])){ | |
| // LOGGED-IN : Visitor already appears to have the required cookies set. | |
| $u = json_decode($_COOKIE['user_object']); | |
| $av = $u->avatar_urls; | |
| foreach ($av as $key => $value) { | |
| if($key == 48){ // medium thumbnail | |
| $av = $value; | |
| } | |
| } | |
| echo '<h3><img style="margin:6px;width:50px;height:50px;float:left;vertical-align:middle;" src="'.$av.'"> logged in as: '.$u->name.'</h3>'; | |
| echo '<br clear="all"><h4><a href="?logout=1">CLICK HERE TO LOG OUT</a></h4>'; | |
| echo '<hr>'; | |
| echo 'uncomment code below to try some tests.'; | |
| // TESTS ///////////////////////////////////////////// | |
| //echo $oauth_config['uri_user']; | |
| // GET CURRENT USER DATA | |
| // Docs : http://wp-api.org/#users_retrieve-current-user | |
| echo '<h3>TEST: GET : '.$oauth_config['uri_user'].' to verify current user</h3>'; | |
| $current_user_object = json_decode($auth->oauthRequest($oauth_config['uri_user'],'GET', $_COOKIE['access_token'], $_COOKIE['access_token_secret'])); | |
| echo '<h4>RESPONSE:</h4>'; | |
| echo '<pre>'; | |
| print_r($current_user_object); | |
| echo '</pre>'; | |
| // exit; | |
| /* | |
| // TEST : CREATE A NEW POST | |
| // Docs : http://wp-api.org/#posts_create-a-post | |
| echo '<hr><h3>test : Creating new post</h3>'; | |
| $post_data = array( | |
| 'status' => 'draft', | |
| 'title' => 'Heyyyyy Another test at '.date('H:i'), | |
| 'content' => 'The quick brown fox jumped over the lazy dogs.' | |
| ); | |
| $post_object = $auth->oauthRequest($oauth_config['wp_api_domain'].$oauth_config['wp_api_path'].'/posts','POST', $_COOKIE['access_token'], $_COOKIE['access_token_secret'], $post_data); | |
| echo '<h4>RESPONSE:</h4>'; | |
| echo '<pre>'; | |
| print_r($post_object); | |
| echo '</pre>'; | |
| */ | |
| // Uncomment the sections below to test some other things.. | |
| /* | |
| // CREATE NEW ATTACHMENT (Media upload) | |
| // Docs : http://wp-api.org/#media_create-an-attachment | |
| echo '<hr><h3>Test : Create New Attachment (Media upload)</h3>'; | |
| $file_data = array( | |
| 'file' => '@./some_photo.jpg;type=image/jpeg' | |
| //'file' => '@./some_video.m4v;type=video/m4v' | |
| //'file' => '@./sometune.mp3;type=audio/mpeg' | |
| ); | |
| $file_object = json_decode($auth->oauthRequest($oauth_config['wp_api_domain'].$oauth_config['wp_api_path'].'/media', | |
| 'POST', | |
| $_COOKIE['access_token'], | |
| $_COOKIE['access_token_secret'], | |
| $file_data | |
| ) | |
| ); | |
| echo '<h4>UPLOAD RESPONSE:</h4>'; | |
| echo '<pre>'; | |
| print_r($file_object); | |
| echo '</pre>'; | |
| // Naturally, you'll need to do a file upload first, if you want the attachment to be 'attached' or embedded in a post. | |
| /**/ | |
| /* | |
| date | |
| date_gmt | |
| password | |
| slug | |
| status - One of: publish, future, draft, pending, private | |
| title | |
| content | |
| author | |
| excerpt | |
| featured_media | |
| comment_status - One of: open, closed | |
| ping_status - One of: open, closed | |
| format - One of: standard, aside, chat, gallery, link, image, quote, status, video, audio | |
| sticky | |
| categories | |
| tags | |
| */ | |
| /* | |
| // UPDATE A (previous) POST | |
| echo '<hr><h3>Test : Updating Post</h3>'; | |
| $post_id = $post_object->id; | |
| $update_data = array( | |
| 'title' => 'The title was edited immediately after creating it at '.time(), | |
| 'excerpt' => 'And this excerpt was added after.', | |
| 'categories' => [ 1, 2, 6 ] | |
| ); | |
| $update_object = json_decode($auth->oauthRequest($oauth_config['wp_api_domain'].$oauth_config['wp_api_path'].'/posts/'.$post_id, | |
| 'POST', | |
| $_COOKIE['access_token'], | |
| $_COOKIE['access_token_secret'], | |
| $update_data, | |
| true // post as JSON | |
| ) | |
| ); | |
| echo '<h4>UPDATE POST RESPONSE:</h4>'; | |
| echo '<pre>'; | |
| print_r($update_object); | |
| echo '</pre>'; | |
| /**/ | |
| // that's it.. | |
| } else { | |
| // Not logged in. | |
| $request_token_string = $auth->oauthRequest($oauth_config['uri_request'],'POST', null, null); | |
| parse_str($request_token_string, $request_parts); | |
| // temporarily store the oauth_token_secret for the next step after the callback. | |
| setcookie("oauth_token_secret", $request_parts['oauth_token_secret'], time() + 60, "/" ); | |
| // echo '<h4>request_token_string :'.$request_token_string.'</h4>'; | |
| // Start OAuth authorisation by obtaining a request token and generating a link to the OAuth server, with a callback here ... | |
| echo '<h3><a href="'.$oauth_config['uri_authorize'].'?'.$request_token_string.'&oauth_callback='.urlencode($oauth_config['oauth_callback']).'">LOGIN USING YOUR '.$oauth_config['wp_api_domain'].' WORDPRESS ACCOUNT</a></h3>'; | |
| echo 'Uses WP-API and OAuth 1.0a Server for WordPress via https://github.com/WP-API'; | |
| } | |
| // That's it! | |
| // ######################################################################### | |
| // OAuth 1.0a library | |
| // ######################################################################### | |
| // NB: All the echo and print_r must be commented out for setcookie to work when running logging in tests. | |
| function logIt($text){ | |
| return;// comment to activate log | |
| $debugLog = '/path/to/debug/log.txt'; | |
| $t = print_r($text, true); | |
| $text = $t; | |
| $handle = fopen($debugLog, "a+"); | |
| if (fwrite($handle, $text."\n") === FALSE) { | |
| } | |
| fclose($handle); | |
| } | |
| class OAuthWP | |
| { | |
| function OAuthWP($config) | |
| { | |
| $this->key = $config['key']; | |
| $this->secret = $config['secret']; | |
| $this->uri_request = $config['uri_request']; | |
| $this->uri_authorize = $config['uri_authorize']; | |
| $this->uri_access = $config['uri_access']; | |
| $this->uri_user = $config['uri_user']; | |
| } | |
| function queryStringFromData($data, $queryParams = false, $prevKey = '') | |
| { | |
| if ($initial = (false === $queryParams)) { | |
| $queryParams = array(); | |
| } | |
| foreach ($data as $key => $value) { | |
| if ($prevKey) { | |
| $key = $prevKey.'['.$key.']'; // Handle multi-dimensional array | |
| } | |
| $queryParams[] = $this->_urlencode_rfc3986($key.'='.$value); // join with equals sign | |
| } | |
| if ($initial) { | |
| return implode('%26', $queryParams); // join with ampersand | |
| } | |
| return $queryParams; | |
| } | |
| function oauthRequest($url, $method, $oauth_access_token, $oauth_access_token_secret, $post_params=null, $post_json=false){ | |
| $params = array( | |
| "oauth_version" => "1.0", | |
| "oauth_nonce" => md5(time().rand()), | |
| "oauth_timestamp" => time(), | |
| "oauth_consumer_key" => $this->key, | |
| "oauth_signature_method" => "HMAC-SHA1", | |
| "oauth_token" => $oauth_access_token | |
| ); | |
| // Filter out empty params. | |
| $params = array_filter($params); | |
| // ## BUILD OAUTH SIGNATURE | |
| // Add extra params if present and not JSON | |
| if($post_params!=null && $post_json === false ){ | |
| foreach ($post_params as $k => $v){ | |
| if(is_array($v)){ | |
| $iii = 0; | |
| logIt('***** ARRAY '); | |
| foreach ($v as $kk => $vv){ | |
| $params[$k][$iii] = $vv; | |
| $iii++; | |
| } | |
| } else { | |
| $params[$k] = $v; | |
| } | |
| } | |
| // Remove 'file' param from signature base string. Since the server will have nothing to compare it to. Also potentially exposes paths. | |
| unset($params['file']); | |
| ksort($params); | |
| } | |
| // Deal query with any query params in the request_uri | |
| $request_query = parse_url($url, PHP_URL_QUERY); | |
| $request_uri_parts = parse_url($url); | |
| $request_base_uri = $request_uri_parts['scheme'].'://'.$request_uri_parts['host'].$request_uri_parts['path']; | |
| $joiner = '?'; // used for final url concatenation down below | |
| if(!empty($request_query)){ | |
| $joiner = '&'; | |
| parse_str($request_query, $query_params); | |
| $params = array_merge($query_params, $params); | |
| ksort($params); | |
| } | |
| // Encode params keys, values, join and then sort. | |
| $keys = $this->_urlencode_rfc3986(array_keys($params)); | |
| $values = $this->_urlencode_rfc3986(array_values($params)); | |
| $params = array_combine($keys, $values); | |
| ksort($params); | |
| // Convert params to string | |
| foreach ($params as $k => $v) { | |
| $pairs[] = $this->_urlencode_rfc3986($k).'='.$this->_urlencode_rfc3986($v); | |
| } | |
| $concatenatedParams = implode('&', $pairs); | |
| $concatenatedParams = str_replace('=', '%3D', $concatenatedParams); | |
| $concatenatedParams = str_replace('&', '%26', $concatenatedParams); | |
| // Form base string (first key) | |
| // echo '<h4>concatenated params</h4><pre>'.$concatenatedParams.'</pre>'; | |
| // base string should never use the '?' even if it has one in a GET query | |
| // See : https://developers.google.com/accounts/docs/OAuth_ref#SigningOAuth | |
| $baseString= $method."&".urlencode($request_base_uri)."&".$concatenatedParams; | |
| // Form secret (second key) | |
| $secret = urlencode($this->secret)."&".$oauth_access_token_secret; // concatentate the oauth_token_secret (null when doing initial '1st leg' request token) | |
| // Make signature and append to params | |
| logIt('base : '.$baseString); | |
| logIt('signature key : '.$secret); | |
| $params['oauth_signature'] = rawurlencode(base64_encode(hash_hmac('sha1', $baseString, $secret, TRUE))); | |
| // Re-sort params | |
| ksort($params); | |
| // Remove any added GET query parameters from the params to rebuild the string without duplication .. | |
| if(isset($query_params)){ | |
| foreach ($query_params as $key => $value) { | |
| if(isset($params[$key])){ | |
| unset($params[$key]); | |
| } | |
| } | |
| ksort($params); | |
| } | |
| // Remove any POST params so they get sent as POST data and not in the query string. | |
| if($post_params!=null && $post_json === false ){ | |
| foreach ($post_params as $key => $value) { | |
| if(isset($params[$key])){ | |
| unset($params[$key]); | |
| } | |
| } | |
| ksort($params); | |
| } | |
| // Build OAuth Authorization header from oauth_* parameters only. | |
| $post_headers = $this->buildAuthorizationHeader($params); | |
| // Convert params to string | |
| foreach ($params as $k => $v) { | |
| $urlPairs[] = $k."=".$v; | |
| } | |
| $concatenatedUrlParams = implode('&', $urlPairs); | |
| // The final url can use the ? query params.... | |
| $final_url = $url; // original url. OAuth data will be set in the Authorization Header of the request, regardless of _GET or _POST (or _FILE) | |
| // Request using cURL | |
| $json_response = $this->_http($final_url, $method, $post_params, $post_headers, $post_json); | |
| // Result JSON | |
| return $json_response; | |
| } | |
| // Send Authorised Request Using Curl /////////////////////////// | |
| function _http($url, $method, $post_data = null, $oauth_headers = null, $post_json=false) | |
| { | |
| $ch = curl_init(); | |
| curl_setopt($ch, CURLOPT_URL, $url); | |
| curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); | |
| curl_setopt($ch, CURLOPT_TIMEOUT, 30); | |
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |
| curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | |
| if($method=='POST') | |
| { | |
| curl_setopt($ch, CURLOPT_POST, 1); | |
| logIt('POST'); | |
| logIt($post_data); | |
| if(isset($post_data['file'])){ | |
| // Media upload | |
| $header[] = 'Content-Type: multipart/form-data'; | |
| if(isset($oauth_headers)){ | |
| array_push($header, $oauth_headers); | |
| } | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); | |
| } else { | |
| if(isset($oauth_headers)){ | |
| if($post_json===true){ | |
| $header[] = 'Content-Type: application/json'; | |
| array_push($header, $oauth_headers); | |
| } else { | |
| $header[] = $oauth_headers; | |
| } | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | |
| } | |
| if($post_json===true){ | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data)); | |
| } else { | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); // application/x-www-form-urlencoded | |
| } | |
| } | |
| } else { | |
| // Not being used yet. | |
| if(isset($oauth_headers)) | |
| { | |
| $header[] = $oauth_headers; | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | |
| } | |
| } | |
| $response = curl_exec($ch); | |
| $this->http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 201 = 'Created' | |
| $this->last_api_call = $url; | |
| $this->response = $response; | |
| // echo "<br>status: ".$this->http_status."<br>"; | |
| // logit('this'); | |
| // logIt($this); | |
| curl_close($ch); | |
| return $response; | |
| } | |
| function _urlencode_rfc3986($input) | |
| { | |
| if (is_array($input)) { | |
| return array_map(array('OAuthWP', '_urlencode_rfc3986'), $input); | |
| } | |
| else if (is_scalar($input)) { | |
| return str_replace('+',' ',str_replace('%7E', '~', rawurlencode($input))); | |
| } | |
| else{ | |
| return ''; | |
| } | |
| } | |
| private function buildAuthorizationHeader($oauth){ | |
| $r = 'Authorization: OAuth '; | |
| $values = array(); | |
| foreach($oauth as $key => $value){ | |
| $values[] = $key . '="' . rawurlencode($value) . '"'; | |
| } | |
| $r .= implode(', ', $values); | |
| return $r; | |
| } | |
| } | |
| ?> |
Hmm.. I just tried it on a fresh Wordpress 4.7.3 on one domain, running this script from another domain and it all worked fine.
Do you have the application client id/secret and the callback url all set up correctly?
Which version of Wordpress and also PHP are you running this on?
Hi, i tried to implement this oAuth too. All flows are working fine.
The only problem is when I tried to fetch current user data, it always returned me unauthorized response like:
{"code":"rest_not_logged_in","message":"You are not currently logged in.","data":{"status":401}}
Any thought?
Works for me on 4.8, awesome job and thank you.
I spoke too soon... When talking to a WP instance on a domain, I am getting the "No OAuth parameters supplied" message also, I tried different domains, different instances, works only if I run it on a local instance.
It turns out, my hosting company has a policy for Authorization headers.
Adding :
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
at the end of the .httaccess file solves the problem.
@bojanseirovski Thank you very much. It works now.
When I am going to exchange the token, it returned 'ERROR: Failed to get access tokens '
Hello Kosso,
First of all thank you for this magnificant client example. Unfortunatly i stumbled across a problem with the Media Upload.
The error I'm getting is:
( [code] => json_oauth1_signature_mismatch [message] => OAuth signature does not match [data] => stdClass Object ( [status] => 401 )
I really would like this to work.. so i hope you can help me!
Thanks in advance!
Notice: Undefined index: logout in C:\xampp\htdocs\example\scripts\curl_post_request.php on line 86
This is showing when I'm running the script on localhost! How to solve that issue?
Currently this line
$request_token_string = $auth->oauthRequest($oauth_config['uri_request'],'POST', null, null);produces
http://www.site.com/oauth1/authorize?No%20OAuth%20parameters%20supplied&oauth_callback=http%3A%2F%2Fwww.site.com%2Ftest.phpSee the No%20OAuth%20parameters%20supplied.
In that function
oauthRequest$json_response = $this->_http($final_url, $method, $post_params, $post_headers, $post_json);returns
No OAuth parameters supplied.In function
_httpcurl_setopt($ch, CURLOPT_HTTPHEADER, $header);returns
No OAuth parameters suppliedand
echo "<br>status: ".$this->http_status."<br>";returns
status: 400Any idea?