Question

I've recently found out about Google's Cloud Messaging for Android and I wanted to integrate my app to use it. I got the Android side of the project working and the app is being correctly registered with the server. The problem is that my server can't seem to be able to authenticate the GCM servers so it can talk to them. Here's what I mean:

Currently, my server is a simple Java-based SSL server with a keystore and a truststore. The truststore contains the client's key (i.e. the app's key) and vice versa and the client/server can talk to each other over SSL without any problems. The code I am using to send a message to the app is this:

Sender sender = new Sender( "API_KEY" );
Message message = new Message.Builder().addData( "message", description ).build();
Result result = sender.send( message, ID, 1 );

It gives my the following exception:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

When I start my server I pass in the name of the trust/keystores and their passwords and load them, so that they can be used to talk to the client. I suspect that the problem is that currently the truststore only contains the client's key, so the server can ONLY talk to the client and no one else. Is this correct, and if it is, anyone have any ideas how to add the GCM certificate to the truststore or something?

Thanks a lot, any help is much appreciated :)

P.S. I tried to just send a message to the client before I load the truststore in the server and the app received it successfully.

Was it helpful?

Solution

With Google Cloud Messaging, your server doesn't talk directly to the client. It goes through the "Cloud" part first. Thus putting the client certificate in your server's trust manager doesn't work.

Instead, your server will have to validate the SSL certificate of Google's Cloud Messaging servers. Those are backed by Certificate Authorities already in your operating system's default CA list, so sending a message to the client before adding the trust store will work just fine.

OTHER TIPS

Figured it out. As kroot suggested, the problem was that the server was not able to authenticate the GCM servers since their certificates were not in its truststore (I was using my own trust store as oposed to the system's trust store). So I changed that by simply copying the cacerts file from the Java security folder, adding the custom client certificate for the Android app in there, and using that file as my trust store since it already has the system's default trust certificates. Was simple enough but took me like half a day to figure out.

The server's trustStore doesn't trust the client's certificate. Check what it contains, and that you really are using that trustStore.

I created a standalone java program which acted as 'server' and could push the message to GCM server which in turn could deliver message to my handset app.

I don't had to install any certificate in my jre\lib\security\cacerts file as the shipped trusted entries are sufficient to connect to GCM server.

The only dependencies are the following

    <dependency>
        <groupId>com.google</groupId>
        <artifactId>gcm-server</artifactId>
        <version>1.0.1</version>
    </dependency>
    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1.1</version>
    </dependency>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top