I'm pretty new to OAuth and am trying to refresh a token using a simple java client. Everything seems to go ok (or I think it does), the problem is I can't tell from the response if it's a good one. The http response code is 200, but when trying to parse the response for access_token, I get a null. Also difficult to troubleshoot is the "raw" response is garbled, or encoded in some way. I was thinking maybe it's byte but it doesn't seem to be. Here's the code:
private static String getClientCredentials() {
String postParams = "grant_type=refresh_token&refresh_token=1234567890";
Pattern pat = Pattern.compile(".*\"access_token\"\\s*:\\s*\"([^\"]+)\".*");
String clientId = "myClientID123";
String clientSecret = "myClientSecret123";
String tokenUrl = "https://www.host.com/oauth2/tenant/token";
String auth = clientId + ":" + clientSecret;
String authentication = Base64.getEncoder().encodeToString(auth.getBytes());
BufferedReader reader = null;
HttpsURLConnection connection = null;
String returnValue = "";
try {
URL url = new URL(tokenUrl);
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", "Basic " + authentication);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
connection.setRequestProperty("Connection", "keep-alive");
connection.setDoOutput(true);
OutputStream outStream = connection.getOutputStream();
outStream.write(postParams.getBytes());
outStream.flush();
outStream.close();
System.out.println("Resp code: " + connection.getResponseCode());
System.out.println("Resp message: " + connection.getResponseMessage());
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
StringWriter out = new StringWriter(connection.getContentLength() > 0 ? connection.getContentLength() : 2048);
while ((line = reader.readLine()) != null) {
out.append(line);
}
String response = out.toString();
Matcher matcher = pat.matcher(response);
if (matcher.matches() && matcher.groupCount() > 0) {
returnValue = matcher.group(1);
}
System.out.println("response: " + response);
System.out.println("returnValue: " + returnValue);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
connection.disconnect();
}
return returnValue;
}
Here's the console output, sorry, I had to screenshot it because the characters didn't paste right:
Response Screenshot
Am I trying something that isn't allowed or is there a way to decode the response so I can run the pattern match to extract only the access_token? Or am I going about it all wrong? Any help is greatly appreciated in advance!
Related
I am struggling to understand the whole new idea of accessing my organizatioon's Sharepoint content using Sahrepoint REST API and I am trying to implementing it in java. My aim is to read all the files in "abc" folder which is in Documents folder. Steps I did.
Register the app:
Click Generate Client ID,
Click Generate Client Secret,
Gave Title,
Gave Appdomain as companyname.onmicrosoft, and
Gave Request URI as https://companyname.sharepoint.com/Shared%20Documents/Forms/AllItems.aspx
Got the app registered. I have client id, client secret, and tenant id.
I used the below code to generate the access token
public String getSpToken(String shp_clientId, String shp_tenantId, String shp_clientSecret) {
String accessToken = "";
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/" + shp_tenantId + "/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", " ");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
// Prepare RequestData
String jsonParam = "grant_type=client_credentials"
+ "&client_id=" + shp_clientId + "#" + shp_tenantId
+ "&client_secret=" + shp_clientSecret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/www.companyname.sharepoint.com#" + shp_tenantId;
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
//Printing the response to the console
System.out.println("Output from the REST" + outputString);
// Extracting accessToken from string, here response (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
//Printing the access token
System.out.println("Access token is " + accessToken);
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
Now that I have the access token in the String variable "accessToken", I used the following code to read the filenames inside the folder "abc" in Documents folder using readFiles() method
public void readFiles(String accessToken) {
try {
//Frame SharePoint siteURL
String siteURL = "https://companyname.sharepoint.com";
//Frame SharePoint URL to retrieve the name of all of the files in a folder
String wsUrl = siteURL + "/_api/web/GetFolderByServerRelativeUrl('Shared%20Documents/abc')/Files";
//Create HttpURLConnection
URL url = new URL(wsUrl);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
//Set Header
httpConn.setRequestMethod("GET");
httpConn.setRequestProperty("Authorization", "Bearer " + accessToken);
httpConn.setRequestProperty("accept", "application/json;odata=verbose"); //To get response in JSON
//httpConn.setRequestProperty("AllowAppOnlyPolicy", "true");
//httpConn.setRequestProperty("Scope", "http://sharepoint/content/sitecollection/web\" Right=\"FullControl");
//Read the response
String httpResponseStr = "";
InputStreamReader isr = null;
System.out.println(httpConn.getResponseCode());
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String strLine = "";
while ((strLine = in.readLine()) != null) {
httpResponseStr = httpResponseStr + strLine;
}
//Print response
System.out.println(httpResponseStr);
} catch (Exception e) {
System.out.println("Error while reading file: " + e.getMessage());
}
}
}
When I execute the above code I am getting {"error_description":"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}. Could someone please help me to figure out what I am doing wrong? I have been sitting on this for days and not able to resolve it.
Please help!
The code below shows a method, downloadUrl(), that takes a String, "myurl," its parameter. There are only two possible urls that I ever send to it, and the behavior of the method is different for each.
when myurl = URL1, it uses a GET request and everything works fine.
when myurl = URL2, however, it uses a POST request, and the response from the php page indicates that the post parameters sent with the request were empty. You can see the line where I set the POST params, so I don't understand why it's sending no params?!
Thanks for any help!
-Adam.
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
String response = "";
try {
URL urlObject = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();
// find out if there's a way to incorporate these timeouts into the progress bar
// and what they mean for shitty network situations
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setDoInput(true);
// INSERTED QUICK CHECK TO SEE WHICH URL WE ARE LOADING FROM
// it's important because one is GET, and one is POST
if (myurl.equals(url2)){
Log.i(TAG, "dlurl() in async recognizes we are doing pre-call");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
String postParams = "?phone=" + phone;
writer.write(postParams);
Log.i(TAG, "we're adding " + postParams + "to " + urlObject);
writer.flush();
writer.close();
os.close();
}
else {
conn.setRequestMethod("GET");
conn.connect();
}
// Starts the query
int responseCode = conn.getResponseCode();
Log.i(TAG, "from " + myurl + ", The response code from SERVER is: " + responseCode);
is = conn.getInputStream();
// Convert the InputStream into a string
// i guess we look up how to do this
if (responseCode == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
response += line;
}
} else {
response = "from downloadUrl, php page response was not OK: " + responseCode;
}
// it's good to close these things?
is.close();
conn.disconnect();
Log.i(TAG, "response is " + response);
return response;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
try with following code block to send parameters of the POST request.
Map<String,String> params = new LinkedHashMap<>();
params.put("phone", "phone");
StringBuilder postPraamString = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postPraamString.length() != 0) postPraamString.append('&');
postPraamString.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postPraamString.append('=');
postPraamString.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
writer.write(postDataBytes);
So I figured out the root of the problem...
In the line:
String postParams = "?phone=" + phone;
The problem was that leading question mark. The question mark should only be used in GET requests.
I'm trying to send email using the SES HTTPS Query API. I have a java method that sends a GET request to an Amazon SES endpoint, I'm trying to send an email with SES and capture the result.
Code:
public static String SendElasticEmail(String timeConv,String action,String source, String destinationAddr, String subject, String body) {
try {
System.out.println("date : "+timeConv);
System.out.println("In Sending Mail Method......!!!!!");
//Construct the data
String data = "Action=" + URLEncoder.encode(action, "UTF-8");
data += "&Source=" + URLEncoder.encode(source, "UTF-8");
data += "&Destination.ToAddresses.member.1=" + URLEncoder.encode(destinationAddr, "UTF-8");
data += "&Message.Subject.Data=" + URLEncoder.encode(subject, "UTF-8");
data += "&Message.Body.Text.Data=" + URLEncoder.encode(body, "UTF-8");
//Send data
System.out.println("https://email.us-east-1.amazonaws.com?"+data);
URL url = new URL("https://email.us-east-1.amazonaws.com?"+data);
//URLConnection conn = url.openConnection();
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("x-amz-date" , timeConv);
con.setRequestProperty("Content-Length", ""+data.toString().length());
con.setRequestProperty("X-Amzn-Authorization" , authHeader);
int responseCode = ((HttpsURLConnection) con).getResponseCode();
String responseMessage = ((HttpsURLConnection) con).getResponseMessage();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
//System.out.println("Response Message : " + responseMessage);
InputStream stream = con.getInputStream();
InputStreamReader isReader = new InputStreamReader(stream );
System.out.println("hgfhfhfhgfgfghfgh");
BufferedReader br = new BufferedReader(isReader);
String result = "";
String line;
while ((line = br.readLine()) != null) {
result+= line;
}
System.out.println(result);
br.close();
con.disconnect();
}
catch(Exception e) {
e.printStackTrace();
}
return subject;
}
I have calculated the signature correctly, because on hitting from postman client getting 200 response.
URL url = new URL("https://email.us-east-1.amazonaws.com?"+data);
You missed a '/' before the question mark. It should be
URL url = new URL("https://email.us-east-1.amazonaws.com/?"+data);
I have a cURL command I want to translate in Java
curl -H "Key: XXX" -d url=http://www.google.com http://myapi.com/v2/extraction?format=json
It works fine.
I started to do in Java: (CODE EDITED, it works)
try {
// POST
System.out.println("POSTING");
URL url = new URL("http://myapi.com/v2/extraction?format=json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Key", "XXX");
String data = "http://www.google.com";
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write("url=" +data);
writer.close();
int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + data);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println("REPOSNE" +response.toString());
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
But I don't know how to set my arguments.
Thanks for your help.
Jean
If you mean to set a header field Key with value XXX you can use the setRequestProperty
ie
conn.setRequestProperty("Key", "XXX");
If you want to send data, use
String data = "url=http://www.google.com";
conn.setRequestProperty("Content-Length", "" + Integer.toString(data.getBytes().length));
EDIT:-
For posting data as form url encoded, try the following code
String data = "url=" + URLEncoder.encode("http://www.google.com", "UTF-8");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
wr.write(data.getBytes());
In official documentation of Google Translate Api for Java it says that we can use post-method to send more than 2K characters. https://developers.google.com/translate/v2/using_rest
However when I try to translate text more than 2k length I get error 414 (Request-URI Too Large).
StringBuilder sb = new StringBuilder();
HttpURLConnection connection = null;
try {
URL url = new URL("https://www.googleapis.com/language/translate/v2");
String urlParameters = "key=" + apiKey + "&source=" + shortLang1 +
"&target=" + shortLang2 + "&q=" + URLEncoder.encode(lyrics, "UTF-8");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches (false);
connection.addRequestProperty("X-HTTP-Method-Override", "GET");
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
if (connection.getResponseCode() != 200) {
return null;
}
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
UPDATE: I got it, the code above is right. Finally I realize that I got this error not from Google Translate service but from my proxy on Google App Engine.
What the document you linked to is saying is that you use the POST method and you put the parameters into the request body ... not the request URL.
Reference:
How are parameters sent in an HTTP POST request?