A while back I came across a very useful service that I thought could be used for a lot of things. The service that I am talking about is PushBullet developed by redittor /u/guzba. I decided to try and write a small android app that would allow me to share content across devices using this service.
PushBullet has an API that was developed recently and it seemed to work well with
curl https://www.pushbullet.com/api/devices -u API_KEY:
I basically wanted to execute the same thing on my android device. As any Android developer will tell you making HTTP calls from Android isn’t exactly the easiest thing in the world, you have to wrap your call in an AsyncTask and then use the Handler mechanism to update the UI when the call is complete. Luckily, James Smith has wrapped all this up, very neatly, in a android-async-http library that is a breeze to integrate into your project.
The PushBullet API uses Basic HTTP authentication as a security mechanism. This means we must pas our API key as the username to the PushBullet API when we request devices from it. This all sounds fairly straight forward and the code to call the devices page using the android-async-http library looks like this.
AsyncHttpClient client = new AsyncHttpClient();
client.setBasicAuth("API_KEY", "",
new AuthScope("pushbullet.com", 443, null));
client.get("https://www.pushbullet.com/api/devices", new AsyncHttpResponseHandler())
This should all have worked but it doesn’t. Looking at the logs, I always saw the same error
04-23 08:52:12.845: W/DefaultRequestDirector(21976): Authentication error: Unable to respond to any of these challenges: {}
Googling around, it seemed that the error was that the server did not tell the client that it used basic HTTP auth but simply said we were “Unauthorized” to view this webpage. A proper configuration of the server would have resulted in our client receiving a list of challenges to reply with and would have sent the basic auth to the server. The HTTP client library does not send the basic auth credentials in the first request to the server but only when the server says that it needs these credentials. The alternative now is to send the basic auth to the server with our initial request.
To do that however, we must first encode our username and password.
String encoded = new String(Base64.encode("API_KEY:".getBytes(), Base64.NO_WRAP));
And then pass this encoded string in the “Authorization” header of our request.
client.addHeader("Authorization", "Basic " + encoded);
That’s it, because the Basic auth credentials are not sent to the server with the initial request the server replies back with proper JSON data.
I spent a good 6 hours trying to figure this out, I hope others don’t have too.







