user3686724
user3686724

Reputation: 613

Google push notifications - Unauthorized WebHook callback channel

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"
 }
}

Upvotes: 23

Views: 14451

Answers (6)

JBW
JBW

Reputation: 81

I had this same issue. Other answers mention the need to add your domain to Google Cloud Platform Console -> APIs & Services -> Domain verification. Where I went wrong was I had a route attached to my domain so I was trying to add https://www.example.com/route. Needed to verify ownership of the top-level domain, ie of https://www.example.com in Google Search Console, then add top-level domain in domain verification and then could use https://www.example.com/route as the address in drive.changes.watch().

Upvotes: 0

Munkhbayar Nergui
Munkhbayar Nergui

Reputation: 31

So this is all because of Settings on console.developers.google.com. You need to add your back-end domain to both Authorised domains on (OAuth Consent Screen tab) and Allowed domains (on Domain Verification tab).

So there reason why it works for you now is that probably you verified and added your top-level domain already while your local environment had separate (not a sub domain of the verified top-level) domain at the time, specially if you had been exposing your local server on internet.

Upvotes: 3

Artemius Pompilius
Artemius Pompilius

Reputation: 49

I confirmed my domain, checked my SSL, but problem hasn't gone.

Finally I found the solution: Use Service Acconut Key in Google Developers Console (not API Key and not OAuth client ID).

Upvotes: 0

Aniket Thakur
Aniket Thakur

Reputation: 68985

For me, I wanted the callback webhook URL as https://test-apis.domain.io. So for domain verification, I added test-apis.domain.io and then tried to modify the TXT record but it never was working(validating).

Finally ended up verifying just domain.io with the same method. After this was done I was able to add the domain test-apis.domain.io in the credentials "Domain verification" screen. Hope this helps others as well.

Upvotes: 0

John Naegle
John Naegle

Reputation: 8257

For me, as I put in a comment above,

The Domain Verification was not saving in google developer console (refresh the page and it was gone). The problem ultimately ended up being I was logged in as two google accounts, my gmail account and my company account. Adding the domain verification seemed to get confused about the account and not save the domain settings.

Try logging in using a different browser or incognito session if you use multiple google accounts.

Upvotes: 5

natronite
natronite

Reputation: 897

You have to add your domain to the developers console.

How to:

  1. Log in to the Google Developers Console
  2. Select your project
  3. Under 'APIS & AUTH' select 'Push'
  4. Click 'Add domains'
  5. Enter the needed domains (Only the domain is needed, not the whole notification url)
  6. Click the 'Add domains' button

After that it should work unless there's something else wrong with what you're doing :p

Upvotes: 32

Related Questions