I have generated the access code by using https://login.mailchimp.com/oauth2/authorize API. But when I try to create the token using https://login.mailchimp.com/oauth2/token, I'm getting unicode result like this.
(?M?? ?0F?UJ?N?NQ? %`??'
"?????nb??f=?&9????i'f??]?~j*$??W??Reg??_T1-???;?oc)
qryStr = {"client_secret":"**********","grant_type":"authorization_code","redirect_uri":"https%3A%2F%2Flocalhost%3A9443%2Fverifymailchimp.sas","client_id":"********","code":"*************"}
HttpURLConnection connection = null;
try
{
URL reqURL = new URL("https://login.mailchimp.com/oauth2/token");
connection = (HttpURLConnection) reqURL.openConnection();
connection.setConnectTimeout(3000); // 3 seconds
connection.setReadTimeout(5000); // 5 seconds
connection.setUseCaches(false);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //No I18N
connection.setRequestProperty("Content-Length", "" + Integer.toString(qryStr.getBytes().length)); //No I18N
connection.setDoOutput(true);
OutputStream os = null;
try
{
os = connection.getOutputStream();
os.write(qryStr.getBytes(CHARSET));
}
finally
{
try{os.close();}catch(Exception e){}
}
int resCode = connection.getResponseCode();
boolean success = (resCode >= 200 && resCode < 300);
InputStream is = success ? connection.getInputStream() : connection.getErrorStream();
if (is == null)
{
return null;
}
String contentStr = null;
try
{
InputStreamReader reader = new InputStreamReader(is, CHARSET);
StringBuilder buffer = new StringBuilder();
char[] bytes = new char[1024];
int bytesRead;
while ((bytesRead = reader.read(bytes, 0, bytes.length)) > 0)
{
buffer.append(bytes, 0, bytesRead);
}
contentStr = buffer.toString();//?M?? ?0F?UJ?N?NQ? %`??' "?????nb??f=?&9????i'f??]?~j*$??W??Reg??_T1-???;?oc
}
finally
{
try{is.close();}catch(Exception e){}
}
}
Can anyone please tell the cause?
I found the cause of this case. An access code is valid for 30 seconds. Need to generate the token before the expiry. If they conveyed the proper error message, we can able to sort out the problem without any confusion :(
Related
I have been trying all day to get a minecraft plugin to allow players on bedrock edition on my geyser sever to (OPTIONALY) sign in to java edition using OAuth2's device code flow. I successfully can get a code and url but when I go to poll the API for a successful login I get "Cross-origin token redemption is permitted only for the 'Single-Page Application'." I've tried adding SPA to my azure app registration but the issue persists. I've tried setting the origin header in my request to "http://localhost" and the issue persist:
here is my code for retrieving the login token:
public static JSONObject pollSignIn(String deviceCode) {
double i = 0;
long previousTime = 0;
while (i <= 60000 /*GeyserFloodgateSkinFix.defaultConfig.requestTimeout*/) {
while (!(System.currentTimeMillis() > previousTime)) {}
previousTime = System.currentTimeMillis();
i++;
if ((i/1000) % 3 == 0) {
try {
URL url = new URL("https://login.microsoftonline.com/common/oauth2/v2.0/token");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Origin", null);
con.setDoOutput(true);
System.out.println(deviceCode);
String body = String.format(
"grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=%s&device_code=%s",
"[Censored]",
deviceCode
);
byte[] output = body.getBytes(StandardCharsets.UTF_8);
OutputStream os = con.getOutputStream();
os.write(output);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(br.readLine());
}
JSONObject json = new JSONObject(sb.toString());
if (json.getString("token_type").equalsIgnoreCase("Bearer")) {
return json;
}
}
catch (Exception ignored) {
System.out.println(ignored.getMessage());
}
}
}
return null;
}
if it helps heres the code I use to get the token (This works)
public static JSONObject getAuthCode() {
try {
URL url = new URL("https://login.microsoftonline.com/common/oauth2/v2.0/devicecode");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setDoOutput(true);
String body = String.format(
"scope=XboxLive.signin%%20offline_access&client_id=%s",
"[Censored]"
);
OutputStream os = con.getOutputStream();
byte[] output = body.getBytes(StandardCharsets.UTF_8);
os.write(output, 0, output.length);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
con.disconnect();
return new JSONObject(sb.toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
UPDATE: I managed to fix the above error but now I am getting "The provided value for the input parameter 'scope' is not valid. The scope 'XboxLive.signin offline_access' is not configured for this tenant." Chanfing the tenant to "consumer" throws "The provided value for the input parameter 'device_code' is not valid. Device codes supporting the personal Microsoft Account sign-in audience can only be used for v2 common or consumers tenants"
I brief description of what I'm doing, I'm automating creating incidents in ServiceNow using API. I have tested with POSTMAN first and it works fine.
Now after I wrote the code, I try to post data, I got no respond from the server. what could be the problem?
if (method.equals("POST") )
{
url+= "api/now/table/incident";
}
else if (method.equals("GET")|| method.equals("PUT"))
{
url+= "api/now/table/incident/" + incident.getSys_id();
}
URL request_url = new URL(url);
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
connection = (HttpsURLConnection) request_url.openConnection();
// ((HttpsURLConnection) connection).setSSLSocketFactory(sslsocketfactory);
if (method.equals("POST") || method.equals("PUT"))
{
connection.setRequestProperty("Content-Type", "application/json");
}
else
{
connection.setRequestProperty("Accept", "application/json");
}
connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // this was suggested as solution, but doesn't work.
connection.setRequestMethod(method);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Authorization", "Basic "+encoded);
if (method.equals("POST") || method.equals("PUT"))
{
JSONObject json = new JSONObject();
json.put("short_description",incident.getShort_description());
json.put("description", incident.getDescription());
json.put("assignment_group",incident.getAssignment_group());
json.put("priority",incident.getPriority());
json.put("impact",incident.getImpact());
OutputStream os = connection.getOutputStream();
os.write(json.toJSONString().getBytes(StandardCharsets.UTF_8));
os.close();
}
// read the respond
httpsCode = connection.getResponseCode();
if (httpsCode == HttpsURLConnection.HTTP_OK || httpsCode == 201)
{
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String lines = null;
StringBuilder stringBuilder = new StringBuilder();
while ((lines = bufferedReader.readLine()) != null)
{
stringBuilder.append(lines);
}
bufferedReader.close();
result = stringBuilder.toString();
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(result);
String incident_number = json.get("incident_number").toString();
String sys_id = json.get("sys_id").toString();
incident.setIncident_number(incident_number);
incident.setSys_id(sys_id);
return null;
}
the error is related to timeout, a posted solution suggested to set up the header to a browser type. but that's also didn't work.
I am using HttpURLConnection to upload an image and get its response.
It works on emulator and my XiaoMi device.
However, it always get a SocketTimeoutException on my Sony device on the line connection.getInputStream().
I've tried to set timeouts to large value like 1 minute but not work.
public String uploadFile(File file, String requestURL) {
if (file != null) {
long fileSize = file.length();
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection connection = null;
try {
//config of connection
connection = (HttpURLConnection) new URL(requestURL).openConnection();
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "image/jpeg");
connection.setDoOutput(true);
connection.setRequestProperty("Content-length", "" + fileSize);
connection.connect();
//upload file
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
int bytesRead;
byte buf[] = new byte[1024];
BufferedInputStream bufInput = new BufferedInputStream(new FileInputStream(file));
while ((bytesRead = bufInput.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
out.flush();
}
out.flush();
out.close();
//get response message, but SocketTimeoutException occurs here
BufferedReader br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
StringBuilder sb = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
sb.append(output);
}
//return response message
return output;
} catch (Exception e) {
// Exception
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
}
return null;
}
What causes this problem happen?And how to fix it?
Additional Info:
I tested on devices under same wifi connection. And sure network and file server worked properly. The file size of tested images is about 100~200kbyte.
Because you set a read timeout of ten seconds and no response was received within ten seconds.
Is this a trick question?
NB You don't need to set the content-length header. Java will do that for you.
Just remove connection.setReadTimeout() statement because by default it will set readTiomeout value to 0 i.e it will wait for data until data is available.so,you might not get SocketTimeOut Exception.
currently I can recognize speech to text using google's speech api. Now that I have this, I was just wondering if there is a way I can stream the response of transcribed text and give it more text to transcribe at the same time. In other words I want to speak into the microphone, and as I speak I want a response from the google servers. The code I am using currently:
System.out.println("openning connection");
HttpsURLConnection httpConn = null;
ByteBuffer buff = ByteBuffer.wrap(data);
byte[] destdata = new byte[2048];
int resCode = -1;
OutputStream out = null;
try {
URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpsURLConnection)) {
throw new IOException ("URL must be HTTPS");
}
httpConn = (HttpsURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("User-Agent", USER_AGENT);
httpConn.setDoOutput(true);
httpConn.setRequestProperty("AcceptEncoding", "gzip,deflate,sdch");
httpConn.setChunkedStreamingMode(0); //TransferType: chunked
httpConn.setRequestProperty("Content-Type", "audio/l16; rate=" + sampleRate);
// this opens a connection, then sends POST & headers.
out = httpConn.getOutputStream();
//beyond 15 sec duration just simply writing the file
// does not seem to work. So buffer it and delay to simulate
// bufferd microphone delivering stream of speech
// re: net.http.ChunkedOutputStream.java
while(buff.remaining() >= destdata.length){
buff.get(destdata);
out.write(destdata);
};
byte[] lastr = new byte[buff.remaining()];
buff.get(lastr, 0, lastr.length);
out.write(lastr);
out.close();
resCode = httpConn.getResponseCode();
if(resCode >= HttpURLConnection.HTTP_UNAUTHORIZED){//Stops here if Google doesn't like us/
System.out.println("unauthorized");
throw new HTTPException(HttpURLConnection.HTTP_UNAUTHORIZED);//Throws
}
String line;//Each line that is read back from Google.
BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
while ((line = br.readLine( )) != null) {
System.out.println(line);
if(line.length()>19 && resCode > 100 && resCode < HttpURLConnection.HTTP_UNAUTHORIZED){
GoogleResponse gr = new GoogleResponse();
parseResponse(line, gr);
fireResponseEvent(gr);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {httpConn.disconnect();}
Thanks for any help.
actually I need a little more information about how to read response from HttpUrlConnection class in Android SDK. I'm trying to read a response from web server,but when it's too big my applications is throwin an OutOfMemoryException. So any source/help/suggestions on how to read the whole response into pieces is welcomed.
As I made a research I found out that I should set something like this : ((HttpURLConnection) connection).setChunkedStreamingMode(1024); But my problem is that I don't know how to read this chuncked stream. So I'll be very happy if someone can guide me through the right way.
Thanks!
Sample Code :
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();
Log.w("device_identificator","device_identificator : "+deviceId);
String resolution = Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getWidth())+ "x" +
Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getHeight());
Log.w("device_resolution","device_resolution : "+resolution);
String version = "Android " + Build.VERSION.RELEASE;
Log.w("device_os_type","device_os_type : "+version);
Log.w("device_identification_string","device_identification_string : "+version);
String locale = getResources().getConfiguration().locale.toString();
Log.w("set_locale","set_locale : "+locale);
String clientApiVersion = null;
PackageManager pm = this.getPackageManager();
PackageInfo packageInfo;
packageInfo = pm.getPackageInfo(this.getPackageName(), 0);
clientApiVersion = packageInfo.versionName;
Log.w("client_api_ver","client_api_ver : "+clientApiVersion);
long timestamp = System.currentTimeMillis()/1000;
String timeStamp = Long.toString(timestamp);
String url = "http://www.rpc.shutdown.com";
String charset = "UTF-8";
String usernameHash = hashUser(username,password);
String passwordHash = hashPass(username,password);
String query = String.format("username_hash=%s&password_hash=%s&new_auth_data=%s&debug_data=%s&client_api_ver=%s&set_locale=%s×tamp=%s&"+
"device_os_type=%s&mobile_imei=%s&device_sync_type=%s&device_identification_string=%s&device_identificator=%s&device_resolution=%s",
URLEncoder.encode(usernameHash, charset),
URLEncoder.encode(passwordHash, charset),
URLEncoder.encode("1", charset),
URLEncoder.encode("1", charset),
URLEncoder.encode(clientApiVersion, charset),
URLEncoder.encode(locale, charset),
URLEncoder.encode(timeStamp, charset),
URLEncoder.encode(version, charset),
URLEncoder.encode(deviceId, charset),
URLEncoder.encode("14", charset),
URLEncoder.encode(version, charset),
URLEncoder.encode(deviceId, charset),
URLEncoder.encode(resolution, charset));
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
OutputStream output = null;
try {
output = connection.getOutputStream();
output.write(query.getBytes(charset));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
}
int status = ((HttpURLConnection) connection).getResponseCode();
Log.i("","Status : "+status);
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
Log.i("Headers","Headers : "+header.getKey() + "=" + header.getValue());
}
InputStream response = connection.getInputStream();
Log.i("","Response : "+response.toString());
int bytesRead = -1;
byte[] buffer = new byte[8*1024];
while ((bytesRead = response.read(buffer)) >= 0) {
String line = new String(buffer, "UTF-8");
Log.i("","line : "+line);
handleDataFromSync(buffer);
}
Simply allocate a byte buffer that can hold a small amount of data and read from the input stream into this buffer (using the read method). Something like:
InputStream is = connection.getInputStream();
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = is.read(buffer)) >= 0) {
// process the buffer, "bytesRead" have been read, no more, no less
}
To read the Response Header try to use :
String sHeaderValue = connection.getHeaderField("Your_Header_Key");