Twitter API responds with "Your credentials do not allow access to this resource" while calling statuses/update.json
Asked Answered
I

4

7

I'm using Hybridauth 3 in my PHP app to make some periodical tweets on behalf of my account. The app has all possible permissions. I'm giving it all permissions when it asks for them on the first auth step. After that Twitter redirects me to the specified callback URL and there I'm getting a pair of access_token and access_token_secret. But when I'm trying to make a tweet using these tokens - it gives me:

{"errors":[{"code":220,"message":"Your credentials do not allow access to this resource."}]} 

Here's how I'm trying to make a tweet:

$config = [
    'authentication_parameters' => [
    //Location where to redirect users once they authenticate 
    'callback' => 'https://mysite/twittercallback/',
    //Twitter application credentials
    'keys' => [
            'key'     => 'xxx', 
            'secret' => 'yyy' 
    ],
    'authorize' => true
    ]
];

$adapter = new Hybridauth\Provider\Twitter($config['authentication_parameters']);

//Attempt to authenticate the user 
$adapter->setAccessToken(/*tokens I've got from getAccessToken() on /twittercallback/*/);

if(! $adapter->isConnected()) {
    // never goes here, so adapter is connected
    return null;
}

try{  
    $response = $adapter->setUserStatus('Hello world!');
}
catch (\Exception $e) {
    // here I've got the error
    echo $e->getMessage();
    return;
}

Tried to recreate tokens and key\secret pairs and passed auth process for the app many times, including entering password for my Twitter account (as suggested in some posts on stackoverflow) but still have this error.

P.S. According to this, Hybridauth has fixed the issue in the recent release.

Ierna answered 20/9, 2017 at 20:23 Comment(0)
I
0

After comparing headers of outgoing requests from my server with the ones required by Twitter, I've noticed that Hybris doesn't add very important part of the header: oauth_token. At least it's not doing this in the code for Twitter adapter and for the scenario when you apply access token with setAccessToken(). It's just storing tokens in the inner storage but not initializing corresponding class member called consumerToken in OAuth1 class. So to initialize the consumer token properly I've overridden the apiRequest method for Twitter class (before it used the defalut parent implementation) and added a small condition, so when consumer token is empty before the request - we need to try to init it.

public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [])
    {
        if(empty($this->consumerToken)) {
            $this->initialize();
        }

        return parent::apiRequest($url, $method, $parameters, $headers);
    }

I'm not sure that I've fixed it the best way, but as long as it's working - that's fine.

Ierna answered 21/9, 2017 at 10:26 Comment(0)
A
4

It looks like you are using application authentication as opposed to user authentication. In order to post a tweet, you must authenticate as a user. Also, make sure your Twitter app has read/write privileges.

Acetate answered 20/9, 2017 at 20:35 Comment(3)
Thank you for a quick reply. What makes you think I'm using app auth instead of user auth? Hybridauth has only one method of authentication ($adapter->authenticate()) which performs oauth. I doubt they would make the default behavior of the method to make app auth, because they are using it everywhere in their examples to make a tweet after the auth process finishes. And, as I said, my app has all possible privileges, I've checked that in My apps section of Twitter.Ierna
If you checked your apps settings at apps.twitter.com and confirmed that it has read/write privileges, that is good. However, that is not what you said in your original question. You said you are "giving it all permissions when it asks for them on the first auth step."Acetate
I see now you probably are user authenticated by setAccessToken. But, just to check, try a different API call other than setUserStatus -- one that works with either application or user authentication.Acetate
I
0

After comparing headers of outgoing requests from my server with the ones required by Twitter, I've noticed that Hybris doesn't add very important part of the header: oauth_token. At least it's not doing this in the code for Twitter adapter and for the scenario when you apply access token with setAccessToken(). It's just storing tokens in the inner storage but not initializing corresponding class member called consumerToken in OAuth1 class. So to initialize the consumer token properly I've overridden the apiRequest method for Twitter class (before it used the defalut parent implementation) and added a small condition, so when consumer token is empty before the request - we need to try to init it.

public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [])
    {
        if(empty($this->consumerToken)) {
            $this->initialize();
        }

        return parent::apiRequest($url, $method, $parameters, $headers);
    }

I'm not sure that I've fixed it the best way, but as long as it's working - that's fine.

Ierna answered 21/9, 2017 at 10:26 Comment(0)
I
0

For your info setAccessToken was fixed in v3.0.0-beta.2 (see PR https://github.com/hybridauth/hybridauth/pull/880)

Inalienable answered 4/12, 2017 at 14:28 Comment(1)
Thanks. Nice to see that the project is evolving. I'll add a note about the fix in the question's description.Ierna
D
0

I faced the same error when implementing a sample app in clojure and the following resource was a huge help to sort out my confusion about application-only auth vs user authentication: https://developer.twitter.com/en/docs/basics/authentication/overview/oauth

Dripstone answered 24/9, 2019 at 9:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.