1

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.

1 Answer 1

4

I was simply using the wrong oauth_token_secret, i should have used the one returned from the access_token not the request_token.

On another note the oauth_verifier is not needed when accessing the api endpoints.

Thats how the function ended up:

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' => '531a7d194914fbd207766bcb022cdc94',
    'consumerSecret' => 'f51868e362b9211d4fde5ebf412080b0',
    'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER
);

// Initiate oAuth consumer
$consumer = new Zend_Oauth_Consumer($params);
// Using oAuth parameters and request Token we got, get access token
$acessToken = new Zend_Oauth_Token_Access;
$acessToken->setParams(array(
    'oauth_token' => 'e3d089e2b420cd3b940c3cf67587a95d',
    'oauth_token_secret' => 'ab2f46861defe6ee5740f7a748301367'
));


// 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

return $response->getBody();


}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.