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