twitter-dart / twitter-api-v2

The most famous and powerful Dart/Flutter library for Twitter API v2.0 🐦
https://pub.dev/packages/twitter_api_v2
BSD 3-Clause "New" or "Revised" License
167 stars 45 forks source link

Authenticating with OAuth 2.0 Application-Only is forbidden for this endpoint #610

Closed azkadev closed 1 year ago

azkadev commented 1 year ago

A few days ago I used your library to make a post on twitter,

my code,

import 'dart:convert'; 
import 'package:twitter_api_v2/twitter_api_v2.dart' as v2; 

void main() async {

  //! You need to get keys and tokens at https://developer.twitter.com
  final twitter = v2.TwitterApi(
    //! Authentication with OAuth2.0 is the default.
    //!
    //! Note that to use endpoints that require certain user permissions,
    //! such as Tweets and Likes, you need a token issued by OAuth2.0 PKCE.
    //!
    //! The easiest way to achieve authentication with OAuth 2.0 PKCE is
    //! to use [twitter_oauth2_pkce](https://pub.dev/packages/twitter_oauth2_pkce)!
    bearerToken: "token",

    //! Or perhaps you would prefer to use the good old OAuth1.0a method
    //! over the OAuth2.0 PKCE method. Then you can use the following code
    //! to set the OAuth1.0a tokens.
    //!
    //! However, note that some endpoints cannot be used for OAuth 1.0a method
    //! authentication.
    oauthTokens: v2.OAuthTokens(
      consumerKey: "my_secret_consumer",
      consumerSecret: "consumer_sceret",
      accessToken: "Acces",
      accessTokenSecret: "Acces_token",
    ),
    //! Automatic retry is available when network error or server error
    //! are happened.
    retryConfig: v2.RetryConfig(
      maxAttempts: 5,
      onExecute: (event) => print(
        'Retry after ${event.intervalInSeconds} seconds... '
        '[${event.retryCount} times]',
      ),
    ),

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 20),

  );

 try {
    //! You can easily post a tweet with the uploaded media.
    var res = await twitter.tweets.createTweet(
      text: 'Tweet with uploaded media', 
    );

    print(res.toJson());
  } catch (e) {
    print(e.toString());
  }
}

But today I can't use your library anymore, error

DataNotFoundException: No data exists in response.

  ✅ Status Code:
   403

  ✅ Request:
   GET https://api.twitter.com/2/users/me?

  ✅ Headers:
   {x-transaction-id: a64769761f4c6dd5, cache-control: no-cache, no-store, max-age=0, date: Fri, 30 Dec 2022 07:08:14 GMT, content-length: 316, x-response-time: 168, perf: 7626143928, x-connection-hash: 538a0d16a58332b61351ffbc11aff07023574e9d4ba3356a227a4e5a97434fe7, content-type: application/problem+json, server: tsa_k}

  ✅ Body:
   {
  "title": "Unsupported Authentication",
  "detail": "Authenticating with OAuth 2.0 Application-Only is forbidden for this endpoint.  Supported authentication types are [OAuth 1.0a User Context, OAuth 2.0 User Context].",
  "type": "https://api.twitter.com/2/problems/unsupported-authentication",
  "status": 403
}

  Please create an Issue if you have a question or suggestion for this exception.

hexaminate@hexaminate-Modern-14-B5M:~/azkadev/automation$ dart run test/test.dart
DataNotFoundException: No data exists in response.

  ✅ Status Code:
   403

  ✅ Request:
   POST https://api.twitter.com/2/tweets?

  ✅ Headers:
   {x-transaction-id: 1853dd95a2c6c802, cache-control: no-cache, no-store, max-age=0, date: Fri, 30 Dec 2022 07:10:12 GMT, content-length: 316, x-response-time: 167, perf: 7626143928, x-connection-hash: 92996a77e732cef61255f41e4b4bdc4381b2c11e79b4db23f763fdd2f88d8233, content-type: application/problem+json, server: tsa_k}

  ✅ Body:
   {
  "title": "Unsupported Authentication",
  "detail": "Authenticating with OAuth 2.0 Application-Only is forbidden for this endpoint.  Supported authentication types are [OAuth 1.0a User Context, OAuth 2.0 User Context].",
  "type": "https://api.twitter.com/2/problems/unsupported-authentication",
  "status": 403
}

  Please create an Issue if you have a question or suggestion for this exception.
github-actions[bot] commented 1 year ago

Thanks for your contribution! :)

myConsciousness commented 1 year ago

Hi @azkadev ,

Are you using v4.7.0 or higher? If so, changes have been made to the priority of tokens used in terms of the following Issue, and this is the expected behaviour.

Also, I feel that the official Twitter API is not designed to allow AppOnly and user context endpoints to be used at the same time, and OAuth 1.0a is not a top priority for this package as it is a legacy and will be deprecated authentication method.

So, the best we can do for now is to create an instance of TwitterApi with AppOnly and user context as follows:

void main() async {
  final userContextTwitter = v2.TwitterApi(
    //! Must be empty.
    bearerToken: "",

    oauthTokens: v2.OAuthTokens(
      consumerKey: "my_secret_consumer",
      consumerSecret: "consumer_sceret",
      accessToken: "Acces",
      accessTokenSecret: "Acces_token",
    ),
  );

  final appOnlytTwitter = v2.TwitterApi(
    bearerToken: "Your app-only bearer token.",
  );
}
myConsciousness commented 1 year ago

@azkadev ,

Also, you can check: