I am the sole developer for the tiny company I work for. I inherited a lot of legacy code. The code relevant to this issue is in Java 8 with SpringBoot.
An entity we get important data from recently updated how it serves data to use a REST API. The REST API can only be accessed over HTTPS and requires a valid username and password. The entity provided example code in several coding languages on how to use their new API. They recommend curl
as the default method of downloading their data, but offer examples in Java 8. I can successfully download a file using my credentials with the curl
command in *NIX. I cannot get the file to download using Java. I am reasonably sure the code is failing at the authentication level. I found this StackOverflow post suggesting it might be a problem with the TLS version, but I haven't been able to get that to work.
My boss has forbidden me from posting the entity's documentation for "security reasons" even though the documentation is publicly available. Similarly, I have to mask my code a bit. I will do everything I can to make the changes minimal.
Here is the two-part curl
command that works:
First get the Token:
curl --request POST --header "X-OpenAM-Username: username" --header "X-OpenAM-password: password" --header "Content-Type:application/json" --data "{}" https://sso.entityname.com/access/authenticate
I get a JSON back that includes a Token. Following the entity's example code, I pass the token in the next curl
command, then I successfully get the file:
curl --request GET --header "Cookie: entityauth=longgibberishstringofencryptioncharaters" --header Content-Type:text/csv "https://entityname.com/rest/secure/download/reports?shortName=awesomereport&version=L&format=C&start=01/01/2018&stop=01/15/2018"
Now this is my Java code. This is copied almost directly from the Entity's provided documention. The code compiles and runs without issue, but every single time it just creates and empty file named, "testOuput.txt".
public static void downloadReport() throws IOException {
String webUrl = "https://entityname.com/rest/secure/download/reports?shortName=awesomereport&version=L&format=C&start=01/01/2018&stop=01/15/2018";
URL url = new URL(webUrl);
String username = "username";
String password = "password";
String authString = username + ":" + password;
String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(authString.getBytes());
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", basicAuth);
InputStream inputStream = urlConnection.getInputStream();
try {
OutputStream out = new FileOutputStream("testOutput.txt");
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I have also tried simply wrapping Java around a shell curl
command using the Process
class, but to no avail. Below is my attempt to do that. Once again, it compiles and runs successfully but creates an empty file named "testOuput.txt" every time.
public static void downloadReportWithCurl() throws IOException {
String authentication = "curl --request POST --header X-OpenAM-Username: username --header X-OpenAM-password: password --header Content-Type:application/json --data {} https://sso.entityname.com/access/authenticate";
ProcessBuilder processBuilder = new ProcessBuilder(authentication.split(" "));
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> jsonMap = objectMapper.readValue(inputStream, Map.class);
String authToken = jsonMap.get("authId").toString().replace(".", ".*") + ".*";
String authHeader = "Cookie: entityauth=" + authToken;
System.out.println(authHeader);
String downloadCommand = "curl --request GET --header "Cookie: entityauth=longgibberishstringofencryptioncharaters" --header Content-Type:text/csv "https://entityname.com/rest/secure/download/reports?shortName=awesomereport&version=L&format=C&start=01/01/2018&stop=01/15/2018"
System.out.println(downloadCommand);
ProcessBuilder processBuilder2 = new ProcessBuilder(downloadCommand.split(" "));
Process process2 = processBuilder2.start();
InputStream dataStream = process2.getInputStream();
try {
OutputStream out = new FileOutputStream("testOutput.txt");
byte[] buf = new byte[1024];
int len;
while ((len = dataStream.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
dataStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
If anyone can help me resolve this issue, I'd be very grateful.