Suddenly getting “java.security.cert.CertPathValidatorException: Trust anchor for certification path not found” when I hadn't before - java

I am attempting to get a token from a JSON endpoint using the following code:
public class FetchToken extends AsyncTask<String, Void, Void> {
String data = "";
String token = "";
public TokenDelegate delegate = null;
#Override
protected Void doInBackground(String... identity) {
try {
if (identity.length == 1) {
URL url = new URL(identity[0]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while (line != null) {
line = bufferedReader.readLine();
data = data + line;
}
JSONObject JO = new JSONObject(data);
token = JO.get("token").toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
When I run the code, I am getting the following error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. Using the same code previously, I was able to query a different JSON endpoint. Now that I have switched to this new server, I am only getting this error.
I have looked at another implementation by a previous developer at my company, querying the same server. There is no reference in their code to any certificates being loaded, any trust managers, or anything of the sort. In their (separate) Android application, they have a .crt file that is inside the assets folder but it does not appear to be included in the app anywhere.
Is there a way to install the certificate with my application? If not, is there anything clear that I am doing incorrectly? I have attempted to look through other references to the same error but they do not address how one would be able to query this endpoint without using a CertificateFactory or something similar.

Related

Unable to call API function and retrieving CSRF token from android studio

I am trying to access an API set up by my friend using visual studio, where i was given an error that says "Trust anchor for certification path not found.". I understand that this error arises when android not being able to verify the certificates and have tried using methods given here and here. However i am still unable to establish a successful connection. The code below is my attempt to call the API and try to get the CSRF token, so that i will be able to use the token to get other data. Any suggestion or help will be much appreciated.
URL iurl = new URL("https://10.0.2.2:44332/api/tanks/");
HttpsURLConnection iconn = (HttpsURLConnection) iurl.openConnection();
iconn.setRequestProperty("Accept", "application/json");
if (iconn.getResponseCode() == 200){
Log.i("Status code ",String.valueOf(iconn.getResponseCode()));
InputStream responseBody = iconn.getInputStream();
InputStreamReader responseBodyReader = new
InputStreamReader(responseBody, "UTF-8");
JsonReader jsonReader = new JsonReader(responseBodyReader);
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String key = jsonReader.nextName();
if (key.equals("__RequestVerificationToken")) {
// Fetch the value as a String
value = jsonReader.nextString();
break;
} else {
jsonReader.skipValue();
}
}
}
Error : Trust anchor for certification path not found.

Google Access token server side validation for android app

I'm developing android application, that is based on communication with server, and I want to use Google(g+) authentication mechanisms.
Basically, I think it should work like this:
In my android app, user logs in to Google, using his email and password.
User allows access to his data for related Google application.
My android app receives access token, after successful log in.
In further communication with my server, my android application should using received Google access token (for example: in queries).
When my server receives some query from android app, with access token, it should ask Google that this token is valid (and for who), and if yes, server should assume that user is authenticated with Google.
My question is: how the server should ask Google if given access token is valid? I think I should somehow check if the token is valid for my android app.
I've tried many Google queries to Google API, that I've found, but nothing worked as I expected. Can you provide me some example?
You can validate if the access_token is valid or not.
You need to send GET request to the api end point : https://www.googleapis.com/oauth2/v1/tokeninfo with your access_token in request.
You can try it like this:
String connection = new ConnectionService().connectionGoogle("https://www.googleapis.com/oauth2/v1/tokeninfo", "access_token=" + "YOUR_EXISTING_ACCESS_TOKEN");
System.out.println(connection);
The methods used in above code are:
public static String connectionGoogle(String url, String parameter) throws MalformedURLException, ProtocolException, IOException {
URL url1 = new URL(url);
HttpURLConnection request1 = (HttpURLConnection) url1.openConnection();
request1.setRequestMethod("GET");
request1.setDoOutput(true);
request1.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter wr = new OutputStreamWriter(request1.getOutputStream());
wr.write(parameter);
wr.flush();
request1.connect();
String responseBody = convertStreamToString(request1.getInputStream());
wr.close();
return responseBody;
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
} catch (IOException e) {
} finally {
try {
is.close();
} catch (IOException e) {
}
}
return sb.toString();
}
You can use the tokeninfo endpoint to check a token (access or ID token). If you just want to play with the API, you can use the TokenInfo API from the API Explorer.
You can use the Google-provided library for OAuth v2 to perform the API calls.
You can also form the URL and perform a GET query as described in the OAuth v2 Playground documentation.

JAVA send/receive information via json

I've been researching on how to send and receive information to a url, via json for the last 3 days. I have found a lot of documentation and code examples on how to do it, I just can't comprehend what they're saying. I've imported god knows how many .jar files into my eclipse package. Does anyone have a good example on how to connect to a url, send/receive information (even login), parse it, and send more information? I understand that I'm asking for a lot. I don't need all the answers, good documentation and some good examples would make me soooo happy.
Start with http://hc.apache.org/
Then look at http://code.google.com/p/google-gson/
or: http://wiki.fasterxml.com/JacksonHome
That should be all you need.
Found a really solid example here on this blog http://www.gnovus.com/blog/programming/making-http-post-request-json-using-apaches-httpclient
Pasted below if for some reason the link doesnt work.
public class SimpleHTTPPOSTRequester {
private String apiusername;
private String apipassword;
private String apiURL;
public SimpleHTTPPOSTRequester(String apiusername, String apipassword, String apiURL) {
this.apiURL = apiURL;
this.apiusername = apiusername;
this.apipassword = apipassword;
}
public void makeHTTPPOSTRequest() {
try {
HttpClient c = new DefaultHttpClient();
HttpPost p = new HttpPost(this.apiURL);
p.setEntity(new StringEntity("{\"username\":\"" + this.apiusername + "\",\"password\":\"" + this.apipassword + "\"}",
ContentType.create("application/json")));
HttpResponse r = c.execute(p);
BufferedReader rd = new BufferedReader(new InputStreamReader(r.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
//Parse our JSON response
JSONParser j = new JSONParser();
JSONObject o = (JSONObject)j.parse(line);
Map response = (Map)o.get("response");
System.out.println(response.get("somevalue"));
}
}
catch(ParseException e) {
System.out.println(e);
}
catch(IOException e) {
System.out.println(e);
}
}
}

Java code (URLConnection - remote get method) in HTML (Blogger.com post)

In Blogger post I have this snippet
<applet codebase="https://droidsnip.googlecode.com/hg/" height="300" archive="text.jar" width="300" code="Google.class">
and have this java code stored at google code:
public class Google extends java.applet.Applet {
public static void main() {
}
public void paint(Graphics g) {
String result = sendGetRequest(
"http://www.google.com", null);
g.drawString(result, 30, 30);
}
public static String sendGetRequest(String url,
String requestParameters) {
String result = null;
if (url.startsWith("http://")) {
try {
URL url1 = new URL(url);
URLConnection conn = url1.openConnection();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
result = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
And i do not get any result in post, but I get a normal html response using Eclipse.
What can be a problem with Blogger?
Btw, if I just use
g.drawString("test", 30, 30);
I get a string on the post, so it works
Unsigned Java applets are restricted in what they can do to prevent malicious use. If your applet isn't signed, then it can only connect to the server on which it is hosted (i.e. droidssnip.google.com in this case).
Here's a reference on how to sign an applet. Note that if you use a self-signed certificate (one you generate yourself with keytool), then you'll be prompted with a security warning when the applet runs. To avoid this, you'll need a certificate from a trusted Certificate Authority.
I guess you hit a security restriction so called "same origin policy": an applet can only talk to the server it was downloaded from. See details here: http://download.oracle.com/javase/tutorial/deployment/applet/security.html
Update: Besides signed applets the other workaround might be to implement a "proxy" servlet. In this case the sevlet polls google (ie. implements the sendGetRequest method) and talks to your applet (ie. the applet reads your servlet which in turn reads google).

Downloading a web page. OK with wget, fails with java

I'm trying to download the following page: http://structureddata.wikispaces.com/Test
wget without any option fails:
wget "http://structureddata.wikispaces.com/Test"
(...) connect to session.wikispaces.com insecurely, use `--no-check-certificate'
with --no-check-certificate, it works
wget --no-check-certificate "http://structureddata.wikispaces.com/Test"
grep Hello Test
Hello World
Now, i would like to download the same URL with java, but the following simple program:
import java.net.*;
import java.io.*;
public class Test
{
public static void main(String args[])
{
int c;
try
{
InputStream in=new URL("http://structureddata.wikispaces.com/Test").openStream();
while((c=in.read())!=-1) System.out.print((char)c);
in.close();
}
catch(Throwable err)
{
err.printStackTrace();
}
}
}
returns nothing
what should I do to download the page with java ?
Many thanks,
Ppierre
The Java URL interface is fairly low-level; it does not automatically do things like follow redirects. Your code above is getting no content to print out because there is none.
By doing something like the below, you'll see that what you are getting is an HTTP 302 response -- a redirect.
URL url = new URL("http://structureddata.wikispaces.com/Test");
URLConnection urlConnection = url.openConnection();
Map<String, List<String>> headers = urlConnection.getHeaderFields();
Set<Map.Entry<String, List<String>>> entrySet = headers.entrySet();
for (Map.Entry<String, List<String>> entry : entrySet) {
String headerName = entry.getKey();
System.out.println("Header Name:" + headerName);
List<String> headerValues = entry.getValue();
for (String value : headerValues) {
System.out.print("Header value:" + value);
}
System.out.println();
System.out.println();
}
I'd suggest using a library like HTTPClient which will handle more of the protocol for you.
(credit where it is due: Copied the above code from here.)
You may want to look at commons-httpclient, this code returns the page no problem
final HttpClient client = new HttpClient();
final GetMethod method = new GetMethod("http://structureddata.wikispaces.com/Test");
try {
if (HttpStatus.SC_OK == client.executeMethod(method)) {
System.out.println(IOUtils.toString(method.getResponseBodyAsStream()));
} else {
throw new IOException("Unable to load page, error " + method.getStatusLine());
}
} finally {
method.releaseConnection();
}
The problem is that it returns a 302 redirect response to a https url. Since the initial request is http and the target is https, the URLConnection won't automatically follow the redirect (it will however do when the target is using the same scheme).
After some observation I concluded that it goes to https to request some authentication token which in turn get redirected to a http url again with the authentication token as request parameter. So, it should be following redirects from http to https and then http with the actual page content.
The following works here.
public static void main(String... args) throws Exception {
// First request.
URLConnection connection = new URL("http://structureddata.wikispaces.com/Test").openConnection();
// Go to the redirected https page to obtain authentication token.
connection = new URL(connection.getHeaderField("location")).openConnection();
// Re-request the http page with the authentication token.
connection = new URL(connection.getHeaderField("location")).openConnection();
// Show page.
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
for (String line; ((line = reader.readLine()) != null);) {
System.out.println(line);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException ignore) {}
}
}
I however do agree that Commons HttpComponents Client is a better tool for the job.

Resources