RFC 9749

Use of Voluntary Application Server Identification (VAPID) in JSON Meta Application Protocol (JMAP) Web Push

πŸ“… published March 2025, from ietf

RFC 9749 πŸŽ€ Use of VAPID in JMAP Web Push

okay bestie, let's get into this one πŸ’… It's a Standards Track doc by Daniel Gultsch from March 2025 πŸ¦‹ It's part of the IETF stream, it's an official Internet Standard-type spec, and it doesn't obsolete or update any other RFCs. Just vibes, no drama 🌸

Abstract ✨

This doc says how JMAP servers can announce that they can sign Web Push notifications with VAPID πŸ”

Status of This Memo πŸ“œ

This is an Internet Standards Track document πŸ’–

It's a product of the IETF, so it has the whole community's consensus 🫢 It got public review and the IESG approved it for publication. If you want more on Internet Standards, check out Section 2 of RFC 7841 🧚 Errata and feedback live at https://www.rfc-editor.org/info/rfc9749 ✨

Copyright (c) 2025 IETF Trust and the document authors, all rights reserved 🌈

This doc is under BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as of the publication date. Read those carefully, they spell out your rights πŸ’… Code pulled from this doc has to include the Revised BSD License text (see Section 4.e of the Trust Legal Provisions), and it comes with no warranty as described in that license πŸ™ˆ

Table of Contents πŸ—‚οΈ

1.  Introduction
2.  Conventions Used in This Document
3.  Discovering Support for VAPID
4.  Issuing Push Notifications
5.  Key Rotation
6.  Security Considerations
7.  IANA Considerations
  7.1.  Registration of the JMAP Capability for VAPID
8.  References
  8.1.  Normative References
  8.2.  Informative References
Author's Address

1. Introduction πŸ¦‹

okay so JMAP [RFC8620] lets clients subscribe to events using something compatible with Web Push [RFC8030] πŸ”” Some push services want the application server to authenticate every push message with VAPID [RFC8292] πŸ” To make that work, the client (aka the user agent in Web Push lingo) needs the server's VAPID public key so it can hand it to the push service when it grabs a new endpoint πŸ’œ

2. Conventions Used in This Document πŸ“š

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in ALL CAPS like that πŸ’…

3. Discovering Support for VAPID πŸ”

The JMAP capabilities object comes back as part of the standard JMAP session object (see Section 2 of [RFC8620]) ✨ Servers that support this spec MUST add a property called urn:ietf:params:jmap:webpush-vapid to the capabilities object πŸŽ€ That property's value is an object that MUST contain the following info:

applicationServerKey: "String" πŸ”‘ The ECDSA public key the push service uses to authenticate the application server πŸ¦‹ It's in uncompressed form (see Section 2.3.3 of [SEC1]) and base64url-encoded [RFC7515] 🌸 Current systems use the P-256 curve [FIPS186] πŸ’–

Informative note: the key format was picked to play nicely with the browser API (Section 7.2 of [PUSH-API]), so you can copy it over directly with zero transformation 🧚 As noted in Section 3.2 of [RFC8292], the X9.62 encoding (which is SEC1-compatible) makes key comparisons easier and is more compact than other formats 🫢

4. Issuing Push Notifications πŸ“¨

Every single time the server sends a push message to a PushSubscription URL, it MUST authenticate that POST request using the protocol in [RFC8292] πŸ” That covers both StateChange events and PushVerification notifications πŸ’… To authenticate, the server MUST use a JSON Web Token (JWT) signed by the private key that matches the application server key πŸ”‘ And this application server key MUST be the one that was advertised in the capabilities object when the PushSubscription got created 😭

5. Key Rotation πŸ”„

When a server needs to swap out its VAPID key, it MUST update the sessionState per [RFC8620] πŸ’« The client MUST keep an eye on the JMAP session object for VAPID key changes, and MUST recreate its push subscription when it spots one πŸ‘€

After a key rotation, the server MAY keep sending push notifications for existing push subscriptions that use the old application server key for a transitional period πŸ¦‹ That gives clients time to recreate their push subscriptions 🌈 At the end of the transitional period (or right away, for implementations that don't have one), the server MUST destroy push subscriptions that use the old key πŸ’€

When destroying push subscriptions that include the PushSubscription data type, the server MAY send one final StateChange push notification using the old URL and application server key πŸŽ€ It tells the client about changes to the PushSubscription data type and prompts it to make a PushSubscription/changes method call πŸ”” The response to that call includes an updated sessionState, which points to a session object with the new VAPID key ✨

Here's a race condition 😬 The server can update its VAPID key after the client has refreshed the session object but before the client calls the PushSubscription/set method πŸ’” Then the server sends a PushVerification object to a push resource URL that's now tied to an outdated VAPID key πŸ™ˆ So the push service rejects it with a 403 (Forbidden) status code, as specified in Section 4.2 of [RFC8292] 🚫

To fix this, the client MUST check whether the sessionState in the PushSubscription/set response points to a session object with an applicationServerKey that matches what it expects πŸ’… If it doesn't match, the client MAY retry creating the PushSubscription πŸ” The client MAY also destroy the PushSubscription from the earlier, failed attempt 🧹

6. Security Considerations πŸ”

Okay this part is serious, bestie 😭 During key rotation, client and server can get out of sync πŸŒͺ️ For example, a client might have a push subscription with the push service tied to an outdated key, while the server signs the PushVerification object with the newly rotated key πŸ’€ That mismatch makes the push service reject the PushVerification request with a 403 (Forbidden) status code, as specified in Section 4.2 of [RFC8292] 🚫

Per the requirements of Section 7.2 of [RFC8620], the server MUST NOT retry the rejected PushVerification request πŸ›‘ So the PushVerification object never reaches the client 😒

To help with this, the client is responsible for detecting and fixing any sync discrepancies, as outlined in Section 5 of this document 🫢

The urn:ietf:params:jmap:webpush-vapid property in the JMAP capabilities object only tells you whether the server supports VAPID πŸ¦‹ It doesn't reveal sensitive info and doesn't add any new security or privacy risks beyond what JMAP and Web Push already have ✨ The security considerations for JMAP [RFC8620] (especially Sections 8.6 and 8.7), Web Push [RFC8030], and VAPID [RFC8292] all apply to this document πŸ’œ

7. IANA Considerations πŸ›οΈ

7.1. Registration of the JMAP Capability for VAPID πŸŽ€

IANA registered a new capability in the "JMAP Capabilities" registry 🌸

Capability Name:  urn:ietf:params:jmap:webpush-vapid
Intended Use:  common
Change Controller:  IETF
Security and Privacy Considerations:  RFC 9749, Section 6
Reference:  RFC 9749

8. References πŸ“š

8.1. Normative References πŸ’…

[FIPS186]  NIST, "Digital Signature Standard (DSS)", NIST FIPS 186-5,
           DOI 10.6028/NIST.FIPS.186-5, February 2023,
           <https://doi.org/10.6028/NIST.FIPS.186-5>.

[SEC1]     Standards for Efficient Cryptography Group, "SEC 1:
           Elliptic Curve Cryptography", Version 2.0, May 2009,
           <http://www.secg.org/sec1-v2.pdf>.

[RFC8620]  Jenkins, N. and C. Newman, "The JSON Meta Application
           Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July
           2019, <https://www.rfc-editor.org/info/rfc8620>.

[RFC8030]  Thomson, M., Damaggio, E., and B. Raymor, Ed., "Generic
           Event Delivery Using HTTP Push", RFC 8030,
           DOI 10.17487/RFC8030, December 2016,
           <https://www.rfc-editor.org/info/rfc8030>.

[RFC8292]  Thomson, M. and P. Beverloo, "Voluntary Application Server
           Identification (VAPID) for Web Push", RFC 8292,
           DOI 10.17487/RFC8292, November 2017,
           <https://www.rfc-editor.org/info/rfc8292>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC7515]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web
           Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
           2015, <https://www.rfc-editor.org/info/rfc7515>.

8.2. Informative References ✨

[PUSH-API] Beverloo, P., Ed., Thomson, M., Ed., and M. Caceres, Ed.,
           "Push API", W3C Working Draft, September 2024,
           <https://www.w3.org/TR/push-api/>.

Author's Address πŸ’Œ

Daniel Gultsch Email: daniel@gultsch.de

πŸ“¦ where this page comes from