Bitbucket API Create New Issue 401 Unauthorized - android

I am using OkHttp to make a POST request to the Bitbucket API to create a new issue. Their documentation says that a private repo or a private issue tracker require authentication to create new issues with this API. Both my repo and my issue tracker are public so there shouldn't be any issues with that. However when I make the call to create a new issue I get a 401 unauthorized response. Here is the code I am using to make the call:
FormEncodingBuilder builder = new FormEncodingBuilder();
String t = "{" +
"\"status\": \"new\"," +
"\"priority\": \"trivial\"," +
"\"title\": \"This is a title\"," +
"\"content\": \"This is the content\"," +
"\"is_spam\": false\n" +
"}";
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), t);
String url = "https://bitbucket.org/api/1.0/repositories/userName/repoName/issues"
Request request = new Request.Builder().url(url)
.post(requestBody)
.build();
Response response = new OkHttpClient().newCall(request).execute();
The Question:
Can anyone tell me why I am getting an unauthorized response back?
UPDATE
Per Jim Redmond I have changed my request to authenticate first. I am now making a POST to https://bitbucket.org/site/oauth2/authorize?client_id=myConsumerKey&response_type=token and I get response 200 OK but I do not see a token in the headers... Any idea why I'm not getting a token in response?

As the documentation also says, authentication is required for this method. It doesn't matter if your repo or issue tracker are public; there still needs to be a "reported_by" user.

Related

Android, OkHttp, AWS4Signer, aws-api-gateway - "Missing Authentication Token"

i am trying to sign a http request to aws api gateway in android using okhttp. i have more or less used the code in this stackoverflow question stackoverflow question
i use CognitoCachingCredentialsProvider() to get a credentialsProvider object. i then use getCredentials() to get the credentials. i then use the following: credentials.getAWSAccessKeyId(), credentials.getAWSSecretKey() and credentials.getSessionToken() to get the necessary keys and token. i use them in postman and am able to successfully execute the api gateway.
the request fails in android using okhttp, returning a code 403 with the message "Missing Authentication Token".
this is how i prepare the request: i build a DefaultRequest object, setting the endpoint and httpmethod. i then use AWS4Signer to sign the request, passing the credentials object as the signer.sign(defaultRequest, credentials) parameter.
i get a map of headers by calling getHeaders() on the defaultRequest. i create two lists, one called key for the key and one called value for the value. i then loop through the map, loading the keys and corresponding values into the two lists.
i then build my okhttp request as follows:
Request request = new Request.Builder()
.url(my ApiEndPoint)
.addHeader(key.get(0), value.get(0))
.addHeader(key.get(1), value.get(1))
.addHeader(key.get(2), value.get(2))
.addHeader(key.get(3), value.get(3))
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.post(body)
.build();
i notice the following:
in the headers map, key x-amz-security-token has a value ....ending in hKADF87VZ44w9IvZ1gU=
printing out the okhttp request, the key x-amz-security-token has a value .... ending in hKADF87VZ44w9IvZ1gU\u003d
the = is replaced by \u003d, could this be the problem? if so, how to prevent this?
otherwise, any help in solving this problem will be greatly appreciated.
thanks
managed to solve the problem. seems that assigning the headers to the OkHttp request was the problem. so here's my code:
i first get AWSSessionCredentials credentials. then:
AmazonWebServiceRequest amazonWebServiceRequest = new AmazonWebServiceRequest() {
};
String API_GATEWAY_SERVICE_NAME = "execute-api";
com.amazonaws.Request requestAws = new DefaultRequest(amazonWebServiceRequest, API_GATEWAY_SERVICE_NAME);
you can use either the service endpoint:
URI uri = URI.create("https://apigateway.eu-west-1.amazonaws.com");
or your api url (the invoke url for api as per Api Gateway console Stages option (The deployed api)):
String invokeUrl = "https://xxxx.execute-api.eu-west-1.amazonaws.com/yyy/zzzzz";
// using the invoke url
URI uri = URI.create(invokeUrl);
requestAws.setEndpoint(uri);
requestAws.setResourcePath(invokeUrl);
requestAws.setHttpMethod(HttpMethodName.POST);
now sign the request
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(API_GATEWAY_SERVICE_NAME);
signer.setRegionName(Region.getRegion(Regions.EU_WEST_1).getName());
signer.sign(requestAws, credentials);
get the headers
// get map of headers
Map<String, String> headers = requestAws.getHeaders();
// create objects for the headers to add manually in OkHttp request builder
String x_date = null;
String x_token = null;
String authorization = null;
//get and assign values
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equals("x-amz-security-token")) {
x_token = entry.getValue();
}
if (entry.getKey().equals("X-Amz-Date")) {
x_date = entry.getValue();
}
if (entry.getKey().equals("Authorization")) {
authorization = entry.getValue();
}
}
build the OkHttp request:
Request request = new Request.Builder()
.url(invokeUrl)
.addHeader("Content-Type", "application/json")
.addHeader("X-Amz-Date", x_date)
.addHeader("x-amz-security-token", x_token)
.addHeader("Authorization", authorization)
.post(body)
.build();
now make your OkHttp call.
hope this is helpful to someone.

How to access cookie and check if it has expired using okhttp3 and PersistentCookieStore?

I am working on an Android app in which a log in post request is made to a webservice. The request returns a cookie which expires in 20 minutes.
Using okhttp3 and this PersistentCookieStore library, I got the cookie to be stored and subsequently added it as request header to access authentication-required get requests (e.g. personal information that are non-public).
The code goes this way,
CookieJar myCookieJar = new PersistentCookieJar(new SetCookieCache(),
new SharedPrefsCookiePersistor(this));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(HttpRequests.cookieJar).build();
I then call a method like this inside an (after I have gone through another log in Async task to get the cookie) Async task to perform a get request that requires authentication,
public static String PostReq(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.addHeader("Cookie", "key=value")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
catch(Exception e){
}
}
The .addHeader("Cookie", "key=value") adds the cookie to the header to tell the webservice that I am authenticated.
Here comes my difficulty. Since the cookie expires after 20 minutes, I would like to be able to access the cookie itself to check for the expiration time and possibly redirect the user to the log in activity by calling the method,
myCookie.expiresAt()
and comparing it to
System.currentTimeMillis()
I tried to look at the PersistentCookieStore codes and found that it uses a SharedPreference with the key "CookiePersistence". I looked inside this file while my emulator was running the app and found it to be empty however.
How would I be able to access this cookie that I have obtained? Much thanks for any advice to be given.
OK, this is old, but I was facing the same problem, and here is how I fixed it.
Hold a reference to your SetCookieCache used to instantiate your CookieJar:
SetCookieCache cookieCache = new SetCookieCache();
CookieJar myCookieJar = new PersistentCookieJar(
cookieCache,
new SharedPrefsCookiePersistor(this)
);
Then use this to find your cookie and check it:
for (Cookie cookie : cookieCache) {
if (cookie.name().equals("cookie_name") && cookie.persistent()) {
//cookie is still good
break;
}
}
Or use cookie.expiresAt() to do your thing.

REST POST not responding in Xamarin.Android App. It is responding with Postman but not app.

I am sending POST request from Xamarin.Android appl on VS 2015 using RestSharp but no response is arriving. I increased timeout but no response. IT IS WORKING WITH POSTMAN but not with Android app.
RestClient client = new RestClient("https://" + orgId + ".internetofthings.ibmcloud.com");
RestRequest request = new RestRequest("/api/v0002/application/types/" + typeId + "/devices/" + deviceId + "/events/" + typeId + deviceId, Method.POST);
byte[] byteArray = Encoding.UTF8.GetBytes(username + ":" + password);
string authenticationToken = Convert.ToBase64String(byteArray);
request.AddHeader("Authorization", "Basic " + authenticationToken);
request.Timeout = 2000000;
request.AddJsonBody(newVal);
IRestResponse response = client.Execute(request);
return response.StatusCode.ToString();`
I am sending only "newVal" (string) in the body. This works with Postman. Please let me know if more explanation is required. THANK YOU SO MUCH.
Environment:
Visual Studio 2015, RESTSharp, Xamarin.Android, Server: IBM BlueMix
not sure where this is failing by might be that you don't pass the header correctly or the body message doesn't have the correct JSON format. You can check that on below link and make sure it is correct
https://docs.internetofthings.ibmcloud.com/swagger/v0002.html#/
This is resolved, Issue was with the 'content type'. I was adding content type as:
request.AddHeader("Content-Type","application/json");
but Content type was not setting for some reason and that's why my request was being shut from server and returned status code 0.
So instead, I did the following and it worked fine.
request.JsonSerializer.ContentType = "application/json; charset=utf-8";

Okhttp Put method returning 'Method Not Allowed'

I am attempting to call a put method on my server using OkHttp from an Android application.
This is the api method signature:
public void Put(int userId, string regId)
{
}
This is the Android code to call the above method:
private boolean SendGCMRegIdToServer(String registrationId, Integer userId) throws IOException {
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host(serverApiHost)
.addPathSegment("AppDashboard")
.addPathSegment("api")
.addPathSegment("GCM/")
.build();
MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String json = "{'userId':" + userId + ","
+ "'regId':'" + registrationId + "'"
+ "}";
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.put(requestBody)
.build();
//this should post the data to my server
Response response = client.newCall(request).execute();
if(response.code() == 400)
return false;
return true;
}
Now the problem is I am getting the error code 405 in the response saying Method not allowed, but I cannot see where the problem is because I can successfully call the method using Postman on the server itself as below:
http://localhost/AppDashboard/api/GCM?userId=5&regId=123
I'm thinking it may have something to do with an integer or string being passed incorrectly in the JSON string, but cannot see why this isn't working.
i had the same problem and server was returning 405 . after some search i realized that is a configuration problem on IIS that does not let put requests. so there is no problem in android code and you should config your server to let this kind of requests.
see this , this and this
Ok thanks for replies guys but seems I was getting a little confused between the two methods I was using to pass the params to my API.
Here's what I did:
changed the signature of the method to post with a param [FromBody] as a Model (only supports one paramater)...
public void Post([FromBody]UserGcmRegIdModel model)
{
}
I was then able to change my method call to the following using a nicer JSONBuilder and using .post in the request builder rather than .put
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("UserId", userId);
jsonObject.put("RegId", registrationId);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObject.toString();
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
I still don't know if there is a problem with put() methods on IIS but using a post in my case was absolutely fine so I'm going with that...
I see two different approaches in your REST api calls. In the one of OkHttp you send a PUT method with a JSON object serialized, and in POSTMAN you send a PUT (although I guess you do a GET) request with the parameters within the URL, I mean not in JSON body structure.
Anyway, HTTP 405 is telling you that your backend does not support the PUT method, and probably it's expecting a POST method with the "X-HTTP-Method-Override:PUT" HTTP header since POST is more standard method in REST than PUT.
What would I do is check your POSTMAN request carefully and adjust the one of Android to be the same method, parameters and headers, not more.
Answer Update (as question has been updated)
Of course there is a problem with that verb, as I said above IIS handles only the standard methods and PUT is not one of those. You have three choices:
Change your PUT to POST.
Use POST with X-HTTP-Method-Override to PUT. (reference)
Modify IIS config to support non standard REST methods. I
personally wouldn't suggest the 3rd one, since it's attached to the
backend config (e.g. imagine you change IIS to NancyFX).

404 error with POST and OkHttp3

I'm having an issue posting data to the Challonge API with OkHttp3 on Android... This is the jist of my code:
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder urlBuilder = new HttpUrl.Builder();
urlBuilder = HttpUrl.parse("https://api.challonge.com/v1/tournaments/"+EVENT_ID+".json")
.newBuilder();
RequestBody postBody = new FormBody.Builder()
.add("_method", "post")
.add("api_key", API_KEY)
.add("participant[name]", name.getText().toString())
.add("participant[misc]", forum_id.getText().toString())
.build();
Request request = new Request.Builder()
.url(urlBuilder.build().toString())
.post(postBody)
.build();
Response response = client.newCall(request).execute();
No matter what I do, the resulting reponse is a 404 page.
If I do a GET response to the same URL, I get a proper response. However, the moment I add .post(postBody) to the request, its immediately 404s.
The documentation for the Challonge API is here:
http://api.challonge.com/v1/documents/participants/create
It looks to me like you're just using the wrong URL. The URL you've got there, "https://api.challonge.com/v1/tournaments/"+EVENT_ID+".json", is the URL for retrieving a single tournament, as seen here. This link was meant to receive GET requests.
According to the link you provided, you should alter your code to POST to https://api.challonge.com/v1/tournaments/"+EVENT_ID+"/participants.json

Categories

Resources