[GH-ISSUE #1034] Propagate authorization credentials to matrix client #725

Open
opened 2026-05-07 00:26:56 +02:00 by BreizhHardware · 5 comments

Originally created by @aerusso on GitHub (Feb 24, 2024).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/1034

Problem
With a (self-hosted) ntfy setup with auth-default-access set to deny, it is "impossible" to use the matrix gateway.

💡 Idea
It's not actually impossible, though. If you are also self-hosting a synapse matrix server, you can (in the matrix database)

update pushers set data '{"url":"https://$ntfy_server/_matrix/push/v1/notify?auth=$auth_token","format":"event_id_only"}' where id = $the_push_id

Be sure properly base64 encode $auth_token twice, as described in the docs! (Also, you must stop the matrix server, do the modification, and then start the matrix server up again). Do select * from pushers ; to get an idea of what is going on.

The "idea" here is to have the ntfy app provide this url, instead of the unauthenticated one, to element. This would be the easiest, I think, because it only requires a few bits of changes in the mobile apps.

Another option is to put the token in pushkey. This is a little harder, because authentication currently occurs in server.handle, which calls handleInternal, which in turn calls into the matrix-specific code. This is only abstractly very slightly better, because the clients will automatically replace the url with a generic gateway url if there is no functioning matrix gateway. Realistically, I don't see the benefit: this proposed change would only apply to ntfy versions that already support the matrix gateway.

To protect the passwords of users, the android app could automatically get a token, and pass that as the auth_token.

💻 Target components
I propose adding to only the mobile apps.

Originally created by @aerusso on GitHub (Feb 24, 2024). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/1034 **Problem** With a (self-hosted) ntfy setup with `auth-default-access` set to `deny`, it is "impossible" to use the matrix gateway. :bulb: **Idea** It's not actually impossible, though. If you are also self-hosting a synapse matrix server, you can (in the matrix database) ``` update pushers set data '{"url":"https://$ntfy_server/_matrix/push/v1/notify?auth=$auth_token","format":"event_id_only"}' where id = $the_push_id ``` Be sure properly base64 encode $auth_token twice, as described in the docs! (Also, you must stop the matrix server, do the modification, and then start the matrix server up again). Do `select * from pushers ;` to get an idea of what is going on. The "idea" here is to have the ntfy app provide this url, instead of the unauthenticated one, to element. This would be the easiest, I think, because it only requires a few bits of changes in the mobile apps. Another option is to put the token in `pushkey`. This is a little harder, because authentication currently occurs in server.handle, which calls handleInternal, which in turn calls into the matrix-specific code. This is only abstractly very slightly better, because the clients will automatically replace the url with a generic gateway url if there is no functioning matrix gateway. Realistically, I don't see the benefit: this proposed change would only apply to ntfy versions that already support the matrix gateway. To protect the passwords of users, the android app could automatically get a token, and pass that as the auth_token. :computer: **Target components** I propose adding to only the mobile apps.
Author
Owner

@wunter8 commented on GitHub (Feb 24, 2024):

The docs recommend that people create an access rule that allows anonymous writes to "up*" topics, so that you can use the matrix gateway and other UnifiedPush services, while still having auth-default-access: deny-all

<!-- gh-comment-id:1962413582 --> @wunter8 commented on GitHub (Feb 24, 2024): The docs recommend that people create an access rule that allows anonymous writes to "up*" topics, so that you can use the matrix gateway and other UnifiedPush services, while still having `auth-default-access: deny-all`
Author
Owner

@aerusso commented on GitHub (Feb 25, 2024):

Now that I'm thinking more, it would probably be best to create some token that is unique to the UP topic and subscribing user, and pass that as the authentication token (instead of one specific to only the user). Then, at topic write-time, the service can check to see if the user is still subscribed to the UP topic, and deny/allow based on that. This would naturally expire stale authorizations.

This would require changes to both the authorization pathway in the go server, and proper calculation of those credentials:

  1. A new service provided to authenticated users that returns an encoding of (a) their username and (b) the hash of (their username, a server-wide secret string, and the UP topic name).
  2. The mobile apps should, at UP subscribe time, query the server for this token, appropriately embed it in the UP subscriber URL, and then pass it to the client app.
  3. The authentication chain in the server should check for this kind of token in URLs, and (a) confirm the hashes match, and (b) confirm the user is actually subscribed to the named topic.

Then, anyone with that secret token will be able to post to that topic name as long as the user is subscribed to it. Only constant additional state is required to be tracked by any parties. Similarly, only constant time is required to validate this. Unsubscribing and resubscribing the service will generate a new UP topic name, making the old token worthless (unless the up topic name happens to be reused by the same username, which is unlikely). As long as the server is updated to provide (1) and (3) first (which can be done without breaking backwards-compatibility), clients can gradually roll out support for (2), gracefully improving service. We could simultaneously change the up prefix at this point, and keep the unconditional write-access to that for a while until everyone has transitioned.

Would patches that implement this be welcome? (Unfortunately, it would be a while before I could get to this. In particular I am probably going to try to debug #1035 first)

<!-- gh-comment-id:1962984778 --> @aerusso commented on GitHub (Feb 25, 2024): Now that I'm thinking more, it would probably be best to create some token that is unique to the UP topic and subscribing user, and pass that as the authentication token (instead of one specific to only the user). Then, at topic write-time, the service can check to see if the user is still subscribed to the UP topic, and deny/allow based on that. This would naturally expire stale authorizations. This would require changes to both the authorization pathway in the go server, and proper calculation of those credentials: 1. A new service provided to authenticated users that returns an encoding of (a) their username and (b) the hash of (their username, a server-wide secret string, and the UP topic name). 2. The mobile apps should, at UP subscribe time, query the server for this token, appropriately embed it in the UP subscriber URL, and then pass it to the client app. 3. The authentication chain in the server should check for this kind of token in URLs, and (a) confirm the hashes match, and (b) confirm the user is actually subscribed to the named topic. Then, anyone with that secret token will be able to post to that topic name as long as the user is subscribed to it. Only constant additional state is required to be tracked by any parties. Similarly, only constant time is required to validate this. Unsubscribing and resubscribing the service will generate a new UP topic name, making the old token worthless (unless the up topic name happens to be reused by the same username, which is unlikely). As long as the server is updated to provide (1) and (3) first (which can be done without breaking backwards-compatibility), clients can gradually roll out support for (2), gracefully improving service. We could simultaneously change the `up` prefix at this point, and keep the unconditional write-access to that for a while until everyone has transitioned. Would patches that implement this be welcome? (Unfortunately, it would be a while before I could get to this. In particular I am probably going to try to debug #1035 first)
Author
Owner

@Fmstrat commented on GitHub (Dec 8, 2024):

The docs recommend that people create an access rule that allows anonymous writes to "up*" topics, so that you can use the matrix gateway and other UnifiedPush services, while still having auth-default-access: deny-all

Hate to do this in an issue, but where are these docs? I've been searching for half an hour on how to integrate a self-hosted ntfy with Synapse/Element and can't find an official doc. Thanks.

<!-- gh-comment-id:2526378575 --> @Fmstrat commented on GitHub (Dec 8, 2024): > The docs recommend that people create an access rule that allows anonymous writes to "up*" topics, so that you can use the matrix gateway and other UnifiedPush services, while still having `auth-default-access: deny-all` Hate to do this in an issue, but where are these docs? I've been searching for half an hour on how to integrate a self-hosted ntfy with Synapse/Element and can't find an official doc. Thanks.
Author
Owner

@wunter8 commented on GitHub (Dec 9, 2024):

At least on the ntfy side, I think that access rule is the only thing you need to do. And that's only if you have auth-default-access: deny-all. That is described here: https://docs.ntfy.sh/config/#example-unifiedpush

On the Matrix side, you can refer to these guides: https://unifiedpush.org/users/troubleshooting/self-hosted-ntfy/ and https://unifiedpush.org/users/troubleshooting/self-hosted-with-matrix/

<!-- gh-comment-id:2526526566 --> @wunter8 commented on GitHub (Dec 9, 2024): At least on the ntfy side, I think that access rule is the only thing you need to do. And that's only if you have `auth-default-access: deny-all`. That is described here: https://docs.ntfy.sh/config/#example-unifiedpush On the Matrix side, you can refer to these guides: https://unifiedpush.org/users/troubleshooting/self-hosted-ntfy/ and https://unifiedpush.org/users/troubleshooting/self-hosted-with-matrix/
Author
Owner

@Fmstrat commented on GitHub (Dec 9, 2024):

@wunter8 Thank you. It finally clicked that the element android client triggered the pusher change in synapse. This isn't well documented anywhere, even in those links (read them previously). I made the deny-all and up* changes based on this issue and that doc, but since there wasn't anything specific from the matrix documentation side, I wasn't sure how it worked, and just happened to try the right things.

<!-- gh-comment-id:2526537987 --> @Fmstrat commented on GitHub (Dec 9, 2024): @wunter8 Thank you. It finally clicked that the element android client triggered the pusher change in synapse. This isn't well documented anywhere, even in those links (read them previously). I made the `deny-all` and `up*` changes based on this issue and that doc, but since there wasn't anything specific from the matrix documentation side, I wasn't sure how it worked, and just happened to try the right things.
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
starred/ntfy#725
No description provided.