Mercurial > prosody-modules
annotate mod_push2/push2.md @ 6299:5cf5ee23b361
mod_voipms: New Module to send and receive SMS/MMS via VoIP.ms APIs.
diff --git a/mod_voipms/README.md b/mod_voipms/README.md
new file mode 100644
--- /dev/null
+++ b/mod_voipms/README.md
@@ -0,0 +1,51 @@
+---
+labels:
+- 'Stage-Alpha'
+- 'Type-Web'
+summary: Send and receive SMS/MMS via VoIP.ms APIs.
+rockspec:
+ build:
+ modules:
+ mod_voipms: mod_voipms.lua
+...
+
+Introduction
+============
+
+This is a Prosody module to map JIDs to DIDs on VoIP.ms and support sending/receiving SMS/MMS.
+
+Configuration
+=============
+
+| option | type | default |
+|-----------------------|--------|---------|
+| voipms\_api\_username | string | nil |
+| voipms\_api\_password | string | nil |
+| voipms\_query\_key | string | nil |
+| voipms\_jid\_map | table | nil |
+```
+VirtualHost "sms.example.com"
+modules_enabled = {
+ "voipms";
+}
+voipms_api_username = john@example.com -- E-mail registered with VoIP.ms
+voipms_api_password = abcd1234 -- API password configured in VoIP.ms
+voipms_query_key = some_query_key -- query param 'key' part of your URL callback
+voipms_jid_map = {
+ ["your_jid@your_domain.com"] = "+1234567890"
+}
+```
+
+HTTP
+====
+
+The module is served on Prosody's default HTTP ports at the path /voipms. More details on configuring HTTP modules in Prosody can be found in the HTTP documentation.
+
+VoIP.ms Webhook URL
+===================
+
+This module receives the VoIP.ms Webhook URL (POST) at the /voipms endpoint. It uses the sendSMS/sendMMS GET methods against the VoIP.ms APIs. This is an example webhook to use in VoIP.ms:
+
+```
+https://sms.example.com/voipms?key=some_query_key
+```
diff --git a/mod_voipms/mod_voipms.lua b/mod_voipms/mod_voipms.lua
new file mode 100644
--- /dev/null
+++ b/mod_voipms/mod_voipms.lua
@@ -0,0 +1,166 @@
+local http = require "net.http"
+local json = require "util.json"
+local st = require "util.stanza"
+
+local api_username = module:get_option_string("voipms_api_username")
+local api_password = module:get_option_string("voipms_api_password")
+local query_key = module:get_option("voipms_query_key")
+local jid_map = module:get_option("voipms_jid_map") or {}
+local rest_endpoint = "https://voip.ms/api/v1/rest.php"
+
+if not api_username or not api_password or not query_key then
+ module:log("error", "Missing required config values (voipms_api_username, voipms_api_password, voipms_query_key)")
+ return
+end
+
+module:depends("http")
+
+local function normalize_number(num)
+ if not num then return nil end
+ if num:sub(1, 1) ~= "+" then
+ return "+1" .. num
+ end
+ return num
+end
+
+local function extract_query_key(event)
+ return (event.request.url.query or ""):match("key=([^&]+)")
+end
+
+module:provides("http", {
+ route = {
+ ["POST"] = function(event)
+ local req = event.request
+ local body = req.body or ""
+
+ if extract_query_key(event) ~= query_key then
+ module:log("warn", "Unauthorized webhook: missing or invalid key")
+ return { status_code = 403 }
+ end
+
+ local json_payload, err = json.decode(body)
+ if not json_payload then
+ module:log("warn", "Invalid JSON: %s", err or "unknown error")
+ return { status_code = 400 }
+ end
+
+ local payload = json_payload.data and json_payload.data.payload
+ if not payload then
+ module:log("warn", "Missing payload in JSON")
+ return { status_code = 400 }
+ end
+
+ local from = payload.from and payload.from.phone_number
+ local to_list = payload.to or {}
+ local to = #to_list > 0 and to_list[1].phone_number or nil
+
+ if not from or not to then
+ module:log("warn", "Missing phone numbers (from: %s, to: %s)", tostring(from), tostring(to))
+ return { status_code = 400 }
+ end
+
+ local normalized_to = normalize_number(to)
+ local target_jid = nil
+
+ for jid, did in pairs(jid_map) do
+ if normalize_number(did) == normalized_to then
+ target_jid = jid
+ break
+ end
+ end
+
+ if not target_jid then
+ module:log("warn", "No JID mapping for DID %s", normalized_to)
+ return { status_code = 404 }
+ end
+
+ local normalized_from = normalize_number(from)
+ local message_text = payload.text or ""
+
+ local message = st.message({
+ from = normalized_from .. "@" .. module.host,
+ to = target_jid,
+ type = "chat"
+ }):tag("body"):text(message_text):up()
+
+ if payload.media and #payload.media > 0 then
+ for _, media_item in ipairs(payload.media) do
+ if media_item.url then
+ message_text = message_text .. "\n" .. media_item.url
+ message:tag("x", { xmlns = "jabber:x:oob" })
+ :tag("url"):text(media_item.url):up():up()
+ end
+ end
+ end
+
+ module:send(message)
+ module:log("info", "Delivered SMS from %s to %s", normalized_from, target_jid)
+
+ return { status_code = 204 }
+ end
+ }
+})
+
+module:hook("message/bare", function(event)
+ local stanza = event.stanza
+ if stanza.attr.type ~= "chat" then return end
+
+ local from_jid = stanza.attr.from
+ local to_jid = stanza.attr.to
+ local body = stanza:get_child_text("body")
+ if not body or body == "" then return end
+
+ local from_number = jid_map[from_jid]
+ if not from_number then
+ module:log("warn", "No DID mapping for JID %s", from_jid)
+ return
+ end
+
+ local to_number = to_jid:match("^([^@]+)")
+ if not to_number then
+ module:log("warn", "Malformed JID in message.to: %s", to_jid)
+ return
+ end
+
+ to_number = normalize_number(to_number)
+
+ local media_urls = {}
+ for line in body:gmatch("[^\r\n]+") do
+ if line:match("^https?://") then
+ table.insert(media_urls, line)
+ end
+ end
+
+ local method = (#media_urls > 0) and "sendMMS" or "sendSMS"
+ local query = {
+ api_username = api_username,
+ api_password = api_password,
+ method = method,
+ did = from_number,
+ dst = to_number,
+ message = body
+ }
+
+ if method == "sendMMS" then
+ for i, url in ipairs(media_urls) do
+ query["media_url[" .. (i - 1) .. "]"] = url
+ end
+ end
+
+ local query_str = http.formencode(query)
+
+ http.request(rest_endpoint .. "?" .. query_str, {
+ method = "GET";
+ }, function(response_body, code)
+ if code == 200 then
+ local resp, err = json.decode(response_body)
+ if not resp or resp.status ~= "success" then
+ module:log("error", "Failed to send %s: %s", method, err or (resp and resp.status) or "unknown")
+ else
+ module:log("info", "Sent %s from %s to %s", method, from_number, to_number)
+ end
+ else
+ module:log("error", "HTTP error sending %s: code %s", method, tostring(code))
+ end
+ end)
+end)
| author | Chaz <menel@snikket.de> |
|---|---|
| date | Mon, 21 Jul 2025 23:57:37 +0200 |
| parents | 1c16bb49f6f6 |
| children |
| rev | line source |
|---|---|
|
5659
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
1 # Push 2.0 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
2 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
3 Adapted from notes made at [XMPP Summit 25](https://pad.nixnet.services/oy6MKVbESSycLeMJIOh6zw). |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
4 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
5 Requirements: |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
6 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
7 - Support for SASL2 inlining |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
8 - Extensible stanza matching rules and notification payload rules |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
9 - Simpler syntax and concept model than original specification |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
10 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
11 ## Client registers to receive push notifications |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
12 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
13 ```xml |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
14 <enable xmlns='urn:xmpp:push2:0'> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
15 <service>pusher@push.example.com</service> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
16 <client>https://push.example.com/adlfkjadafdasf</client> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
17 <match profile="urn:xmpp:push2:match:archived-with-body"> |
|
6184
2f2539ce8f3b
mod_push2: implement grace period
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6183
diff
changeset
|
18 <grace>144</grace> |
|
6200
1c16bb49f6f6
mod_push2: rename chat to filter
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6184
diff
changeset
|
19 <filter jid="somemuc@conference.example.com"> |
|
6183
e53f0967520c
mod_push: Allow filtering pushes for particular chats
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6162
diff
changeset
|
20 <mention/> |
|
6200
1c16bb49f6f6
mod_push2: rename chat to filter
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6184
diff
changeset
|
21 </filter> |
|
5659
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
22 <send xmlns="urn:xmpp:push2:send:notify-only:0"/> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
23 </match> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
24 </enable> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
25 ``` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
26 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
27 The `<service/>` element contains a JID which push notifications for this client will be sent to. It may be a host, bare or full JID. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
28 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
29 The `<client/>` element contains an opaque string that will be included in all communication with the push service. It may be used to convey client identifiers used by the push notification service to route notifications. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
30 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
31 The `<match/>` and `<send/>` elements define what profiles to use for matching stanzas and sending notifications. These are described later in this document. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
32 |
|
6200
1c16bb49f6f6
mod_push2: rename chat to filter
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6184
diff
changeset
|
33 The optional `<filter/>` child of `<match/>` allows extra filtering of pushes for only specific chats. No specified filters means muted, do not push. `<mention/>` means push on mentions, `<reply/>` means push on replies. |
|
6183
e53f0967520c
mod_push: Allow filtering pushes for particular chats
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6162
diff
changeset
|
34 |
|
6184
2f2539ce8f3b
mod_push2: implement grace period
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6183
diff
changeset
|
35 The optional `<grace/>` child of `<match/>` allows specifying a "grace period" in seconds where activity on another session by the same user (such as sending a message) will temporarily pause sending push notifications. |
|
2f2539ce8f3b
mod_push2: implement grace period
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
6183
diff
changeset
|
36 |
|
5659
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
37 ## Match and send profiles |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
38 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
39 Different clients and push services have different requirements for push notifications, often due to the differing capabilities of target platforms. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
40 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
41 A "profile" in the context of this specification is a set of rules for matching the kinds of stanzas that should be pushed, and how to transform them before sending the notification to the push service. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
42 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
43 ### Match profiles |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
44 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
45 Match profiles define which incoming stanzas will trigger a push notification. More than one match may be specified. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
46 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
47 Some match profiles are defined in this XEP. Other XEPs may define additional profiles with the reserved `urn:xmpp:push2:match:` prefix, following the registrar considerations explained later in this document. Custom profiles not defined in a XEP should use their own appropriate URI. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
48 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
49 #### `urn:xmpp:push2:match:all` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
50 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
51 Using this profile, all stanzas will trigger a push notification to be sent to the push service when the client is unavailable. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
52 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
53 #### `urn:xmpp:push2:match:important` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
54 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
55 Stanzas that are considered to be "important" are pushed. At the time of writing, there is no standard definition of "important", however most servers already contain such logic for traffic optimization when combined with [XEP-0352: Client State Indication](https://xmpp.org/extensions/xep-0352.html). |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
56 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
57 #### `urn:xmpp:push2:match:archived` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
58 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
59 Push notifications will be sent for any stanza that is stored in the user's archive. This is a good indication that the stanza is important, and is desired on all of a user's devices. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
60 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
61 #### `urn:xmpp:push2:match:archived-with-body` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
62 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
63 Matches only archived messages that contain a body. This can be used to exclude certain message types, such as typing notifications, receipts and error replies. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
64 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
65 ### Send profiles |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
66 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
67 When a server has determined that a stanza should trigger a push notification (according to the client's selected 'match' profile), it proceeds to create a notification stanza following the send profiles specified in the match profiles which match this stanza. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
68 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
69 After constructing the notification stanza, it will then be sent to the push service JID selected by the client. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
70 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
71 Some send profiles are defined in this XEP. Other XEPs may define additional profiles with the `urn:xmpp:push2:send:` prefix, following the registrar considerations explained later in this document. Custom profiles not defined in a XEP should use their own appropriate URI. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
72 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
73 #### `urn:xmpp:push2:send:notify-only:0` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
74 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
75 Send an empty notification to the push service. Such notifications are useful if a push notification can trigger the client to "wake up" and connect to the server to receive the message over XMPP. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
76 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
77 Example: |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
78 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
79 ```xml |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
80 <message to="pusher@push.example.net"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
81 <notification xmlns="urn:xmpp:push2:0"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
82 <client>https://push.example.com/adlfkjadafdasf</client> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
83 <priority>normal</priority> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
84 </notification> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
85 </message> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
86 ``` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
87 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
88 #### `urn:xmpp:push2:send:sce+rfc8291+rfc8292:0` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
89 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
90 Delivers content encrypted according to RFC8291 and with a JWT auth following RFC8292 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
91 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
92 ```xml |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
93 <send xmlns="urn:xmpp:push2:send:sce+rfc8291+rfc8292:0"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
94 <ua-public>Base64 encoded P-256 ECDH public key (raw, uncompressed)</ua-public> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
95 <auth-secret>Base64 encoded randomly generated 16 octets</auth-secret> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
96 <jwt-alg>ES256</jwt-alg> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
97 <jwt-key>PKCS#8 PEM encoded ECDSA keypair, without the header or footer lines</jwt-key> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
98 <jwt-claim name="aud">https://push.example.com</jwt-claim> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
99 </send> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
100 ``` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
101 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
102 The full stanza is wrapped in XEP-0297 forwarded and then that is wrapped in XEP-0420 envelope/content with optional rpad. The raw bytes of the resulting XML are encrypted according to RFC8291 using the provided `ua-public` and `auth-secret`. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
103 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
104 If `jwt-alg` is specified, then a JWT is computed over any provided claims plus a suitable `exp` and `sub` claim and signed using the provided key. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
105 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
106 Then a notification is sent: |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
107 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
108 ```xml |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
109 <message to="pusher@push.example.net"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
110 <notification xmlns="urn:xmpp:push2:0"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
111 <client>https://push.example.com/adlfkjadafdasf</client> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
112 <priority>normal</priority> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
113 <encrypted xmlns="urn:xmpp:sce:rfc8291:0"> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
114 <payload>Base64 encoded ciphertext</payload> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
115 </encrypted> |
|
5663
a1d22d6efb3d
mod_push2: Need to include the public key with the JWT
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5659
diff
changeset
|
116 <jwt key="base64 encoded raw public key">the signed JWT, if present</jwt> |
|
5659
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
117 </notification> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
118 </message> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
119 ``` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
120 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
121 NOTE: if the stanza exceeds the maximum size of 4096 bytes (and some implementations may wish to restrict this even more) the stanza may have some elements removed, body truncated, etc before it is delivered. Servers SHOULD ensure that at least the MAM id (if there is one) is still present after any minimization. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
122 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
123 ## Discovering support |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
124 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
125 A server that supports this protocol MUST advertise the `urn:xmpp:push2:0` feature in an account's service discovery information, along with the supported match and send profiles. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
126 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
127 ```xml |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
128 <iq from='juliet@capulet.lit' |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
129 to='juliet@capulet.lit/balcony' |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
130 id='disco1' |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
131 type='result'> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
132 <query xmlns='http://jabber.org/protocol/disco#info'> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
133 <identity category='account' type='registered'/> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
134 <feature var='urn:xmpp:push2:0'/> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
135 <feature var='urn:xmpp:push2:send:'/> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
136 </query> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
137 </iq> |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
138 ``` |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
139 |
|
6162
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
140 ## Client disables future pushes |
|
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
141 |
|
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
142 ```xml |
|
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
143 <disable xmlns='urn:xmpp:push2:0' /> |
|
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
144 ``` |
|
aa240145aa22
mod_push2: support for disabling push notifications
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
5975
diff
changeset
|
145 |
|
5659
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
146 ## Push service interactions |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
147 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
148 ### Transient delivery errors |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
149 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
150 The user's server might receive delivery errors while sending notifications to the user's push service. The error 'type' attribute SHOULD be honoured - errors of type 'wait' SHOULD be retried in an appropriate manner (e.g. using exponential back-off algorithm, up to a limit), discarding the notification after an appropriate length of time or number of attempts. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
151 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
152 Other error types MUST NOT be automatically retried. |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
153 |
|
4d1a3de56c3d
Initial work on Push 2.0
Stephen Paul Weber <singpolyma@singpolyma.net>
parents:
diff
changeset
|
154 A user's server MAY automatically disable a push configuration for a service that has consistently failed to relay notifications for an extended period of time. This period is a matter of deployment configuration, but a default no less than 72 hours is recommended. |
