I'm trying to call Magento REST API with pre authorized access token, I thought it would be easy but for some reason i cant get it to work, i mean i have the four components required, the consumerKey, consumerSecret, oauth_token and oauth_token_secret, however i always get a nonce_used error (right from the REST docs: This error is used if the nonce-timestamp combination has already been used.)
My normal authentication code is as follows:
class AppFactory_Basic_TestController extends Mage_Core_Controller_Front_Action {
public function indexAction() {
//Basic parameters that need to be provided for oAuth authentication
//on Magento
$params = array(
'siteUrl' => 'http://www.appfactory.loc/magento/oauth',
'requestTokenUrl' => 'http://www.appfactory.loc/magento/oauth/initiate',
'accessTokenUrl' => 'http://www.appfactory.loc/magento/oauth/token',
'authorizeUrl' => 'http://www.appfactory.loc/magento/admin/oauth_authorize',//This URL is used only if we authenticate as Admin user type
'consumerKey' => '0165d0443e9a15a019f26b2e2ca8c0bc',//Consumer key registered in server administration
'consumerSecret' => 'a1e9e199de111a566ed9698da7bf69b2',//Consumer secret registered in server administration
'callbackUrl' => 'http://www.appfactory.loc/magento/basic/test/callback',//Url of callback action below
);
// Initiate oAuth consumer with above parameters
$consumer = new Zend_Oauth_Consumer($params);
// Get request token
$requestToken = $consumer->getRequestToken();
// Get session
$session = Mage::getSingleton('core/session');
// Save serialized request token object in session for later use
$session->setRequestToken(serialize($requestToken));
// Redirect to authorize URL
//Zend_Debug::dump( serialize($requestToken) );
//Zend_Debug::dump( $requestToken );
$consumer->redirect();
return;
}
public function callbackAction() {
//oAuth parameters
$params = array(
'siteUrl' => 'http://www.appfactory.loc/magento/oauth',
'requestTokenUrl' => 'http://www.appfactory.loc/magento/oauth/initiate',
'accessTokenUrl' => 'http://www.appfactory.loc/magento/oauth/token',
'consumerKey' => '0165d0443e9a15a019f26b2e2ca8c0bc',
'consumerSecret' => 'a1e9e199de111a566ed9698da7bf69b2'
);
// Get session
$session = Mage::getSingleton('core/session');
// Read and unserialize request token from session
$requestToken = unserialize($session->getRequestToken());
// Initiate oAuth consumer
$consumer = new Zend_Oauth_Consumer($params);
// Using oAuth parameters and request Token we got, get access token
Mage::log('Get Array:' . print_r($_GET, true) );
$acessToken = $consumer->getAccessToken($_GET, $requestToken);
// Get HTTP client from access token object
$restClient = $acessToken->getHttpClient($params);
// Set REST resource URL
$restClient->setUri('http://www.appfactory.loc/magento/api/rest/products');
// In Magento it is neccesary to set json or xml headers in order to work
$restClient->setHeaders('Accept', 'application/json');
// Get method
$restClient->setMethod(Zend_Http_Client::GET);
//Make REST request
$response = $restClient->request();
// Here we can see that response body contains json list of products
Zend_Debug::dump($response);
return;
}
Everything so far is running smoothly, im getting the Magento Authorize/Deny page and im redirected to the call back function with the actual API output and the product list. Now I try to do another call with the aouth_token i got:
public function doshitAction(){
$params = array(
'siteUrl' => 'http://www.appfactory.loc/magento/oauth',
'requestTokenUrl' => 'http://www.appfactory.loc/magento/oauth/initiate',
'accessTokenUrl' => 'http://www.appfactory.loc/magento/oauth/token',
'consumerKey' => '0165d0443e9a15a019f26b2e2ca8c0bc',
'consumerSecret' => 'a1e9e199de111a566ed9698da7bf69b2'
);
// Get session
$session = Mage::getSingleton('core/session');
// Read and unserialize request token from session
$requestToken = unserialize($session->getRequestToken());
Zend_Debug::dump($requestToken);
// Initiate oAuth consumer
$consumer = new Zend_Oauth_Consumer($params);
// Using oAuth parameters and request Token we got, get access token
$acessToken = $consumer->getAccessToken( array( 'oauth_token' => 'abd3945f27c4601591cb3434665ad6e8' ,
'oauth_verifier' => '85516e31405f59ac6f50eabac001edc5'
) , $requestToken);
// do a request
$restClient = $acessToken->getHttpClient($params);
$restClient->setUri('http://www.appfactory.loc/magento/api/rest/products');
$restClient->setHeaders('Accept', 'application/json');
$restClient->setMethod(Zend_Http_Client::GET);
$response = $restClient->request();
// Here we can see that response body contains json list of products
Zend_Debug::dump($response);
return;
}
And this is where im stuck, its exactly the same code in the callback function, but i replaced $_GET array with the varaiables that were actually in the array. What i am doing wrong. The $requestToken btw dump is
object(Zend_Oauth_Token_Request)#131 (3) {
["_params":protected] => array(3) {
["oauth_token"] => string(32) "abd3945f27c4601591cb3434665ad6e8"
["oauth_token_secret"] => string(32) "1c06bdd7614dce7357095fb43dd526a7"
["oauth_callback_confirmed"] => string(4) "true"
}
["_response":protected] => NULL
["_httpUtility":protected] => object(Zend_Oauth_Http_Utility)#44 (0) {
}
}
so it has the oauth_token and oauth_token_secret, not sure why the getAccessToken functions need a oauth_verifier value.
Below is the stack trace:
Could not retrieve a valid Token response from Token URL:
oauth_problem=nonce_used
Trace:
#0 C:\Development\stage\grantorino-appfactory-ab\magento\lib\Zend\Oauth\Http.php(190): Zend_Oauth_Http->_assessRequestAttempt(Object(Zend_Http_Response))
#1 C:\Development\stage\grantorino-appfactory-ab\magento\lib\Zend\Oauth\Http.php(191): Zend_Oauth_Http->startRequestCycle(Array)
#2 C:\Development\stage\grantorino-appfactory-ab\magento\lib\Zend\Oauth\Http.php(191): Zend_Oauth_Http->startRequestCycle(Array)
#3 C:\Development\stage\grantorino-appfactory-ab\magento\lib\Zend\Oauth\Http\AccessToken.php(52): Zend_Oauth_Http->startRequestCycle(Array)
#4 C:\Development\stage\grantorino-appfactory-ab\magento\lib\Zend\Oauth\Consumer.php(225): Zend_Oauth_Http_AccessToken->execute()
#5 C:\Development\stage\grantorino-appfactory-ab\magento\app\code\local\AppFactory\Basic\controllers\TestController.php(96): Zend_Oauth_Consumer->getAccessToken(Array, Object(Zend_Oauth_Token_Request))
I also tracked the Zend_Oauth_Http_AccessToken and found out that I actually im getting a new nonce on every request:
/**
* Initiate a HTTP request to retrieve an Access Token.
*
* @return Zend_Oauth_Token_Access
*/
public function execute()
{
$params = $this->assembleParams();
Zend_Debug::dump($params);
$response = $this->startRequestCycle($params);
$return = new Zend_Oauth_Token_Access($response);
return $return;
}
/**
* Assemble all parameters for an OAuth Access Token request.
*
* @return array
*/
public function assembleParams()
{
$params = array(
'oauth_consumer_key' => $this->_consumer->getConsumerKey(),
'oauth_nonce' => $this->_httpUtility->generateNonce(),
'oauth_signature_method' => $this->_consumer->getSignatureMethod(),
'oauth_timestamp' => $this->_httpUtility->generateTimestamp(),
'oauth_token' => $this->_consumer->getLastRequestToken()->getToken(),
'oauth_version' => $this->_consumer->getVersion(),
);
if (!empty($this->_parameters)) {
$params = array_merge($params, $this->_parameters);
}
$params['oauth_signature'] = $this->_httpUtility->sign(
$params,
$this->_consumer->getSignatureMethod(),
$this->_consumer->getConsumerSecret(),
$this->_consumer->getLastRequestToken()->getTokenSecret(),
$this->_preferredRequestMethod,
$this->_consumer->getAccessTokenUrl()
);
return $params;
}
so the error message showing might be misleading.