I'm facing problem with Google push notifications (for drive). I use service account which works perfectly for all other drive operations except drive changes watch.
Below is application code which now fails with "Unauthorized WebHook callback channel" exception. I also dumped requests and responses which are generated when drive.changes.watch.execute is called.
Target notification address is whitelisted in APIs & auth Push control panel (I even listed it in Javascript origins and referrers) and now I'm stuck with this 401 Unauthorized error.
Does someone know where I'm making mistake? Thanks for any help.
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), p12File, "notasecret", "privatekey", "notasecret");
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport t = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential gc = new GoogleCredential.Builder()
.setTransport(t)
.setJsonFactory(jsonFactory)
.setServiceAccountScopes(Collections.singleton(DriveScopes.DRIVE))
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.setServiceAccountId(Config.SERVICE_ACCOUNT_ID)
.setServiceAccountUser(Config.SERVICE_ACCOUNT_USER)
.build();
drive = new Drive.Builder(t, jsonFactory, null).setHttpRequestInitializer(gc).setApplicationName(cfg.getStringParam(Config.GAE_APPLICATION_NAME)).build();
// THIS WORKS
Changes.List request = drive.changes().list();
ChangeList changes = request.execute();
// THIS DOES NOT WORK
Channel channel = new Channel();
channel.setId(UUID.randomUUID().toString());
channel.setType("web_hook");
channel.setAddress(Config.PUSH_NOTIFICATION_ADDRESS);
Channel c = drive.changes().watch(channel).execute();
-------------- REQUEST --------------
POST https://www.googleapis.com/drive/v2/changes/watch
Accept-Encoding: gzip
Authorization: Bearer XXX
User-Agent: XXX Google-HTTP-Java-Client/1.17.0-rc (gzip)
Content-Type: application/json; charset=UTF-8
Content-Length: 118
CONFIG: curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'Authorization: Bearer XXX' -H 'User-Agent: XXX Google-HTTP-Java-Client/1.17.0-rc (gzip)' -H 'Content-Type: application/json; charset=UTF-8' -d '@-' -- 'https://www.googleapis.com/drive/v2/changes/watch' << $$$
CONFIG: {"address":"XXX","id":"8078114c-fba0-44e7-a34c-cb391ea40061","type":"web_hook"}
-------------- RESPONSE --------------
401 OK
www-authenticate: Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token
-------------- REQUEST --------------
POST https://accounts.google.com/o/oauth2/token
-------------- RESPONSE --------------
200 OK
{
"access_token" : XXX,
"token_type" : "Bearer",
"expires_in" : 3600
}
-------------- REQUEST --------------
POST https://www.googleapis.com/drive/v2/changes/watch
-------------- RESPONSE --------------
401 OK
www-authenticate: Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token
...
...
...
-------------- RESPONSE --------------
200 OK
content-type: application/json; charset=utf-8
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: Fri, 01 Jan 1990 00:00:00 GMT
date: Wed, 28 May 2014 20:51:19 GMT
content-disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
content-encoding: gzip
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
server: GSE
alternate-protocol: 443:quic
transfer-encoding: chunked
{
"access_token" : XXX,
"token_type" : "Bearer",
"expires_in" : 3600
}
{
"error": {
"errors": [
{
"domain": "global",
"reason": "push.webhookUrlUnauthorized",
"message": "Unauthorized WebHook callback channel: XXX"
}
],
"code": 401,
"message": "Unauthorized WebHook callback channel: XXX"
}
}
You have to add your domain to the developers console.
How to:
After that it should work unless there's something else wrong with what you're doing :p