Strange behaviour in Get request - java

NOTE: This contains fixed code.
The following get request works:
curl https://9d3d9934609d1a7d79865231be1ecb23:9432fb76a34a0d46d64a2f4cf81bebd6#smartprice-2.myshopify.com/admin/orders.json
But the following code in java that I though did the same returns a 401.
final String url = "https://9d3d9934609d1a7d79865231be1ecb23:9432fb76a34a0d46d64a2f4cf81bebd6#smartprice-2.myshopify.com/admin/orders.json";
final HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Content-Type", "application/json");
final String encoded = Base64.encodeBase64String((api+":"+pass).getBytes());
con.setRequestProperty("Authorization", "Basic "+encoded);
System.out.println("\nSending 'GET' request to URL : " + url);
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
What am I missing here?
Are those not identical?

401 means unauthorized. Nothing surprising. The thing is that curl is able to resolve username:password used in your URL (part before '#' sign) and append it automatically as Authorization header in your request. But Java API is not doing this so you will have to do it on your own. The best way to investigate is to run curl with -v option. In it, you will see something like:
* Server auth using Basic with user '9d3d9934609d1a7d79865231be1ecb23'
> GET /admin/orders.json HTTP/1.1
> Host: smartprice-2.myshopify.com
> Authorization: Basic OWQzZDk5MzQ2MDlkMWE3ZDc5ODY1MjMxYmUxZWNiMjM6OTQzMmZiNzZhMzRhMGQ0NmQ2NGEyZjRjZjgxYmViZDY=
> User-Agent: curl/7.44.0
> Accept: */*
So you can notice that curl automatically appends HTTP Basic Authorization header to your request. So the correct Java code would be:
final String url = "https://smartprice-2.myshopify.com/admin/orders.json";
final HttpsURLConnection con = (HttpsURLConnection) new URL(url).openConnection();
con.setRequestProperty("Authorization", "Basic OWQzZDk5MzQ2MDlkMWE3ZDc5ODY1MjMxYmUxZWNiMjM6OTQzMmZiNzZhMzRhMGQ0NmQ2NGEyZjRjZjgxYmViZDY=");
con.setRequestMethod("GET");
System.out.println("Response Code : " + con.getResponseCode());
You can notice, that there is no reason to use credentials in URL and use only Authorization header (request property). By the way if you decode Base64: OWQzZDk5MzQ2MDlkMWE3ZDc5ODY1MjMxYmUxZWNiMjM6OTQzMmZiNzZhMzRhMGQ0NmQ2NGEyZjRjZjgxYmViZDY=, you will get exactly the part of URL before '#' which is: 9d3d9934609d1a7d79865231be1ecb23:9432fb76a34a0d46d64a2f4cf81bebd6
If you want automatic way how to resolve your Authorization header, you can use
final String credentials = DatatypeConverter.printBase64Binary("username:password".getBytes());
con.setRequestProperty("Authorization", "Basic " + credentials);

401 error stands for the Unauthorized access.
You need to either use Authenticator:
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("username", "password".toCharArray());
}
});
or set a property:
String basicAuth = "Basic " + new String(new Base64().encode(userpass.getBytes()));
con.setRequestProperty ("Authorization", basicAuth);

Related

Alternative of Basic Auth - Sonar Critical Vulnerability

I need to fetch the access token before making the actual call to the OAuth2-protected API.
As of now, I am doing it in the below fashion
String credential = clientId + ":" + clientSecret;
String encoding = Base64.getEncoder().encodeToString((credential).getBytes(‌"UTF‌​-8"​));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Basic " + encoding);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(postDataLength));
Sonar says this is Non-Compliant RSPEC-2647, therefore I want to know what are the alternatives I can use, and how to fix this issue?
--EDIT
In the body, I was passing grant_type, username, and password.
I tried adding client_id and client_secret as well and it works.
Now I have one more question, is passing these credentials in the body more secure?
String body = "grant_type="+grantType+"&username="+username+"&password="+password+"&client_id="+clientId+"&client_secret="+clientSecret;
byte[] postData = body.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
try(DataOutputStream wr = new DataOutputStream(conn.getOutputStream())) {
wr.write(postData);
}
conn.connect();

cURL + Java -- CPAS Request -- Suggestion Please

Explination
I am working on a Java App that sends a text message via a CPAS API (Similar to Tweepy). I am using CURL to request the message send. The request from Java seems to be sent but I am getting a 401 code. I'm assuming there is an issue with the encoding of my Authentication for the request. The code is as follows:
URL url = new URL("https://api.zang.io/v2/Accounts/ACe1889084d37de951ef064200aecbe4b2/SMS/Messages");
String auth = AUTH + ":" + TOKEN;
String encodeedAuth = Base64.getEncoder().withoutPadding().encodeToString(auth.getBytes());
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setRequestProperty("Authorization", "Basic " + encodeedAuth);
String data = "From=+14132698029&To=17817381451&Body=New Test";
byte[] out = data.getBytes(StandardCharsets.UTF_8);
OutputStream stream = http.getOutputStream();
stream.write(out);
System.out.println(http.getResponseCode() + " " + http.getResponseMessage());
http.disconnect();
"""
An HTTP 401 response is commonly an HTTP endpoint authorization failure. The best way to see why your auth credentials are failing is to capture the request/response pair in transit (at the receiving end would be optimal) and then compare that request/response pair to one that works.

curl response is different from the responce of java.net.URL

curl -v https://whatwg.org/html
header is:
HTTP/1.1 301 Moved Permanently
Location: https://html.spec.whatwg.org/multipage
however..
String link = "https://whatwg.org/html";
URL url = new URL(link);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
int status = conn.getResponseCode();
System.out.println("Response Code ... " + status);
Response Code ... 200
The first and second results are different, what I am doing wrong and how should I receive 301 ?

How to Pass Username and Password in GET Request in Java

Below is the Code Written by me.
But when i send the request i am getting Response Code 401 : Unathorized.
String url = "SAMPLE_URL";
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);
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
Add this code to your program after obj.openConnection();
String encoded = Base64.encode(username+":"+password);
con.setRequestProperty("Authorization", "Basic "+encoded);

HTTPS Login using Java

I've a problem to login to a website via https.
I wrote this code (it works) for http access:
String user = user;
String password = psw;
String authString = user + ":" + password;
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
URLConnection connection= url.openConnection();
connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.connect();
I'd like to do the same things but via https. Is it possible?
You can, please use HttpsURLConnection
Checkout sample program on http://www.mkyong.com/java/java-https-client-httpsurlconnection-example/
When specifying your URL, make sure to pass "https://..."
url.openConnection();
will return you an object that has the type of the established connection. It will always be URLConnection, but it can be a class that extends URLConnection as well. Such classes are HttpURLConnection and HttpsURLConnection (and others).
You should verify that the returned object is of type HttpsURLConnection. And if it's not, you should stop the connection (in case you want to avoid non secure connections).
if (connection instanceof HttpsURLConnection)

Categories

Resources