maxence-charriere / go-app

A package to build progressive web apps with Go programming language and WebAssembly.
https://go-app.dev
MIT License
7.91k stars 363 forks source link

Support for push manager #303

Closed bgokden closed 2 years ago

bgokden commented 4 years ago

It would be nice to add subscription bootstrap into page.js (https://github.com/maxence-charriere/app/blob/c5fc1cb2b7861d05ca80284f2e38b1b7c46a69b7/internal/http/page.js)

And callbacks to goapp.js

maxence-charriere commented 4 years ago

Yes it would be good to be able to do push notifications. I ll work on this next.

prologic commented 2 years ago

Yes it would be good to be able to do push notifications. I ll work on this next.

You said you'd work on this next πŸ˜… That was nearly ~2 years ago!

I'm building a new messaging app over at salty.im and it would be really great if you could add some kind of push notifications support to go-app πŸ‘Œ -- I don't know much about how push notifications work really, I've tried to understand how to self-hosted (without relying on Firebase or other "cloud" services); but I'm not even sure this is possible? (the docs on the Web Push API are confusing and not very clear :/)

maxence-charriere commented 2 years ago

I gave a try but wasnt satisfied. I guess i have to give another one.

oderwat commented 2 years ago

Funny coincidence.

I am currently working on it and have it running (for us). I started to make something that could work as PR. I think it could be something "pluggable" that can be activated (similar to the service worker updates I just made a PR for).

Facts: It works with Desktop Chrome, Edge, and Firefox on Windows and Mac. It works on Android but it does not work on iOS and will not until Apple implements it.

prologic commented 2 years ago

Isn't this already supported in iOS 15.4?

See: https://www.macworld.com/article/610673/ios-15-4-safari-push-notifications.html

At least there were rumours it was coming, but I'm not 100% sure!

prologic commented 2 years ago

@maxence-charriere Also if would be great if we would merge some of the outstanding PR(s) that @oderwat has mentioend. I'm even happy to review code as well (especially Go code).

oderwat commented 2 years ago

Isn't this already supported in iOS 15.4?

See: https://www.macworld.com/article/610673/ios-15-4-safari-push-notifications.html

At least there were rumours it was coming, but I'm not 100% sure!

Having "some sort" of push notifications for PWAs on iOS would be nice indeed.

But what we are currently using is https://developer.mozilla.org/en-US/docs/Web/API/Push_API

Web Push (using service workers) does not work with Apple and I doubt it ever will. This does currently also not work for Safari on Mac (which supports some other kind of push for years). It does work for Firefox and Chrome on OSX and even shows up in the system notifications bar. So all you need on OSX is to use another browser than Safari.

You may read about it here:

https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW1

You will see that you need to use a developer account and register it for this to work (on Safari). I choose not to investigate and implement this until such functionality is available to the users of our clients and for sure not just to make Safari work (and I am an hardcore OSX user).

prologic commented 2 years ago

@oderwat Then we need to push Apple to implement the Web Push API.

prologic commented 2 years ago

We should however add support for Web Push API to go-app, even if it isn't supported on iOS / OSX 's Safari (yet).

oderwat commented 2 years ago

We should however add support for Web Push API to go-app, even if it isn't supported on iOS / OSX 's Safari (yet).

This is actually not so easy to do universally, because it may be very special what you want to do.

There is also more to it than "just" push, as you want to create notifications and react to actions when a user clicks them.

But not every push should end up in notification and you also may want to create notifications from inside the app.

For the push to the clients, you also need the backend to store the subscription of each client and the logic to send a push to some or all of them. You also want to expire, clean up and let the user unregister subscriptions. There is a lot more to it than I think that go-app can/should handle itself.

Writing everything just as "abstractions" also adds a lot of interfaces and code for a very special use case, while you still need to write the service worker in javascript and your only way of communication with the clients are messages or the local storage.

I have most of this working right now, but I have no clue on how to make this universal. You need to change the service worker (adding events like push/message/notificationclick) and you need to add code to your client to handle messages to and from the services worker.

I currently extend the service worker and let it create and receive messages that tell me if I get push or notifications. In return it receives messages for creation of notifications. Then the client receives those messages and transforms them to go-app actions. While it also allows to send messages to the service worker. So when I get a push it transfers to the client, the client checks what kind of push it is and creates a notification if needed. When those are clicked, the service worker finds open tabs or PWAs and focuses them while also creating a message to optionally navigate/handle the action from the notification. If no tab / PWA is active it opens one and adds some information through the URL, as you can't send a message to the freshly opened client).

P.S.: I have more than 20 browser tabs with informations open that helped to solve the puzzle ;-)

prologic commented 2 years ago

@oderwat If you could help document what you did and how and show code examples that would help a lot. I understand what you're saying, and my own use-case may be different to yours (although I doubt it). we'll see... I need to get anything working at all though.

We'll leave the "Get Apple off their lazy buts to add Web Push to iOS" later, but that'll have to happen too, I have no doubts they're working on it.

Also yes, I do have a server that can maintain subscriptions, in fact this is how my app works in the first place πŸ˜…

prologic commented 2 years ago

For reference: https://git.mills.io/saltyim/saltyim

oderwat commented 2 years ago

For reference: https://git.mills.io/saltyim/saltyim

Actually, I a not sure that I would want an encrypted and decentralized chat system to register my browser at a server of a third party (even a Google or Mozilla one) which could then track my identity, the identities of all other users, and when they and I am online or receive messages :)

Besides that, I already wrote, that I am thinking of creating a PR for it, but currently, I don't see how this could work with all the moving targets.

I started and used mostly these sources of information:

The basic knowledge is that you need to create the VAPID Keys for "your app" and then let the client create a subscription. This subscription goes to the server and the server can then push a notification to the client. The push is being received by the service worker and (may) needs to be sent to one of the clients of the services worker. In addition one may want to show a notification for those notifications and send the user to the right tab / app, when he clicks it.

prologic commented 2 years ago

Actually, I a not sure that I would want an encrypted and decentralized chat system to register my browser at a server of a third party (even a Google or Mozilla one) which could then track my identity, the identities of all other users, and when they and I am online or receive messages :)

That's my problem too. I always thought with this whole Push stuff you coudl self-host the push server or something. But I can't seem to figure this out. There is no way I'm adding Push support if that "data" just gets shoved through AWS or Google.

oderwat commented 2 years ago

I always thought with this whole Push stuff you coudl self-host the push server

This would mean that the devices would need to be connected to an "infinite" number of servers all the time.

With web push, the browser needs to be connected to the push server to receive the messages and there is only one. And if you want to have it for PWAs the OS itself needs to run the browsers and the service workers as part of it. This is (I guess) also the reason why Apple does not support it (service worker-based push). They have their own push system in the OS, so why add another one?

It is like usually: Nothing is free and being able to use push comes with a cost. Of course :)

As long as we can not run permanent background networking on the devices, there will be no independent messaging. This also has nothing to do with PWAs. Notifications for any mobile app are going through the OS vendor's systems.

So the only thing you can do is running your own push services but this will not trigger the PWA and need the app to be running. The next best thing would be sending SMS / iMessage / e-mail and well, same problem and even less convenient.

prologic commented 2 years ago

Well we'll just have to get Apple to fish this so Web Push actually works and a Service Worker can get notified. Otherwise this is kind of pointless to write PWA(s) -- especially for iOS.

Your comment re "infinite servers" is a bit odd? I'm only talking about one server, one app.

prologic commented 2 years ago

This article seems to have a great deal more detail on the upcoming support for Web Push and even improvements to Web Manifests for PWA(s) on Apple's iPadOS and iOS platforms.

Really excited by this potentially coming to iOS 16.x -- It obviously didn't make it to 15.4 :/

oderwat commented 2 years ago

Your comment re "infinite servers" is a bit odd? I'm only talking about one server, one app.

But I have not only one app on my mobile phone. I have about 500...

P.S.: I don't think that PWAs are pointless for iOS. Not every app needs to have push notifications.

prologic commented 2 years ago

P.S.: I don't think that PWAs are pointless for iOS. Not every app needs to have push notifications.

But you probably do want this in a messaging app? πŸ€”

oderwat commented 2 years ago

But you probably do want this in a messaging app? πŸ€”

As previously said: No, I usually don't want to be tracked by third parties when securely messaging, heck I do not even want to be tracked by any service. And before you ask: I would not use any secure (+ anonymous) messaging system on any mobile device ever. This is just to much of a "black box", even if I write it myself and deploy it myself onto the device.

But this gets pointless. I specifically said that it is not needed for every type of PWA. I already wrote games and tools which just don't need any push messages.

Could we go back to how stuff is implemented? If you have some questions about what I posted above I am glad to help :)

prologic commented 2 years ago

@oderwat Sorry yes of course, was just confused by your earlier statement.

Web Push API support...

Gys commented 2 years ago

@oderwat The discussion mainly focuses on Safari and iOS, but do you have it working for Android?

From this article [0] I understand two APIs are 'available': the (local) Notifications API and the (remote) Push API. I understand both APIs are supported by Android.

[0] https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push

oderwat commented 2 years ago

@oderwat The discussion mainly focuses on Safari and iOS, but do you have it working for Android?

Facts: It works with Desktop Chrome, Edge, and Firefox on Windows and Mac. It works on Android but it does not work on iOS and will not until Apple implements it.

Gys commented 2 years ago

Sorry! I overlooked that one.

You wrote: I am currently working on it and have it running (for us). I started to make something that could work as PR.

By 'it' do you mean the Push API I believe. I would be interested if go-app.dev would support at least Android.

oderwat commented 2 years ago

By 'it' do you mean the Push API

I mean push and notifications. I also gave links to all needed information and resources to implement it here: https://github.com/maxence-charriere/go-app/issues/303#issuecomment-1079687582

I am not going to create a PR for this as it would need a lot of front and backend code which seems to be very special and abstractions leave a lot of stuff open.

@maxence-charriere I think we need a way to modify (add) our own code to the service worker, which has to be JS. I also think it would be nice to have an official implementation for messaging between clients and the service worker. My current solutions are only working with our own go-app fork (which also contains the other PRs I have open and which are being used by out projects).

prologic commented 2 years ago

@maxence-charriere I think we need a way to modify (add) our own code to the service worker, which has to be JS. I also think it would be nice to have an official implementation for messaging between clients and the service worker. My current solutions are only working with our own go-app fork (which also contains the other PRs I have open and which are being used by out projects).

This would be nice πŸ‘Œ

prologic commented 2 years ago

Just circling back on this issue to see if anyone had noticed whether Apple's newest iOS 16.x now support Web Push like they promised? πŸ€”

Gys commented 2 years ago

Apple said that starts half of 2023

krustowski commented 7 months ago

I may be dumb, but I really thought I could be able to send Push notifications to an iOS device without the need for applying to the Apple Developer Program... so now I know I guess. (I misinterpreted Apple Push Notifications and Web Push Notifications).

TL;DR: I did my homework, and figured out how to send Web Push notifications to iOS devices: just fill the Subscriber property of webpush.Options struct.


For anyone interested further, I will describe my problem in more detail below.

For the Web Push notification service, I am using the recommended SherClockHolmes' webpush-go library. Everything works fine for all browsers and device combinations that @oderwat mentioned above. Except for Safari on for any Apple platform.

I was curious on why this won't work at all. So I started digging. Soon after, I found that Apple's Push endpoint returns HTTP/403 with a JSON snippet:

{"reason":"BadJwtToken"}

Moreover, I had been browsing through the Apple Developer documentation portal. Then I bumped into this quote [1]:

You don’t need to join the Apple Developer Program to send web push notifications.

Whoa! OK! Let's continue our journey then. I started looking for this, such verbose, error message on the web. I had been trying to tweak the subscription somehow to make it work too. Nope. OK, back to reading.

Next, I found out, that the source URL had to be different from localhost, [2]

Note: As of this writing, if a push notification request contains a VAPID subject referencing an https://localhost URI (set either using the options argument or via the global setVapidDetails() method), Safari's push notification endpoint rejects the request with a BadJwtToken error.

So, I setup a new site for the dev instance, just for the sake of HTTPS suite usage. Nope. Still getting the strange response from the Apple's Web Push gateway. Maybe adding more fields would help? Not really. OK, let's see the specifications from Apple now, again. Found this quote: [3]

BadJwtToken The JSON web token (JWT) has one of following issues: The JWT is missing. The JWT is signed with the wrong private key. The JWT subject claim isn’t a URL or mailto:. The JWT audience claim isn’t the origin of the push service where you sent the request. The JWT expiration parameter is more than one day into the future.

Hm, I wasn't really like disassembling webpush lib(s) or writing it all again myself, so I kept looking for more info. Frustrated, tired, desperate, I opened the RFC [4], to read about JWT's claims etc. Then out of blue I got an idea: there's that Subscriber property, where one can specify an username or whatever. Let me try to fill it with an e-mail. Maybe? Redeployed the app, fired a request for notification to the provider and BOOM --- my phone vibrates and I got my notification... So trivial, innit?

In conclusion, let's break the journey into those bullets:

[1] https://developer.apple.com/documentation/UserNotifications/sending-web-push-notifications-in-web-apps-and-browsers [2] https://github.com/web-push-libs/web-push [3] https://developer.apple.com/documentation/UserNotifications/sending-web-push-notifications-in-web-apps-and-browsers [4] https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2

oderwat commented 6 months ago

FYI: WebPush on iOS (17.3 /17.4) works for us

oderwat commented 6 months ago

@krustowski I did not follow your post but did the same journey yesterday. We actually made our own webpush package. There is even more to the whole thing if you use TTL and JWT expiration. SherClockHolmes seems to be using deprecated packages too. But overall this is working, and I hope that @maxence-charriere will update v10 and splits the implementation, so we can push other stuff than just notifications too.