Authentication requests using HTTPS to an API in Java - java

I am looking to use an API called HookTheory. I am making the HTTPS calls in Java, and since its my first time using HTTP or HTTPS clients I am running into a few road blocks.
Here are the document's details on User Authentication:
You authenticate to the Hooktheory API by providing an HTTP Bearer Token, according to the OAuth 2 protocol. Your HTTP Bearer Token is retrieved through the API with your www.hooktheory.com username and password. To retrieve your HTTP Bearer Token, make the following request:
POST users/auth
The body of the request must contain your www.hooktheory.com username and password:
{
"username": "Hooktheory",
"password": "0123456789"
}
The response will contain three fields, as shown below:
{
"id": 1234,
"username": "Hooktheory",
"activkey": "aoa6jjacz34kcta3aomeqwuz89"
}
The "activkey" property contains your HTTP Bearer Token; include it as an authorization header in all future requests to the API.
Can someone explain in better detail how I would go about doing this in Java?
My starter code is the following:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
con.setRequestProperty("username", username);
con.setRequestProperty("password", password);
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
This code is basically a copy of the code here.
I get a 401 error (authentication) when I run the post code above. I'm guessing its because I haven't formatted the get/post requests correctly.
Can somebody point me in the right direction?

You've set username and password as request properties, which are HTTP headers. Per the HookTheory docs, you need to send these on the request body.
Specifically, you need to send the JSON request on the body like this:
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
Also, per their docs you should indicate that this is JSON by setting the Accept and Content-Type headers. This is done prior to sending the post request data through calls like this:
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
So the entire block looks like:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
wr.flush();
wr.close();

code 401 clearly specifies something wrong with authentication. stack trace shows unauthenticated on server side.
10.4.2 401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication"

Related

Java HTTPS (SSL) Connection Return 400 Status where as CURL/ARC works for same URL

I'm trying to connect to salesforce production account via OAuth and exchange an access token by giving a refresh token.
When i make a call using Chrome Advanced Rest Client or CURL i'm able to get the access token; but when i'm trying to make the same call using java HttpClient or URLConnection i'm getting a 400 status.
String url = "https://login.salesforce.com/services/oauth2/token";
String requestBody = "grant_type=refresh_token&client_id=myClientId&client_secret=myClientSecret&refresh_token=myRefreshToken";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "myapp/1.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(requestBody);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + requestBody);
System.out.println("Response Code : " + responseCode);
BufferedReader br = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
//print result
System.out.println(response.toString());
I examined both requests using wireshark. And both the requests look identical. Since the URL is https, i posted the request to a dummy URL and verified using wireshark.
Anybody ran into this kinda of issue ? BTW the same code works for developer edition and is not working for production edition. And for production edition it works with CURL and Chrome ARC.
Salesforce only allows HTTPS connections on TLS 1.1 or higher. Since i'm running on Java 7, default is TLS 1.0. As a result the request is failing from Java.
By adding the following property we can add support for TLSv1.1 and TLSv1.2
-Dhttps.protocols=TLSv1.1,TLSv1.2

Difference between Java Post Request and browser post request

I am trying to use api of one popular russian social networks. I am using OAuth via Java HttpUrlConnection. The problem is, when I send post data via Java, I get 401 response code. When I copy request and paste it browser, I get redirect to URL containing access token I need. That means that my post request is correct, but why when I send it with Java I get 401 error? When I send request with incorrect password, I get 200. It means that request is correct too.
private void getHomeAuth() throws Exception {
String url = "https://oauth.vk.com/authorize?client_id=APP_ID&scope=friends&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.34&response_type=token";
URL oauth = new URL(url);
HttpURLConnection connection = (HttpURLConnection) oauth.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = connection.getResponseCode();
System.out.println("Response code: " + responseCode);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while((inputLine = reader.readLine()) != null)
response.append(inputLine + "\n");
reader.close();
PrintWriter writer = new PrintWriter("auth.html");
writer.print(response);
writer.close();
parse();
cookies = connection.getHeaderField("Set-Cookie");
referer = connection.getURL().toString();
}
private void postAuth() throws Exception {
email = URLEncoder.encode("example#gmail.com", "UTF-8");
password = "password";
_origin = URLEncoder.encode(_origin, "UTF-8");
String url = "https://login.vk.com/?act=login&soft=1";
URL post = new URL(url);
String urlParameters = "ip_h=" + ip_h + "&_origin=" + _origin + "&to=" + to + "&expire=" + expire + "&email=" + email + "&pass=" + password;
HttpsURLConnection con = (HttpsURLConnection) post.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Cookie", cookies);
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("Sent post. Response code: " + responseCode + "\nRequest: " + post.toString() + urlParameters + "\nRequestMethod: " + con.getRequestMethod());
}
I also tryied to send this request via addon in browser, and the result was correct. I obtained access token from redirect link.
Maybe the problem is that something inside request is incorrect. I have tried to monitor requests from java app, but I failed.
My experience with this kind of problem is that the http request that first authenticates the user also puts cookies (scope varies from case to case) into the response and subsequent http requests are expected to contain those cookies. Look very closely at the complete returned response headers to see what cookies might have been returned.

RestEasy client to secured service

We have deployed RestEasy services, as part of application, and secured them with filter (a class that implements javax.servlet.Filter). Filter checks if object of the User class exists in the session. The user object is inserted into session when user logs in. Everything works fine.
However, we need to create standalone app that accesses these services. We decided to use RestEasy client API. We can access these services if the filter is turned off, but how do we perform this logging in and session manipulation from RestEasy client API.
Let's assume your standalone client was written in Java.
Then a sample code would look like this.
First we need to authenticate the user by calling your auth service and obtain a valid session ID. Let's assume the obtained session id is equivalent to "f47cdba8-d066-48e8-ad29-8c4222906bc7". Then we can call the REST service with the valid session ID as a HTTP header parameter.
String url = "http://localhost:8081/AuthService/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Authorization", "token=f47cdba8-d066-48e8-ad29-8c4222906bc7");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
At the back end you need to process this HTTP header parameter based Session ID and validate the oncoming request before serving it.
Hope this helps.

Java POST Connection Timeout Using HttpsUrlConnection

I have a question about making a POST request with Java, and since this is my first attempt at something of this magnitude, please bear with me. I am working on a third party application in Java to connect to a website and make POST requests. Am I doing this correctly? Here is what I have so far:
Website Code:
(This is the code the website has for "bumping a trade" which simply sends 2 pieces of data to a php file. The URL is http://cdn.dota2lounge.com/script/trades.js)
function bumpTrade(trade, code) {
$.ajax({
type: "POST",
url: "ajax/bumpTrade.php",
data: "trade=" + trade + "&code=" + code
});
}
My Java Code:
private void sendPost() throws Exception {
//String url = "https://www.cdn.dota2lounge.com/script/ajax/bumpTrade.php";
String url = "https://www.cdn.dota2lounge.com/script/ajax/bumpTrade.php";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
String urlParameters = "trade=96510389&code=94cebd9";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
However I am receiving a connection timeout error when attempting to connect. I would be very grateful if someone could point me in the right direction!
The Java client code seems to be on the right track. But it looks like the URL in the code was the wrong URL.
Using the url "http://www.dota2lounge.com/ajax/bumpTrade.php" and HttpUrlConnection, I was able to get a 200 response (OK):
Sending 'POST' request to URL : http://www.dota2lounge.com/ajax/bumpTrade.php
Post parameters : trade=96510389&code=94cebd9
Response Code : 200
However nothing beyond that. Not sure of the API of the remote site but hopefully that's some help.

post requests to google fusion tables

I've been trying to insert new rows in my google fusion table, but in response I obtain a 401 error; also any other post request doesn't work.
I've already put the oauth access token, and also the api key, here is the code:
private void sendPost() throws Exception {
String url = "https://www.googleapis.com/fusiontables/v1/query?sql= **here I put my query** ?key="+ "**here I put my api key**";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Chrome/11.0.660.0");
con.addRequestProperty("client_id", "**here I put my client_ID**");
con.addRequestProperty("client_secret", "**here I put my client_secret**");
con.setRequestProperty("Authorization","Oauth " + "**here I put my access token**");
con.setRequestProperty("Content-Type", "application/json");
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(newInputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
}
Can you tell me if the code is wrong and in which point?
Thank you in advance.
Two separate requests are required:
a first POST request, to get the OAuth token. The body containing client_id, client_secret, redirect_uri, grant_type and the authorization_code.
a second POST request with body being the SQL command. In this case, INSERT INTO TableID (field1, field2, ...) VALUES (value1, value2, ...). This request needs the Authentication header token.

Categories