Skip to content

parse.initialize not working when using server url which is self signed ssl. #429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sekharrockz opened this issue Mar 31, 2016 · 11 comments

Comments

@sekharrockz
Copy link

eg:
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("LTApplicationID") // should correspond to APP_ID env variable
.clientKey(null) // set explicitly unless clientKey is explicitly configured on Parse server
.addNetworkInterceptor(new ParseLogInterceptor())
.server("https://xxx.xxx.xxx.xx:1337/parse/").build());

@parse-github-bot
Copy link

Thank you for your feedback. We prioritize issues that have clear and concise repro steps. Please see our Bug Reporting Guidelines about what information should be added to this issue.

Please try the latest SDK. Our release notes have details about what issues were fixed in each release.

In addition, you might find the following resources helpful:

@parse-github-bot
Copy link

This issue has not been updated for 7 days. If you have additional information to help pinpoint this issue as an SDK bug, please comment on this issue. We will close this issue in 7 days if no additional information is provided. Thank you for your feedback.

@bilthon
Copy link

bilthon commented Apr 11, 2016

I'm not sure this qualifies as a bug, it is rather a feature that I can't find. The problem is an exception generated by the fact that we're using a self-signed certificate on the server side. I get this for instance:

IOException. Msg: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found

And that of course makes sense, since the certificate validated by any publicly known CA. The Android documentation explains how to solve this issue here: http://developer.android.com/intl/es/training/articles/security-ssl.html#SelfSigned.

But I don't know if the parse SDK exposes any API to do the same.

@parse-github-bot
Copy link

This issue has not been updated for 7 days. If you have additional information to help pinpoint this issue as an SDK bug, please comment on this issue. We will close this issue in 7 days if no additional information is provided. Thank you for your feedback.

@sekharrockz
Copy link
Author

Even I get the same issue. Need somebody's help on fixing this issue

@sekharrockz
Copy link
Author

I want to assign trust keystore to the httpclient inside parse SDK

@sekharrockz
Copy link
Author

I am using Android client

@dromosys
Copy link

dromosys commented Jun 30, 2016

got it working via a NetworkInterceptor not very nice but better than a null security provider

Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId(".....")
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId(".....")
.addNetworkInterceptor(new ParseInterceptor())
.server("https://..../parse/")
.build());

public class ParseInterceptor implements ParseNetworkInterceptor {

public static final String TAG = "ParseInterceptor";

@Override
public ParseHttpResponse intercept(Chain chain) throws IOException {
    Log.d(TAG, "intercept");

    ParseHttpRequest request = chain.getRequest();
    //ParseHttpRequest.Builder builder = new ParseHttpRequest.Builder(request).addHeader(Config.HEADER_KEY, Config.HEADER_VALUE);
    //return chain.proceed(builder.build());

    //ParseHttpResponse response = chain.proceed(request);
    ParseURLConnectionClientCustom client = new ParseURLConnectionClientCustom(10000, null);
    ParseHttpResponse response = client.execute(request);
    //Log.d(TAG, "response:" + response);
    // Consume the response body
    ByteArrayOutputStream responseBodyByteStream = new ByteArrayOutputStream();
    int n;
    byte[] buffer = new byte[1024];
    while ((n = response.getContent().read(buffer, 0, buffer.length)) != -1) {
        responseBodyByteStream.write(buffer, 0, n);
    }
    final byte[] responseBodyBytes = responseBodyByteStream.toByteArray();
    Log.d(TAG, new String(responseBodyBytes));

    // Make a new response before return the response
    response = new ParseHttpResponse.Builder(response)
            .setContent(new ByteArrayInputStream(responseBodyBytes))
            .build();

    return response;
}

}
public class ParseURLConnectionClientCustom extends ParseURLConnectionHttpClient {

public static final String TAG = "ParseURLConnectionClientCustom";

int socketOperationTimeout;

private static final String ACCEPT_ENCODING_HEADER = "Accept-encoding";
private static final String GZIP_ENCODING = "gzip";
private static final String CONTENT_LENGTH_HEADER = "Content-Length";
private static final String CONTENT_TYPE_HEADER = "Content-Type";

public ParseURLConnectionClientCustom(int socketOperationTimeout, SSLSessionCache sslSessionCache) {
    super(socketOperationTimeout, sslSessionCache);
    this.socketOperationTimeout = socketOperationTimeout;
}



@Override

/* package */ HttpURLConnection getRequest(ParseHttpRequest parseRequest)
throws IOException {

    Log.d(TAG,"getRequest");
    HttpsURLConnection connection;
    URL url = new URL(parseRequest.getUrl());

    connection = (HttpsURLConnection)url.openConnection();
    connection.setSSLSocketFactory(HttpsTrustManager.getCA());

    connection.setRequestMethod(parseRequest.getMethod().toString());

    connection.setConnectTimeout(socketOperationTimeout);
    connection.setReadTimeout(socketOperationTimeout);
    connection.setDoInput(true);

    // Don't handle redirects. We copy the setting from AndroidHttpClient.
    // For detail, check https://quip.com/Px8jAxnaun2r
    connection.setInstanceFollowRedirects(false);

    // Set header
    for (Map.Entry<String, String> entry : parseRequest.getAllHeaders().entrySet()) {
        connection.setRequestProperty(entry.getKey(), entry.getValue());
    }

    // When URLConnection is powered by OkHttp, by adding this head, OkHttp will turn off its
    // transparent decompress which will expose the raw network stream to our interceptors.
    if (disableHttpLibraryAutoDecompress()) {
        connection.setRequestProperty(ACCEPT_ENCODING_HEADER, GZIP_ENCODING);
    }
    // Set body
    ParseHttpBody body = parseRequest.getBody();
    if (body != null) {
        // Content type and content length
        connection.setRequestProperty(CONTENT_LENGTH_HEADER, String.valueOf(body.getContentLength()));
        connection.setRequestProperty(CONTENT_TYPE_HEADER, body.getContentType());
        // We need to set this in order to make URLConnection not buffer our request body so that our
        // upload progress callback works.
        connection.setFixedLengthStreamingMode(body.getContentLength());
        connection.setDoOutput(true);
    }

    Log.d(TAG,"connection");

    return connection;
}

}

public static SSLSocketFactory getCA() {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
SSLSocketFactory response = null;
CertificateFactory cf = null;
InputStream caInput = null;
try {
cf = CertificateFactory.getInstance("X.509");

// From https://www.washington.edu/itconnect/security/ca/load-der.crt

    Certificate ca;
        InputStream is = ApplicationContext.getAppContext().getResources().getAssets().open("CA.crt");
        caInput = new BufferedInputStream(is);
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

     response=  context.getSocketFactory();

    } catch (Exception e) {
        Log.e("HttpsTrustManager",e);
    } finally {
        try {
            if(caInput != null) {
                caInput.close();
            }
        } catch (IOException e) {}
    }

    return response;
}

@jeandealmeida-dev
Copy link

Same here!

@rogerhu rogerhu added state:duplicate Duplicate of already reported issue and removed state:duplicate Duplicate of already reported issue labels Mar 9, 2017
@CharlesAE
Copy link

@sekharrockz did you ever get this issue resolved? do you mind sharing your solution?
@androidrobotfactory im currently stuck on this issue, do you mind clarifying your solution(your network interceptor code)? perhaps a gist?

@Jawnnypoo
Copy link
Member

This can be closed since this can be accomplished now by providing a custom clientBuilder when initializing Parse.

@rogerhu rogerhu closed this as completed Apr 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants