mozilla-services / autopush

Python Web Push Server used by Mozilla
https://autopush.readthedocs.io/
Mozilla Public License 2.0
215 stars 34 forks source link

How to send notifications without vapid keys #1451

Closed waleed-alsaady closed 3 years ago

waleed-alsaady commented 3 years ago

I have a lot of subscriptions from Firefox (endpoints, with the two keys). They are not tied to an applicationServerKey. I'm looking at this site to see the sending process: https://mozilla-services.github.io/WebPushDataTestPage/ It states the payload isn't supposed to be encrypted but it seems that webpush libraries generally do encrypt it, so I'm not sure how I can send notifications correctly. I've tried many things but always get 401 Unauthorized errors: "Request did not validate missing authorization header: Invalid key data" "Request did not validate missing authorization header: Missing Authorization Header" Request did not validate invalid token etc

This example in the above site is the only working thing I've found that sends without vapids, but it's really hard for me to follow and copy the process in C#. There must be a simple way to do this?

jrconlin commented 3 years ago

That web page does encrypt the data for you, and is more designed for library authors than for someone trying out webpush.

Near the bottom (in step 6 "Send the Message" you'll see a "Curl:" block. That contains the encrypted message, plus the various headers you'd need to send it. (I'll note that the page uses an older form of encryption and I have not had a chance to updated it to the proper version, but it should still work.) It looks like a jumble if you're not familiar with how command line curl works, but the first line writes a bunch of encrypted binary into a file encrypted.data, then the curl -v -X POST ... sends the data.

The 401 error does wound like you are trying to send to a push URL that has been locked. In that case you'd need to add the appropriate VAPID Authorization header. We tried to make the error responses as helpful as we could, (e.g. "Invalid key data" usually happens because the content of the -H "crypto-key: ..." header had wrong or incomplete data in it, "Missing Authorization Header" happens because there's no -H "Authorization:..." header, "Invalid token" means that the Push URL https://updates.push.services.mozilla.com/... was shortened or had extra characters inserted. etc.

I'll also say that that page only works for Mozilla Push URLs. https://updates.push.services.mozilla.com/... Chrome works similarly, but has it's own requirements (Notably, all Push messages require VAPID auth.)

waleed-alsaady commented 3 years ago

Hi, Thanks for the information. My problem is that the subscriptions were all obtained through One Signal and now I'm trying to import them and do the sending myself. Chrome subscriptions work fine since they gave me the vapid keys, but they claim that they do not use vapid keys for firefox as it's not required. Anyway, I've noticed all the firefox subscriptions from OS have "v2" in the endpoint, but the one from this test page comes out as "v1". My guess is that v2 uses vapid, and v1 doesn't? So I just realized I can test out, I'll see what happens if I try to get a subscription (using localhost test page) without specifying a vapid key ie. calling just

await registration.pushManager.subscribe({
        userVisibleOnly: true,
        //applicationServerKey: publicKey
    });

If the resulting endpoint has v2, then OS is correct (they really didn't put a vapid key and got 'v2' endpoints), otherwise if it's "v1" then that means OS is mistaken since logically v2 must mean a vapid was given. Well the result is that i got a "v1" endpoint, so there must be vapids tied to those OS subscriptions. Anyway, I've noticed out of the subscriptions there are only about 100 per 10k subscriptions, so it's not really worthwhile to get this working. It's also owing to firefox auto hiding the permission popup so my priority will just be to implement double opt in in my script. Thanks a lot for the help

jrconlin commented 3 years ago

Ah, I see.

Yeah, trying to send out subscription updates like that will never work for a whole host of security reasons. One Signal uses VAPID to authenticate, but each subscription is also encrypted according to a shared key that only they have. You would need to have your customers resubscribe so you get fresh subscription info blocks (which include the encryption key data) and that you could then lock using your own VAPID key.

I'll note that this stuff can be a bit tricky to work out MDN's documentation, mostly focuses on the client(browser) side of things. I've written several posts that talk about how to send out push subscription updates that might be more useful.