You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2026/10/19 13:43:22 UTC
(james-project) 07/08: fixup! [ENHANCEMENT] JMAP Web Push: VAPID (RFC-9749)
This is an automated email from the ASF dual-hosted git repository.
chibenwa pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 1293a61230158aea665c152c4dd94cd4064f1e68
Author: Clement Guyon <cg...@linagora.com>
AuthorDate: Mon Oct 12 23:49:30 2026 +0200
fixup! [ENHANCEMENT] JMAP Web Push: VAPID (RFC-9749)
Document how to generate the VAPID key pair and what to use as subject.
---
docs/modules/servers/partials/configure/jmap.adoc | 38 +++++++++++++++++++++-
.../sample-configuration/jmap.properties | 6 ++--
.../sample-configuration/jmap.properties | 6 ++--
.../sample-configuration/jmap.properties | 6 ++--
4 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/docs/modules/servers/partials/configure/jmap.adoc b/docs/modules/servers/partials/configure/jmap.adoc
index 190305a2ef..03b0d1bd38 100644
--- a/docs/modules/servers/partials/configure/jmap.adoc
+++ b/docs/modules/servers/partials/configure/jmap.adoc
@@ -129,7 +129,9 @@ Required when the public key is set. Keep it secret.
| webpush.vapid.subject
| Optional string. Contact of the operator of this server, sent to the push services as the `sub` claim: a `mailto:`
-or an `https:` URI. Recommended when VAPID is configured, as some push services refuse requests without it.
+or an `https:` URI. Set it whenever VAPID is configured: the push service of Apple (`web.push.apple.com`) refuses
+requests without it, and the {server-name} logs a warning upon start when it is missing.
+See <<_generating_vapid_cryptographic_material,Generating VAPID cryptographic material>>.
| cassandra.filter.projection.activated
|Optional boolean. Defaults to false. Casandra backends only. Whether to use or not the Cassandra projection
@@ -264,6 +266,40 @@ This token can then be passed as `Bearer` of the `Authorization` header :
The public key can be referenced as `jwt.publickeypem.url` of the `jmap.properties` configuration file.
+== Generating VAPID cryptographic material
+
+Browsers only subscribe to Web Push with the public key of the server, and their push services refuse the pushes that
+are not signed with the matching private key (VAPID, link:https://www.rfc-editor.org/rfc/rfc8292[RFC-8292]). The
+{server-name} needs one P-256 key pair for this, set in `jmap.properties`. It advertises the public key in the JMAP
+session, so that clients need no configuration (link:https://www.rfc-editor.org/rfc/rfc9749[RFC-9749]).
+
+One can use OpenSSL to generate the key pair, then print each key in the expected form, base64url without padding:
+
+ # key pair
+ openssl ecparam -name prime256v1 -genkey -noout -out vapid.pem
+ # webpush.vapid.private.key: the private value, 32 bytes
+ openssl ec -in vapid.pem -outform DER 2>/dev/null | tail -c +8 | head -c 32 | base64 | tr '+/' '-_' | tr -d '=\n'
+ # webpush.vapid.public.key: the public key as an uncompressed point, 65 bytes
+ openssl ec -in vapid.pem -pubout -outform DER 2>/dev/null | tail -c 65 | base64 | tr '+/' '-_' | tr -d '=\n'
+
+The keys are 43 and 87 characters long. Tools that generate VAPID keys for Web Push, as
+`npx web-push generate-vapid-keys`, print them in this same form.
+
+ webpush.vapid.public.key=<the public key>
+ webpush.vapid.private.key=<the private key>
+ webpush.vapid.subject=mailto:postmaster@domain.tld
+
+Regarding these values:
+
+ - The private key is a secret: restrict the access to `jmap.properties`, and delete `vapid.pem` once the keys are
+copied. The {server-name} refuses to start when the two keys do not match.
+ - The subject tells the push services whom to contact about the pushes of this server: use an address that is read,
+as `mailto:postmaster@domain.tld`, or the `https:` URL of a contact page. It is sent to the push services only, never
+to the users.
+ - Use the same key pair on every node of a cluster, and keep it: subscriptions are bound to the key they were created
+with. Key rotation (RFC-9749 section 5) is not implemented, hence after a change push services refuse the pushes of
+existing subscriptions until clients subscribe again.
+
== Annotated specification
The [annotated documentation](https://github.com/apache/james-project/tree/master/server/protocols/jmap-rfc-8621/doc/specs/spec)
diff --git a/server/apps/distributed-app/sample-configuration/jmap.properties b/server/apps/distributed-app/sample-configuration/jmap.properties
index a92f58ac46..4ecb40a262 100644
--- a/server/apps/distributed-app/sample-configuration/jmap.properties
+++ b/server/apps/distributed-app/sample-configuration/jmap.properties
@@ -59,8 +59,10 @@ tls.secret=james72laBalle
# VAPID (RFC-8292, RFC-9749): identifies this server to the push services, which browsers require to subscribe.
# A P-256 key pair, base64url encoded as Web Push tools generate it: the public key in its uncompressed form (65 bytes),
-# the private key (32 bytes). Defaults to no VAPID.
+# the private key (32 bytes). Defaults to no VAPID. See "Generating VAPID cryptographic material" in the JMAP
+# configuration documentation.
# webpush.vapid.public.key=
# webpush.vapid.private.key=
-# Contact of the operator, a mailto: or an https: URI. Recommended: some push services refuse requests without it.
+# Contact of the operator, a mailto: or an https: URI. Set it with the keys: the push service of Apple refuses
+# requests without it.
# webpush.vapid.subject=mailto:postmaster@example.com
\ No newline at end of file
diff --git a/server/apps/memory-app/sample-configuration/jmap.properties b/server/apps/memory-app/sample-configuration/jmap.properties
index 720bdb80af..ac4f143c45 100644
--- a/server/apps/memory-app/sample-configuration/jmap.properties
+++ b/server/apps/memory-app/sample-configuration/jmap.properties
@@ -56,8 +56,10 @@ delay.sends.enabled=true
# VAPID (RFC-8292, RFC-9749): identifies this server to the push services, which browsers require to subscribe.
# A P-256 key pair, base64url encoded as Web Push tools generate it: the public key in its uncompressed form (65 bytes),
-# the private key (32 bytes). Defaults to no VAPID.
+# the private key (32 bytes). Defaults to no VAPID. See "Generating VAPID cryptographic material" in the JMAP
+# configuration documentation.
# webpush.vapid.public.key=
# webpush.vapid.private.key=
-# Contact of the operator, a mailto: or an https: URI. Recommended: some push services refuse requests without it.
+# Contact of the operator, a mailto: or an https: URI. Set it with the keys: the push service of Apple refuses
+# requests without it.
# webpush.vapid.subject=mailto:postmaster@example.com
\ No newline at end of file
diff --git a/server/apps/postgres-app/sample-configuration/jmap.properties b/server/apps/postgres-app/sample-configuration/jmap.properties
index a92f58ac46..4ecb40a262 100644
--- a/server/apps/postgres-app/sample-configuration/jmap.properties
+++ b/server/apps/postgres-app/sample-configuration/jmap.properties
@@ -59,8 +59,10 @@ tls.secret=james72laBalle
# VAPID (RFC-8292, RFC-9749): identifies this server to the push services, which browsers require to subscribe.
# A P-256 key pair, base64url encoded as Web Push tools generate it: the public key in its uncompressed form (65 bytes),
-# the private key (32 bytes). Defaults to no VAPID.
+# the private key (32 bytes). Defaults to no VAPID. See "Generating VAPID cryptographic material" in the JMAP
+# configuration documentation.
# webpush.vapid.public.key=
# webpush.vapid.private.key=
-# Contact of the operator, a mailto: or an https: URI. Recommended: some push services refuse requests without it.
+# Contact of the operator, a mailto: or an https: URI. Set it with the keys: the push service of Apple refuses
+# requests without it.
# webpush.vapid.subject=mailto:postmaster@example.com
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org