Home>

Premises /What you want to achieve

I would like to tweet using Flutter.
The value of the GET request such as Timeline acquisition can be acquired correctly as shown below, but the POST request returns 403 as described in "Problem /Error Message". I will come.

As the flow of source code processing,

  1. Read access_token and access_token_secret which are obtained in advance in another file and saved in Firebase.
  2. Send a request in POST format to tweet using oauth1.
    It is a flow.

Problems /error messages occurring

flutter: {title: Forbidden, detail: Forbidden, type: about: blank, status: 403}

Corresponding source code

import'package: flutter /material.dart';
import'package: oauth1 /oauth1.dart' as oauth1;
import'package: url_launcher /url_launcher.dart';
import'root.dart';
import'package: cloud_firestore /cloud_firestore.dart';
import'package: firebase_core /firebase_core.dart';
import'dart: convert';
void main () {
  runApp (MyApp ());
}
/*
void setData (String collection, Map data) {
  FirebaseFirestore.instance.collection (collection) .add (data);
}
* //
class MyApp extends StatelessWidget {
  @override
  Widget build (BuildContext context) {
    return MaterialApp (
      title:'Flutter Demo',
      theme: ThemeData (
        primarySwatch: Colors.blue,
      ),
      home: MyWidget (),
    );
  }
}
class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState ()= >
 _MyWidgetState ();
}
class _MyWidgetState extends State <
MyWidget >
 {
  final controller= TextEditingController ();
  final platform= oauth1.Platform (
    'https://api.twitter.com/oauth/request_token',
    'https://api.twitter.com/oauth/authorize',
    'https://api.twitter.com/oauth/access_token',
    oauth1.SignatureMethods.hmacSha1,
  );
  final clientCredentials= oauth1.ClientCredentials (
    '<API key>',
    '<API secret key>',
  );
  late final auth= oauth1.Authorization (clientCredentials, platform);
  oauth1.Credentials? tokenCredentials;
  @override
  void initState () {
    super.initState ();
    //You can authenticate with PIN by setting Callback URL to "oob"
    auth.requestTemporaryCredentials ('oob'). then ((res) {
      tokenCredentials= res.credentials;
      //Open the login URL with launch ()
      launch (auth.getResourceOwnerAuthorizationURI (tokenCredentials! .Token));
    });
  }
  @override
  Widget build (BuildContext context) {
    return MaterialApp (
      home: Scaffold (
        body: Center (
          child: Column (
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              //Enter the PIN displayed after login
              TextFormField (
                controller: controller,
              ),
              ElevatedButton (
                onPressed: () async {
                  //Get Access Token based on the entered PIN
                  final pin= controller.text;
                  final verifier= pin;
                  final res= await auth.requestTokenCredentials (
                    tokenCredentials !,
                    verifier,
                  );
                  print ('Access Token: $ {res.credentials.token}');
                  print ('Access Token Secret: $ {res.credentials.tokenSecret}');
                  /*
                  FirebaseFirestore.instance.collection ('test_collection1'). add ({{
                    'access_token': res.credentials.token,
                    'access_token_secret': res.credentials.tokenSecret,
                  });
                   * //
                  //You can request to API using the obtained Access Token
                  final client= oauth1.Client (
                    platform.signatureMethod,
                    clientCredentials,
                    res.credentials,
                  );
                  /*final apiResponse= await client.get (Uri.parse (Uri.parse (
                        'https://api.twitter.com/1.1/statuses/home_timeline.json?count=1'),
                  );
                  print (apiResponse.body);
                   * //
                  final getResponse= await client.get (
                    Uri.https (
                      'api.twitter.com',
                      '/2 /tweets',
                      {'text':'Hello World !!'},
                    ),
                  );
                  final getBody= jsonDecode (getResponse.body.toString ());
                  print (getBody);
                  final postResponse= await client.post (
                    Uri.https (
                      'api.twitter.com',
                      '/2 /tweets',
                      {'text':'Hello World !!'},
                    ),
                  );
                  final postBody= jsonDecode (postResponse.body.toString ());
                  print (postBody);
                },
                child: Text ('authentication'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

HereI tried to send a request even if the get of the source code described in was changed to post, but the following response was returned. (It seems that OAuth 2.0 does not authenticate.)

If you have any other necessary information, please let me know.

Supplementary information

  • Flutter official page (how to use Twitter API)

  • For how to specify the parameter of Uri.https, refer to "Get Timeline" above.

  • The result of writing the code by the parameter specification method taught by suzukis.

    Error: Too many positional arguments: 1 allowed, but 2 found.
    Try removing the extra positional arguments.
    final res= await client.post (

  • Returned message

    flutter: {errors: [{parameters: {ids: []}, message: Theidsquery parameter can not be empty}, {parameters: {text: [Hello World !!]}, message: The query parameter [text] is not one of [ids, expansions, tweets.fields, media.fields, poll.fields, place.fields, user.fields]}], title: Invalid Request, detail: One or more parameters to your request was invalid., type: https://api.twitter.com/2/problems/invalid-request}
    flutter: {errors: [{parameters: {text: [Hello World !!]}, message: The query parameter [text] is not one of [expansions, tweet.fields, media.fields, poll.fields, place.fields, user.fields]}], title: Invalid Request, detail: One or more parameters to your request was invalid., type: https://api.twitter.com/2/problems/invalid-request}

It is easier to solve the problem by posting the error message itself instead of returning the error message. First of all, it may be better to try it by directly specifying the oauth system without Firebase. In addition, it may be better to try curl or POST MAN for the time being as described in the Twitter API documentation. I got the knack of Twitter API with POST MAN, curl.

zunda2022-01-26 20:27:48

@zunda Thank you for your comment. I tried to make a request directly from the oauth system without Firebase. The error message returned at that time is described in the supplementary information. Looking at the content of the message, it seems that it is recognized as a Twitter lookup request when a GET request is made to the same URL, but isn't it sent by post? Thank you. I will try using post man etc.

Yuu2022-01-26 20:27:48

I can't say anything because I'm not familiar with the languages ​​listed, but it's easier to start with a simple API. The API isEven is very simple.

zunda2022-01-26 20:27:48

got it. thank you.

Yuu2022-01-26 20:27:48