1

I want to create an Oauth with the twitter API https://api.twitter.com/1.1/statuses/user_timeline.json. I have gotten some Java code together and I have been able to reproduce the Signature in the twitter example Twitter Oath Example

My problem. My URL also contains some additional parameters and I'm not sure how to represent that in the %encoded String.
Here is what I have at the moment.

Method: "GET"
URL: "https://api.twitter.com/1.1/statuses/user_timeline.json
Parameters: "screen_name=user handle"
CONSUMER_API_KEY = "oauth_consumer_key=gdprVZGNotRealKeyZRGMUfP";
OAUTH_NONCE = "oauth_nonce=u4cknC6Lfea";
HMACSHA1 ="oauth_signature_method=HMAC-SHA1";
OAUTH_TIMESTAMP = "oauth_timestamp=1591889894";
ACCESS_TOKEN = "oauth_token=63345074-vNvsSSlMsMmNotRealKeytGR040GD9";
oauth_version ="oauth_version=1.0";
public class MainActivity extends AppCompatActivity {
    private ArrayList<MyTweet> tweets = new ArrayList<MyTweet>();
    private TextView post_reponse_text;
    private MyTweetsAdapter Adapter;
    Twitter twitter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button post_request_button = findViewById(R.id.test);
        post_reponse_text = findViewById(R.id.get_response_data);
        post_request_button.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public void onClick(View v) {
                postRequest();
                String url = "https://api.twitter.com/1.1/statuses/user_timeline.json";

                 test t1 = new test();
                 //t1.concatURL(url,"GET");
                 //String percented = t1.encode(url);

                String percentURL1 = t1.encode(url);
                Log.v("String encoded with ent",percentURL1);

                Log.v("Concat:",t1.StringConcat());
                String fin = t1.concatURL(percentURL1,"GET") + t1.encode(t1.StringConcat());


                Log.v("FinishedString:",fin);


                Log.v("Sig:",t1.generateSignature(fin, "CONSUMERSECREATrFMeKkS", "TOKENSECREATvqWFWzxEZtGdc"));

            }
        });
    }

    private void postRequest() {
        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
        String url = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=user handle";
        final StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.e("HttpClient", "success! response: " + response.toString());
                        try {
                            // post_reponse_text.setText("Post Data : " + response);
                            post_reponse_text.setText("Twitter Feed");
                            JSONArray jsonArray = new JSONArray(response);

                            for (int i = 0; i < jsonArray.length(); i++) {
                                JSONObject session = jsonArray.getJSONObject(i);

                                MyTweet tweet = new MyTweet("might need to remove", "this also");
                                tweet.content = session.getString("text");
                                tweet.author = session.getString("id_str");
                                tweets.add(tweet);
                            }

                            /*Send to Adapter*/
                            RecyclerView recyclerView = findViewById(R.id.my_recycler_view);
                            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
                            recyclerView.setLayoutManager(layoutManager);
                            Adapter = new MyTweetsAdapter(tweets);
                            recyclerView.setAdapter(Adapter);
                            Adapter.setOnItemClickListener(new MyTweetsAdapter.OnItemClickListener() {
                                @Override
                                public void onItemClick(int position) {

                                }
                            });

                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.v("Error:", "Error Creating JSON object");
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
                Log.e("HttpClient", "error: " + error.toString());
                post_reponse_text.setText("Failed to find Twitter feed");

            }
        })
        {

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

//Generated from postman and added manually
                params.put("Authorization", "OAuth oauth_consumer_key=\"notrealkeyZRGMUfP\",oauth_token=\"63139074-vNvsSSnotrealkey\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1592143976\",oauth_nonce=\"i5Ha2524SuC\",oauth_signature=\"DFf7rD9enXp1pIxsCkf99VC4rSE%3D\"");

                return params;
            }
        };
        queue.add(stringRequest);
    }
}

public class test {

//http://optimumbrew.com/blog/2015/03/oauth/how-to-generate-oauth-signature-for-twitter-in-core-java

//used to % encode string values
@RequiresApi(api = Build.VERSION_CODES.O)
public String encode(String value) {
    String encoded = "";
    try {
        encoded = URLEncoder.encode(value, "UTF-8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    String sb = "";
    char focus;
    for (int i = 0; i < encoded.length(); i++) {
        focus = encoded.charAt(i);
        if (focus == '*') {
            sb += "%2A";
        } else if (focus == '+') {
            sb += "%20";
        } else if (focus == '%' && i + 1 < encoded.length()
                && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
            sb += '~';
            i += 2;
        } else {
            sb += focus;
        }
    }
    Log.v("String Encoded:", sb);



    return sb;

}


//passes the string with consumer secret & token to generate a signature.
//I will send this signature in the header requests
@RequiresApi(api = Build.VERSION_CODES.O)
public String generateSignature(String signatueBaseStr, String oAuthConsumerSecret, String oAuthTokenSecret) {
    byte[] byteHMAC = null;
    try {
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec spec;
        if (null == oAuthTokenSecret) {
            String signingKey = encode(oAuthConsumerSecret) + '&';
            spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
        } else {
            String signingKey = encode(oAuthConsumerSecret) + '&' + encode(oAuthTokenSecret);
            spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
        }
        mac.init(spec);
        byteHMAC = mac.doFinal(signatueBaseStr.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return twitter4j.BASE64Encoder.encode(byteHMAC);
    // return new twitter4j.BASE64Encoder().encode(byteHMAC);
}

public String concatURL(String url, String method) {

    String contact = method + "&" + url+"&";
    return contact;
}


@RequiresApi(api = Build.VERSION_CODES.O)
public String StringConcat() {

   String CONSUMER_API_KEY = "oauth_consumer_key=gdnotrealkeyRGMUfP";
    String OAUTH_NONCE = "oauth_nonce=i5Ha2524SuC";
    String HMACSHA1 ="oauth_signature_method=HMAC-SHA1";
    String OAUTH_TIMESTAMP = "oauth_timestamp=1592143976";
    String ACCESS_TOKEN = "oauth_token=63139074-vNvnotrealkeygJn8VtGR040GD9";
    String oauth_version ="oauth_version=1.0";
    String screen_name = "screen_name=user handle";

            /*
            oauth_consumer_key=\"gdprVZGkHT7mOfALr8ZRGMUfP\",
            oauth_nonce=\"u4cknC6Lfea\",
            oauth_signature_method=\"HMAC-SHA1\",
            oauth_timestamp=\"1591889894\",
            oauth_token=\"63139074-vNvsSSlMsMmosQwJ2EWVmHvGzAlgJn8VtGR040GD9\"
             */


    String concat = CONSUMER_API_KEY+ "&" +OAUTH_NONCE+ "&" +HMACSHA1+ "&" +OAUTH_TIMESTAMP+ "&" +ACCESS_TOKEN+ "&" +oauth_version+ "&"+screen_name;
    //String concat = CONSUMER_API_KEY+ "&" +OAUTH_NONCE+ "&" +HMACSHA1+ "&" +OAUTH_TIMESTAMP+ "&" +ACCESS_TOKEN+ "&" +oauth_version;
    return concat;
}

}





Combining to make
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fuser_timeline.json&oauth_consumer_key%3DgdprVZGNotRealKeyZRGMUfP%26oauth_nonce%3Du4cknC6Lfea%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1591889894%26oauth_token%3D63345074-vNvsSSlMsMmNotRealKeytGR040GD9%26oauth_version%3D1.0%26screen_name%3Duser%20handle
Using postman I can get instances of successful auths and can see the created signature of those auths. Using the timestamps and nonces from postman I am trying to validate I can create the same signature as postman. So far I'm unsuccessful and I'm assuming its something to do with how i put the string together
Eamon M
  • 55
  • 2
  • 9

1 Answers1

0

The actual signature seems to be missing in the request

You can find more information at this link

https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature

Buzz back if you’re stuck and I’ll help you

Ralph
  • 309
  • 1
  • 8
  • Thank, really appreciate it. So if i use Postman I can send my consumer keys, access tokens,Consumer Secret and Token Secret. Postman then generates the signature by automatically adding the nonce, timestamp and signature type. I can then see the signature value returned. What im trying to emulate through Java is to add the SAME details from postman and Create the Same signature result. Ive followed the steps in the link u provided but im not getting the same result. So im assuming i havent put the string together correctly to generate the same Post man result – Eamon M Jun 14 '20 at 14:18
  • So i guess my question is, Given Method: "GET" URL: "https://api.twitter.com/1.1/statuses/user_timeline.json?" paramenter:"screen_name=user handle" CONSUMER_API_KEY = "oauth_consumer_key=gdprVZGNotRealKeyZRGMUfP"; OAUTH_NONCE = "oauth_nonce=u4cknC6Lfea"; HMACSHA1 ="oauth_signature_method=HMAC-SHA1"; OAUTH_TIMESTAMP = "oauth_timestamp=1591889894"; ACCESS_TOKEN = "oauth_token=63345074-vNvsSSlMsMmNotRealKeytGR040GD9"; oauth_version ="oauth_version=1.0"; What format should the String be before passing it through base64 encoding? – Eamon M Jun 14 '20 at 14:22
  • Still unclear, you have to use base64 after signing using HMac-SHA1 with the secret key. The process is slightly complex so you’d have to come up with some code here so that I can reference and provide a response – Ralph Jun 14 '20 at 18:16
  • Added the code. I use the method generateSignature() to pass the generated the string and the AuthConsumerSecret and oAuthTokenSecret. I believe this is working as i was able to test it using the twitter example. What i believe is wrong is the string i build to pass to the method and generate the signature. – Eamon M Jun 14 '20 at 18:59
  • Yeah, that is the usual suspect, did you try out Pathfix, helps if you are building OAuth based integrations to many providers – Ralph Jun 15 '20 at 01:28