Notifications on phones while NeoKOM is in the background (Web Push) #135

Open
opened 2026-10-19 01:43:17 +00:00 by littlefox · 5 comments
Owner

On a phone, the browser freezes NeoKOM soon after it goes to the background (and closes its WebSocket), so it doesn't hear about new posts and can't notify. The notifications from #103 only work while the page is still running.

Fixing that needs Web Push: something that stays connected to LysKOM for the person and sends a push message to the phone's push service. That would be the relay, holding a logged-in session, or a second session per person, which changes what the relay is (today it only forwards bytes, D-040).

Needs a decision from the user before any work: whether a server-side component may stay logged in on someone's behalf, and where it runs.

On a phone, the browser freezes NeoKOM soon after it goes to the background (and closes its WebSocket), so it doesn't hear about new posts and can't notify. The notifications from #103 only work while the page is still running. Fixing that needs Web Push: something that stays connected to LysKOM for the person and sends a push message to the phone's push service. That would be the relay, holding a logged-in session, or a second session per person, which changes what the relay is (today it only forwards bytes, D-040). Needs a decision from the user before any work: whether a server-side component may stay logged in on someone's behalf, and where it runs.
Author
Owner

I assume there would be some security implications with holding sessions open on the relay. The relay would have to cache the user password or have some authentication mechanism when connecting to the relay.

I assume there would be some security implications with holding sessions open on the relay. The relay would have to cache the user password or have some authentication mechanism when connecting to the relay.
Author
Owner

Yes. That's the core of it. LysKOM has no tokens or app passwords: the only way to log in is person + password (Protocol A login). So whatever stays connected for someone either holds the password, or holds a session that was opened with it.

What changes, and what doesn't

Already true today. The relay terminates the browser's TLS and passes the login request on, so it sees the password in transit at every login. Users already trust the relay operator with that. Holding sessions changes how long a credential lives: from "during one connection, in memory" to "hours or days".

Risks, roughly biggest first:

  1. Stored passwords. Passwords on disk, even encrypted with a key on the same server, turn a relay break-in into everyone's LysKOM password. People reuse passwords. I'd rule this out.
  2. Hijacking a held session. Whatever lets a device reattach to, or control, its session must be a strong random secret, bound to that device, revocable and expiring.
  3. What the session can do. A logged-in session can do anything the person can: write, mark read, change memberships. The watcher has to be read-only by construction: an allow-list of the few calls it needs (log in invisibly, accept new-text and message events, get text-stat and subject), with everything else refused in code.
  4. Visibility on the server. People would appear logged in around the clock. Log in invisibly. That's still a permanent connection per person from one address, which the lyskomd admins should agree to (more than D-040's "other relays exist").
  5. What goes through Google and Apple. Web Push payloads are encrypted end to end (RFC 8291), so the push service can't read them. It does see timing and which device. The notification text also shows on the lock screen. There should be a choice between "Anna nämnde dig: Fråga" and just "Nytt i NeoKOM".
  6. Logging out. "Logga ut" has to stop the watcher. A list of devices that get notifications should let you remove one.
  7. Logs. Keep the 24 h policy, and never log text content or anything from the login.

Options

A. The password stays in memory only. A separate small push service; I'd keep it out of the byte-forwarding relay, so the relay stays simple to audit.

  • Turning notifications on for a device sends the password once, over TLS, to that service. The service logs in an invisible, read-only watcher and keeps the password only in memory (and could even drop it once logged in).
  • Push subscriptions are kept on disk; they aren't secrets in the same way. After a restart, or if lyskomd drops the session, the watchers are gone. The service then sends each device one last push: "Aviseringar pausade, öppna NeoKOM". Opening the app turns them back on.
  • Weakness: anyone controlling the running process can read memory. That's no worse than today's relay.

B. Keep the browser's own session when the page goes away. The relay doesn't close the lyskomd connection when the WebSocket drops; it watches it, and the page reattaches with a secret token.

  • No second login and no password handover.
  • But the relay has to understand Protocol A, not just forward bytes, and reattaching mid-stream is fiddly.
  • The full session stays open, not a read-only one, so a hijack gets everything.

C. Stored, encrypted password. It survives restarts, but it's risk 1. Not recommended.

D. No server. Android only lets an installed web app sync in the background rarely (Periodic Background Sync, about every 12 h at best). That's useless for this.

Worth knowing: iPhones only get Web Push for apps added to the home screen (iOS 16.4 and later).

My recommendation

A, opt-in per device, with:

  • a read-only invisible watcher;
  • no credentials on disk;
  • a "paused, open NeoKOM" push after restarts;
  • a device list with "remove";
  • a setting for hiding content in notifications.

Questions for you

  1. Where does it run? Only in your home Docker container (your machine, your password), or also on the public deployment at Lysator (#71), where it would hold other people's sessions?
  2. Lyskomd admins. For the public deployment, are you OK with me drafting a note to the lyskomd admins about invisible, permanent read-only sessions from one address? You'd send it.
  3. Paused after a restart. Is "notifications pause until you open the app again" acceptable after a restart?
Yes. That's the core of it. LysKOM has no tokens or app passwords: the only way to log in is person + password (Protocol A `login`). So whatever stays connected for someone either holds the password, or holds a session that was opened with it. ## What changes, and what doesn't **Already true today.** The relay terminates the browser's TLS and passes the login request on, so it sees the password in transit at every login. Users already trust the relay operator with that. Holding sessions changes how long a credential lives: from "during one connection, in memory" to "hours or days". **Risks, roughly biggest first:** 1. **Stored passwords.** Passwords on disk, even encrypted with a key on the same server, turn a relay break-in into everyone's LysKOM password. People reuse passwords. I'd rule this out. 2. **Hijacking a held session.** Whatever lets a device reattach to, or control, its session must be a strong random secret, bound to that device, revocable and expiring. 3. **What the session can do.** A logged-in session can do anything the person can: write, mark read, change memberships. The watcher has to be read-only by construction: an allow-list of the few calls it needs (log in invisibly, accept new-text and message events, get text-stat and subject), with everything else refused in code. 4. **Visibility on the server.** People would appear logged in around the clock. Log in invisibly. That's still a permanent connection per person from one address, which the lyskomd admins should agree to (more than D-040's "other relays exist"). 5. **What goes through Google and Apple.** Web Push payloads are encrypted end to end (RFC 8291), so the push service can't read them. It does see timing and which device. The notification text also shows on the lock screen. There should be a choice between "Anna nämnde dig: Fråga" and just "Nytt i NeoKOM". 6. **Logging out.** "Logga ut" has to stop the watcher. A list of devices that get notifications should let you remove one. 7. **Logs.** Keep the 24 h policy, and never log text content or anything from the login. ## Options **A. The password stays in memory only.** A separate small push service; I'd keep it out of the byte-forwarding relay, so the relay stays simple to audit. - Turning notifications on for a device sends the password once, over TLS, to that service. The service logs in an invisible, read-only watcher and keeps the password only in memory (and could even drop it once logged in). - Push subscriptions are kept on disk; they aren't secrets in the same way. After a restart, or if lyskomd drops the session, the watchers are gone. The service then sends each device one last push: "Aviseringar pausade, öppna NeoKOM". Opening the app turns them back on. - Weakness: anyone controlling the running process can read memory. That's no worse than today's relay. **B. Keep the browser's own session when the page goes away.** The relay doesn't close the lyskomd connection when the WebSocket drops; it watches it, and the page reattaches with a secret token. - No second login and no password handover. - But the relay has to understand Protocol A, not just forward bytes, and reattaching mid-stream is fiddly. - The full session stays open, not a read-only one, so a hijack gets everything. **C. Stored, encrypted password.** It survives restarts, but it's risk 1. Not recommended. **D. No server.** Android only lets an installed web app sync in the background rarely (Periodic Background Sync, about every 12 h at best). That's useless for this. Worth knowing: iPhones only get Web Push for apps added to the home screen (iOS 16.4 and later). ## My recommendation A, opt-in per device, with: - a read-only invisible watcher; - no credentials on disk; - a "paused, open NeoKOM" push after restarts; - a device list with "remove"; - a setting for hiding content in notifications. ## Questions for you 1. **Where does it run?** Only in your home Docker container (your machine, your password), or also on the public deployment at Lysator (#71), where it would hold other people's sessions? 2. **Lyskomd admins.** For the public deployment, are you OK with me drafting a note to the lyskomd admins about invisible, permanent read-only sessions from one address? You'd send it. 3. **Paused after a restart.** Is "notifications pause until you open the app again" acceptable after a restart?
Author
Owner

I need to think some more before I answer these questions fully. But the intended end-goal is to run a public relay on lysator. Lyskomd admins should be fine with it, since there are already other types of relays and, since passwords pass the "last mile" as plain-text anyway, security is rather relaxed in general. Paused notifications are perfectly fine.

This is a massive limitation of Protocol A. I want to file this away for a rainy day when I can think about drafting some proposals for extentions of the protocol

I need to think some more before I answer these questions fully. But the intended end-goal is to run a public relay on lysator. Lyskomd admins should be fine with it, since there are already other types of relays and, since passwords pass the "last mile" as plain-text anyway, security is rather relaxed in general. Paused notifications are perfectly fine. This is a massive limitation of Protocol A. I want to file this away for a rainy day when I can think about drafting some proposals for extentions of the protocol
Author
Owner

Thanks. Recorded as D-043 (PR #139). Aimed at the public deployment, pausing after a restart is fine, and 0.3 ships without it. The protocol idea is filed as #138. This issue stays open with needs/user until you've decided on the design.

Thanks. Recorded as D-043 (PR #139). Aimed at the public deployment, pausing after a restart is fine, and 0.3 ships without it. The protocol idea is filed as #138. This issue stays open with needs/user until you've decided on the design.
Author
Owner

Parking this issue for now. Important for future usability, but currently not possible to achieve safely and effectively.

Parking this issue for now. Important for future usability, but currently not possible to achieve safely and effectively.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
littlefox/neokom#135
No description provided.