New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 692577 link

Starred by 0 users

Issue metadata

Status: WontFix
Owner: ----
Closed: Feb 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

Migration from GCM (manifest) to VAPID (applicationServerKey) managed incorrectly

Reported by collimar...@gmail.com, Feb 15 2017

Issue description

Steps to reproduce the problem:
1. Subscribe a device by using GCM (you enter the GCM sender ID in the manifest.json) - notifications are sent successfully
2. Then you decide to migrate your application to VAPID, so you add an applicationServerKey param to the pushManager.subscribe call (and you leave the manifest there)
3. Subscribe a new device with VAPID - notifications are sent successfully
4. Take the initial device, which already has a subscription created with GCM - notifications are still sent successfully with the legacy GCM credentials
5. The problem is that if you call pushManager.subscribe on the initial device, it returns an FCM subscription (https://fcm.googleapis.com/fcm/send/...) that doesn't work - the error 400 UnauthorizedRegistration is returned by FCM to the server, as if you were using a wrong VAPID key pair
6. Moreover pushManager.getSubscription() still returns the old https://android.googleapis.com/... endpoint, while the  pushManager.subscribe method returns the new FCM endpoint - that is clearly inconsistent behavior

What is the expected behavior?
Chrome on Android (like Chrome on Desktop and Firefox already do) must raise an error if pushManager.subscribe is called when there is already a subscription associated to a different sender (e.g. a different VAPID key or a legacy GCM sender).

What went wrong?
1. pushManager.subscribe returns a new endpoint that doesn't work, but it should have raised an exception
2. pushManager.subscribe and pushManager.getSubscription() return two different endpoints (you can call them many times, with interleaving, and they will keep returning different endpoints - that is inconsistent)

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 55.0.2883.91  Channel: n/a
OS Version: 6.0.0, HUAWEI
Flash Version:

 
Even removing the manifest.json doesn't solve the problem - the issue is still the same.

Even calling pushManager.subscribe({ ... }).then(function() { pushManager.getSubscription ... }); doesn't circumvent the problem: we still get the invalid FCM endpoint, returned by getSubscription this time. However if we call pushManager.getSubscription outside the pushManager.subscribe callback, we get the old GCM endpoint. This is totally inconsistent behavior.

Because of this bug at Pushpad we're getting a lot of FCM endpoints that are invalid (400 UnauthorizedRegistration)!
We can't do anything to prevent that on our side. Please do something to fix this bug.

Comment 2 by peter@chromium.org, Feb 15 2017

Cc: awdf@chromium.org
Hi Marco, thanks for the report!

According to the bug you're using Chrome 55 - we actually fixed the first part of this issue in Chrome 56 ( Issue 638924 ). Would you mind trying again with the latest version?

The difficulty in determining which URL we return is that it's based off whether you pass an `applicationServerKey` or not. The reason for this is that many developers, unfortunately, were (and are) parsing the URL under the assumption that it would be the GCM endpoint.

However, they should be interchangeable. Does the authentication error occur because this triggers your server to try and authenticate using VAPID, as opposed to the GCM authentication secret?

One possible work-around (that I haven't tried!) would be to get the subscription and read the PushSubscription.`options` object to see whether the applicationServerKey was set.
> Would you mind trying again with the latest version?

Chrome 56 is not available yet on the Play Store (Italy). I'll try to update Chrome again in the next days.

> Does the authentication error occur because this triggers your server to try and authenticate using VAPID, as opposed to the GCM authentication secret?

Yes, the problem is that our server uses VAPID for fcm.googleapis.com, while it uses the legacy GCM HTTP server for old subscriptions (android.googleapis.com). 
This is **the correct behavior** based on what you have wrote on your blog:

> To subscribe a Chrome user for push with the VAPID public key, you need to [...] You'll know if it has worked by examining the endpoint in the resulting subscription object, if the origin is fcm.googleapis.com, it's working.
> https://developers.google.com/web/updates/2016/07/web-push-interop-wins
What behavior should I expect from **Chrome 56**? I mean: After raising the exception, if you catch it and call pushManager.getSubscription (like we do on line 145: https://pushpad.xyz/pushpad.js), do you get the correct GCM endpoint (android.googleapis.com) or you get the corrupted endpoint that starts with fcm.googleapis.com?

Comment 5 by peter@chromium.org, Feb 15 2017

I see that the release has been delayed indeed, it should become available in the next few days.

The documentation indeed doesn't cover this case very well. We'll have to update the article in the near future due to new syntax for VAPID (that other browsers are also adopting), so this'll be considered as part of that.

Chrome 56 will start throwing when calling subscribe() because the given `applicationServerKey` is different from the Manifest's `gcm_sender_id` that was used to create the subscription. Given that getSubscription() will return the existing subscription, that should indeed return the endpoint you expect.
> Chrome 56 will start throwing when calling subscribe() because the given `applicationServerKey` is different from the Manifest's `gcm_sender_id` that was used to create the subscription. Given that getSubscription() will return the existing subscription, that should indeed return the endpoint you expect.

Ok great! This is the behavior that I was expecting because we had tested the migration from GCM to VAPID on Chrome 56 Desktop. So if the behavior will become consistent on the mobile version the issue will eventually solve.

> The documentation indeed doesn't cover this case very well. We'll have to update the article in the near future due to new syntax for VAPID (that other browsers are also adopting), so this'll be considered as part of that.

I think that with the new behavior of Chrome 56, you can suggest to use the method that we have already used and successfully tested (on desktop) at Pushpad:
If you call pushManager.subscribe and it raises an exception, catch the exception and, in order to establish if the current device is subscribed to push notifications with another sender, call pushManager.getSubscription.
You can see the code on line 145: https://pushpad.xyz/pushpad.js 

This method ensures that:
- old GCM subscriptions work
- new VAPID subscriptions work
- if you try to subscribe with VAPID an old GCM subscription, then you still get the old GCM subscription
- after an old GCM subscriber resets the permission, he will be able to use VAPID

Comment 7 by peter@chromium.org, Feb 16 2017

Cc: mattgaunt@chromium.org
Status: WontFix (was: Unconfirmed)
That's very helpful, thank you! +mattgaunt FYI

Let me close this issue as there's nothing we can change about Chrome 55 anymore. Please feel free to file a new issue for other issues you're encountering.
I have just tested with Chrome 56 on Android and the method I've described above works as expected!

Sign in to add a comment