Google push notifications - Unauthorized WebHook callback channel
Asked Answered
B

6

23

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"
 }
}
Berkin answered 29/5, 2014 at 8:15 Comment(10)
Half year after, same code, same configuration, same environment, domain, etc. and now it works...Berkin
FWIW, I was getting this error today. 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. Hope this helps somebody.Thaxton
@JohnNaegle This was the solution that worked for me. Thanks :-)Wentworth
@JohnNaegle Wow. Yeah, refresh and everything is gone. ( that took an hour and half to diagnose ). Thank god for your comment. I've tried relogging and incognito, same result => No real save seems to happen. Was there something you did in particular?Tortfeasor
@Tortfeasor I don't remember now - sorry. The google developer console is a very frustrating tool.Thaxton
@user3686724, I've got similar issue. Have you solved one? Can you share your solution, please?Lakitalaks
As i wrote earlier, under same conditions it did work later (it was 11/2014), but as I am not using that code any more I can't tell what is the problem now...Berkin
I also have this issue. I tried incognito, and nothing seems to work. Adding comment here in case anyone has a solutionTooling
I am also getting same problem, I am using angular5 and nodejs app.Indeclinable
I am getting this issue as well... I have the URL saved and verified but still get the 401 Unauthorized error.Hershberger
G
32

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

Giddy answered 5/7, 2014 at 17:15 Comment(6)
You also need to add a https url, and have a valid (not self-signed) SSL license.Laceylach
APIS & AUTH has moved to Credentials => Domain VerificationThaxton
Sounds like an obvious thing - but this didn't work for me for ages because the test access token I was getting was tied to the OAuth playground app, not my own Google app (where I'd added the domain as above).Butte
I have this working on production, do you know any way to test it locally though?Junta
The only way you could test notifications locally would be if your machine had a dedicated IP that Google can access through a domain. You can add localhost in the developer console to use the API locally though. Refer to this thread: How to test google calendar api v3 on localhostGiddy
The steps are now: 1. Go to the Google Cloud Platform Console. 2. Select your project. 3. Open the navigation sidebar in the top left corner, select APIs & services. 4. Then select Credentials. Select Domain verification. 5. Select Add domain.Scheck
T
5

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.

Thaxton answered 8/9, 2016 at 15:51 Comment(0)
L
3

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.

Lusitania answered 4/12, 2018 at 12:22 Comment(0)
F
0

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.

Feed answered 30/8, 2018 at 9:33 Comment(0)
M
0

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).

Maroon answered 8/10, 2018 at 14:41 Comment(0)
D
0

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().

Deragon answered 19/10, 2021 at 23:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.