Google push notifications - Unauthorized WebHook callback channel
google-api, google-api-java-client, google-drive-api, java
Solution
You have to add your domain to the developers console.
How to:
- Log in to the Google Developers Console
- Select your project
- Under 'APIS & AUTH' select 'Push'
- Click 'Add domains'
- Enter the needed domains (Only the domain is needed, not the whole notification url)
- Click the 'Add domains' button
After that it should work unless there's something else wrong with what you're doing :p
Problem
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" } } ```