Why would my Oauth POST request to Twitter Ads API fail, while the GET request works fine

Viewed 28

I've successfully been able to query the Twitter Ads API with GET requests, but I'm trying to POST (to generate reports) and those keep failing with an UNAUTHROIZED_ACCESS "This request is not properly authenticated" error from Twitter.

I have been able to successfully run the query from Postman, so my credentials are OK. I have tried a couple of oAuth libraries (the oauth and oauth-1.0a libraries from npm) and I believe the root cause may be in the way they're generating the oAuth signature in the header.

Here's some test code which shows the problem:

    let key = TWITTER_CONSUMER_API_KEY;
    let secret = TWITTER_CONSUMER_API_SECRET_KEY;
    let urlPost = 'https://ads-api.twitter.com/11/stats/jobs/accounts/<<accountid>>?entity=CAMPAIGN&entity_ids=i8be1&granularity=DAY&metric_groups=BILLING,ENGAGEMENT,MEDIA,WEB_CONVERSION&start_time=2022-06-12T00:00:00+10:00&end_time=2022-07-27T00:00:00+10:00&placement=ALL_ON_TWITTER';
    let urlGet = 'https://ads-api.twitter.com/11/stats/jobs/accounts/<<accountid>>';    
    let oauth_token = <<OAUTH TOKEN>>;
    let oauth_token_secret = <<OAUTH TOKEN SECRET>>;

    // METHOD 1
    const OAuth = require('oauth-1.0a')

    const oauthConsumer = OAuth({
        consumer: {
            key: key,
            secret: secret
        },
        signature_method: 'HMAC-SHA1', 
        hash_function(base_string, key) {
            return crypto
                .createHmac('sha1', key)
                .update(base_string)
                .digest('base64')
        }
    });

    const authHeaderPost = oauthConsumer.toHeader(oauthConsumer.authorize({
        url: urlPost,
        method: 'POST',
    }, {key: oauth_token, secret: oauth_token_secret})); 

    const authHeaderGet = oauthConsumer.toHeader(oauthConsumer.authorize({
        url: urlGet,
        method: 'GET',
    }, {key: oauth_token, secret: oauth_token_secret})); 


    let initialResponse = await fetch(urlGet, {
        method: 'GET',
        headers: new Headers({
            Authorization: authHeaderGet["Authorization"]
        })
    });
    console.log(`[TEST] Method 1 GET Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);


    initialResponse = await fetch(urlPost, {
        method: 'POST',
        headers: new Headers({
            Authorization: authHeaderPost["Authorization"]
        })
    });
    console.log(`[TEST] Method 1 POST Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);

    
    // METHOD 2
    import oauth from 'oauth'; // This is the npm library "oauth"

    let extra_params = {};
    const oAuthConsumer2 = new oauth.OAuth(
        'https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token',
        key,
        secret,
        '1.0', ``, 'HMAC-SHA1'
    );
    let orderedParametersPost= oAuthConsumer2._prepareParameters(oauth_token, oauth_token_secret, "POST", urlPost, extra_params);
    let headerPost = oAuthConsumer2._buildAuthorizationHeaders(orderedParametersPost); 
    let orderedParametersGet= oAuthConsumer2._prepareParameters(oauth_token, oauth_token_secret, "GET", urlGet, extra_params);
    let headerGet = oAuthConsumer2._buildAuthorizationHeaders(orderedParametersGet); 


    initialResponse = await fetch(urlGet, {
        method: 'GET',
        headers: new Headers({
            Authorization: headerGet
        })
    });
    console.log(`[TEST] Method 2 GET Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);


    initialResponse = await fetch(urlPost, {
        method: 'POST',
        headers: new Headers({
            Authorization: headerPost
        })
    });
    console.log(`[TEST] Method 2 POST Received Successful?`, initialResponse.status >= 200 && initialResponse.status <= 299);
    
    console.log(`[TEST ************************************************************************************************************************************************************]`);

    
}

The results are that both GET requests work successfully, but both POST requests fail.

Is there something I'm doing incorrectly?

0 Answers
Related