I am trying to get content from the website Socialcast which needs authentication. (First I do a HTTP Post with Basic Authentication and then I try a HTTP GET).
I tried several codes, I receive this as "result":
emily#socialcast.com:demo
Base64 encoded auth string: ZW1pbHlAc29jaWFsY2FzdC5jb206ZGVtbw==
* BEGIN
You are being redirected.
END *
Here is the code for HTTP Basic Auth:
try {
String webPage = "http://demo.socialcast.com";
String name = "emily#socialcast.com";
String password = "demo";
String authString = name + ":" + password;
System.out.println("auth string: " + authString);
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
System.out.println("Base64 encoded auth string: " + authStringEnc);
URL url = new URL(webPage);
URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("Authorization", "Basic " + authStringEnc);
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
StringBuffer sb = new StringBuffer();
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
String result = sb.toString();
System.out.println("*** BEGIN ***");
System.out.println(result);
System.out.println("*** END ***");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
However, when I try to do a GET afterwards, it says unauthorized.
The credentials are emily#socialcast.com/demo - those are provided by Socialcast Dev at the moment, as I also cannot access my own Socialcast instance.
Is this code wrong? How can I do it properly? BTW, I am using HttpClient 4.x.
Are you sending the credentials in each request? I think this is needed, otherwise the server does not have any other information to prove that you still are authorized to view other pages...
I'm not sure why this question is tagged with apache-httpclient-4.x when your example code doesn't use it. In fact, if you do use httpclient then you can get it to handle authentication for you quite easily, see here for the excellent tutorial.
Related
I was trying to integrate SnapChat login kit to my web application. I was able to get the authorization code from the SnapChat, but I am having trouble getting the access token.
I have done FB, Google, Instagram login integration perfectly fine, but this one I am totally lost.
I have tried to encode the parameters, change the order of headers, but all the time it gives me 400 bad request.
try {
URL url = null;
if(service.equals(APIConstants.GOOGLE))
url = new URL(SNSIdentifications.GOOGLE_TOKEN_REQUEST_URL);
else if (service.equals(APIConstants.FACEBOOK))
url = new URL(SNSIdentifications.FACEBOOK_TOKEN_REQUEST_URL);
else if (service.equals(APIConstants.INSTAGRAM))
url = new URL(SNSIdentifications.INSTAGRAM_TOKEN_REQUEST_URL);
else
url = new URL(SNSIdentifications.SNAPCHAT_TOKEN_REQUEST_URL);
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
if(service.equals(APIConstants.SNAPCHAT)) {
// String userCredentials = URLEncoder.encode(client_id + ":" + secret, "UTF-8");
String userCredentials = client_id + ":" + secret;
byte[] data = Base64.getEncoder().encode(userCredentials.getBytes());
String authorizationHeaderBase64 = new String(data);
conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
conn.setRequestProperty( "Authorization", "Basic " + authorizationHeaderBase64);
// conn.setRequestProperty("charset", "utf-8");
//Integer.toString(payload.getBytes(StandardCharsets.UTF_8).length)
// conn.setRequestProperty( "Content-Length", Integer.toString(payload.getBytes(StandardCharsets.UTF_8).length) );
writer = new OutputStreamWriter(conn.getOutputStream());
// writer.write(URLEncoder.encode(payload, "UTF-8"));
writer.write(params);
writer.flush();
System.out.println(conn.getResponseCode() + " " + conn.getResponseMessage() + " ");
} else {
writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(params);
writer.flush();
}
int responseCode = conn.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK) {
return new JSONObject(fetchResponse(conn));
}
} catch (IOException e) {
e.printStackTrace();
}
I should expect access token, refresh token, and expires_in values from the code above, but unfortunately it cannot, because of 400 bad request error.
I solved the problem. It turned out it was several combinations of problems.
When you are having an issue as I posted, please do check the followings:
Make sure you are using correct Client Id and Secret.
If you are adding Code Challenge and code challenge method parameters, you need to have code verifier to get access token. If you don't have these parameters, you don't need to worry about getting an access token.
When setting a header "Authorization" use base64 encode, not base16. (Snapchat page says base16, but in an example, it's in 64).
Check your urls, id, secret once again with those to get the authorization code.
:)
I am trying to access the Drive Api from a JavaFX Desktop app. After I received the initial authentication (aka code), I want to get the token to be able to work with the api. The config is set up as a native application in the dev console.
When I attempt to fetch the token I get various http-errors (400, 401, 404, 405, 406, 411). I guess something is wrong with the encoding and/or the way I send the request to the server.
Here the code:
public void sendOAuth2TokenRequest(String initialOAuth2) {
final String charset = "UTF-8";
try {
String url = "https://www.googleapis.com/oauth2/v3/token";
HttpsURLConnection con = (HttpsURLConnection) new URL(url).openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Accept-Charset", charset);
con.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
OutputStream output = con.getOutputStream();
output.write(getEncodedUrlParms().getBytes(charset));
output.close();
BufferedReader responseReader =
new BufferedReader(new InputStreamReader(con.getInputStream(), charset));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = responseReader.readLine()) != null) {
response.append(inputLine);
}
Log.i(TAG, "OAuth2Request " + inputLine);
responseReader.close();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "OAuth2Request Error: " + e.getMessage());
}
}
private String getEncodedUrlParms() throws UnsupportedEncodingException {
return "code=" + URLEncoder.encode(getInitialCode(), "UTF-8") +
"&client_id=" + URLEncoder.encode(DriveHelper.CLIENT_ID, "UTF-8") +
"&client_secret=" + URLEncoder.encode(DriveHelper.CLIENT_SECRET, "UTF-8") +
"&redirect_uri=" + URLEncoder.encode("urn:ietf:wg:oauth:2.0:oob", "UTF-8") +
"&grant_type=" + URLEncoder.encode("authorization_code", "UTF-8");
}
Please let me know what the mean here:
The client secret you obtained from the Developers Console (optional for clients registered as Android, iOS or Chrome applications).
Is the client_secret needed (mandatory) in native apps?
i must send one text string using java to a IP web cam, before it take picture. So after I read the camera user manual and searched in google, the only thing i found was using cURL. I install it and its run fine, and everything is okay, the text from the file appear in the video streaming. The command is this
curl -T test.xml http://admin:pass#192.168.0.1/Video/inputs/channels/2/overlays/text/2
and the content of test.xml is:
<TextOverlay xmlns="http://www.hikvision.com/ver10/XMLSchema" version="1.0">
<id>2</id>
<enabled>true</enabled>
<posX>5</posX>
<posY>5</posY>
<message>Text here </message>
</TextOverlay>
So I want to send this content using Java, I already tried using post and java.net but I get an error "Server returned HTTP response code: 403 for URL"
Here is my code:
System.out.println("Starting......");
URL url = new URL("http://192.168.0.1/Video/inputs/channels/2/overlays/text/2/");
String data = "<TextOverlay xmlns=\"http://www.hikvision.com/ver10/XMLSchema\" version=\"1.0\">\n"
+ "<id>2</id>\n"
+ "<enabled>true</enabled>\n"
+ "<posX>5</posX>\n"
+ "<posY>5</posY>\n"
+ "<message>Text here</message>\n"
+ "</TextOverlay>";
HttpURLConnection httpConnection = prepareConn(url, null, "admin", "pass");
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setRequestMethod("POST");
httpConnection.setRequestProperty ( "Content-Type", "text/xml" );
OutputStreamWriter out = new OutputStreamWriter(httpConnection.getOutputStream());
out.write(data);
out.flush();
out.close();
System.out.println("Printing......");
System.out.println(httpConnection.getResponseCode());
System.out.println(httpConnection.getResponseMessage());
InputStreamReader reader = new InputStreamReader(httpConnection.getInputStream());
StringBuilder buf = new StringBuilder();
char[] cbuf = new char[2048];
int num;
while(-1 != (num = reader.read(cbuf)))
{
buf.append(cbuf, 0, num);
}
String result = buf.toString();
System.out.println("\nResponse received from server after POST" + result);
}
static private HttpURLConnection prepareConn(final URL url, Properties request_props, String username, String password) throws Error, IOException
{
System.out.println("Authorization......");
if (!url.getProtocol().equalsIgnoreCase("http"))
throw new Error(url.toString() + " is not HTTP!");
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(300);
conn.setRequestMethod("POST");
final Properties DEFAULT_REQUEST_PROPS = new Properties();
DEFAULT_REQUEST_PROPS.setProperty("charset", "utf-8");
final Properties props = new Properties(DEFAULT_REQUEST_PROPS);
if (request_props != null)
for (final String name : request_props.stringPropertyNames())
props.setProperty(name, request_props.getProperty(name));
for (final String name : props.stringPropertyNames())
conn.setRequestProperty(name, props.getProperty(name));
if(null != username && null != password)
conn.setRequestProperty("Authorization", "Basic " + new BASE64Encoder().encode((username+":"+password).getBytes()));
return conn;
}
Hope someone can help :)
All the best !
I just use wrong RequestMethod, after deep research I found that i must use PUT not POST request. Now just change setRequestMethod("POST") to setRequestMethod("PUT") and works like a charm.
I am trying to read https://d3ca01230439ce08d4aab0c61810af23:bla#mycon.mycompany.com/recordings.atom
using Rome but its giving me error
INFO: Illegal access: this web application instance has been stopped already. Could not load org.bouncycastle.jcajce.provider.symmetric.AES$ECB. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
and
Server returned HTTP response code: 401 for URL: https://d3ca01230439ce08d4aab0c61810af23:bla#mycon.mycompany.com/recordings.atom .
I am doing this
URL url = new URL("https://d3ca01230439ce08d4aab0c61810af23:bla#mycon.mycompany.com/recordings.atom ");
try {
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(url));
System.out.println("Feed Author:"+feed.getAuthor());
for(Object entries: feed.getEntries()){
SyndEntry entry = (SyndEntry) entries;
System.out.println("title :"+entry.getTitle());
System.out.println("description : "+entry.getDescription());
}
} catch (IllegalArgumentException | FeedException | IOException e) {
e.printStackTrace();
}
Do I need to put the username password somewhere?
update
This I have done
URL url = new URL("https://d3ca01230439ce08d4aab0c61810af23:bla#mycon.mycompany.com/recordings.atom");
HttpURLConnection httpcon = (HttpURLConnection)url.openConnection();
String encoding = new sun.misc.BASE64Encoder().encode("username:pass".getBytes());
httpcon.setRequestProperty ("Authorization", "Basic " + encoding);
When I hit that URL from my browser it asks for basic authentication. You can do this with ROME:
URL feedUrl = new URL(feed)
HttpURLConnection httpcon = (HttpURLConnection)feedUrl.openConnection();
String encoding = new sun.misc.BASE64Encoder().encode("username:password".getBytes());
httpcon.setRequestProperty ("Authorization", "Basic " + encoding);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(httpcon));
You probably shouldn't use sun.misc.BASE64Encoder. Rather find another one somewhere.
From: http://cephas.net/blog/2005/02/09/retrieving-an-rss-feed-protected-by-basic-authentication-using-rome/
I find this a bit more elastic when it comes to authentication, this code works with and without authentication:
URL feedUrl = new URL("http://the.url.to/the/feed");
//URL feedUrl = new URL("http://user:pass#the.url.to/the/feed");
HttpURLConnection connection = (HttpURLConnection) feedUrl.openConnection();
if (feedUrl.getUserInfo() != null) {
String encoding = new sun.misc.BASE64Encoder().encode(feedUrl.getUserInfo().getBytes());
connection.setRequestProperty("Authorization", "Basic " + encoding);
}
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(connection));
You could also use the following in place of
String encoding = new sun.misc.BASE64Encoder().encode("username:password".getBytes());
to this:
String BASIC_AUTH = "Basic " + Base64.encodeToString("username:password".getBytes(), Base64.NO_WRAP);
What is the best way to use preemptive basic http authentication using HttpUrlConnection. (Assume for now I can't use HttpClient).
EDIT for clarification: I'm setting the un/pw correctly in the request header using Base64 encoding. Are there any additional flags or properties that need to be set, or is the fact that I'm setting the basic auth headers for the request all that is needed for preemptive basic auth?
If you are using Java 8 or later, java.util.Base64 is usable:
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
String encoded = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8)); //Java 8
connection.setRequestProperty("Authorization", "Basic "+encoded);
Then use the connection as normal.
If you're using Java 7 or lower, you'll need a method to encode a String to Base64, such as:
byte[] message = (username+":"+password).getBytes("UTF-8");
String encoded = javax.xml.bind.DatatypeConverter.printBase64Binary(message);
Yes, that's all you have to do in order to use Basic Auth. The code above to set the Request Property should be done immediately after opening the connection and before getting the Input or Output streams.
Incidentally, in case someone else runs into the same, the android problem, is also present if you use org.apache.commons.codec.binary.Base64 and do Base64.encodeBase64String(). You need to do Base64.encodeBase64() and get a byte[] then construct the string.
It caught me offguard entirely that the results would be different for the line ending between those two methods.
You can use java.net.Authenticator to configure basic auth. globally for every request send by your application, see :
http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html
http://developer.android.com/reference/java/net/Authenticator.html#getPasswordAuthentication()
you need to do this just copy paste it be happy
HttpURLConnection urlConnection;
String url;
// String data = json;
String result = null;
try {
String username ="danish.hussain#gmail.com";
String password = "12345678";
String auth =new String(username + ":" + password);
byte[] data1 = auth.getBytes(UTF_8);
String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
//Connect
urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "Basic "+base64);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
JSONObject obj = new JSONObject();
obj.put("MobileNumber", "+97333746934");
obj.put("EmailAddress", "danish.hussain#dhl.com");
obj.put("FirstName", "Danish");
obj.put("LastName", "Hussain");
obj.put("Country", "BH");
obj.put("Language", "EN");
String data = obj.toString();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(data);
writer.close();
outputStream.close();
int responseCode=urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
}else {
// return new String("false : "+responseCode);
new String("false : "+responseCode);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
I was having this problem too.
And Now I have solved this problem.
My code is :
URL url = new URL(stringUrl);
String authStr = "MyAPIKey"+":"+"Password";
System.out.println("Original String is " + authStr);
// encode data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(authStr .getBytes());
String authEncoded = new String(bytesEncoded);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Basic "+authEncoded);
It may help many others.
Best of luck.
Regarding the Base64 encoding problem, I found this library: http://sourceforge.net/projects/migbase64/
I have not fully vetted it but I am using it for the Basic Authentication solution shown above (as well as for image encoding/decoding), and it works well. It provides a parameter for whether or not to include the newline.