← PushPig
Web Push (VAPID)
Wie VAPID und Web Push funktionieren — und wie du beides ohne eine Zeile Service-Worker-Code bekommst.
Web Push erreicht deine Nutzer direkt im Browser — auch dann, wenn deine Seite
gerade nicht geöffnet ist. Technisch stecken darin drei Standards: das Push-Protokoll selbst
(RFC 8030), die Ende-zu-Ende-Verschlüsselung der Nutzlast
(RFC 8291) und die Identifikation deines Servers gegenüber dem Push-Dienst
per VAPID (RFC 8292). PushPig übernimmt alle drei — du schreibst keinen
Service Worker und verwaltest keine VAPID-Schlüssel.
Was ist VAPID (RFC 8292)?
VAPID steht für Voluntary Application Server Identification for Web Push. Es beantwortet
eine einzige Frage: Wer ist der Server, der diese Push-Nachricht abschickt? Ohne VAPID nimmt ein
Push-Dienst wie der von Chrome oder Firefox Nachrichten anonym an — er kann Missbrauch nicht
zuordnen und dich bei Problemen nicht erreichen. Mit VAPID signiert dein Anwendungsserver jede
Zustellung mit einem ECDSA-Schlüsselpaar (P-256, ES256).
Signiert wird ein JWT mit genau drei relevanten Claims:
aud — der Origin des Push-Endpoints, z. B. https://fcm.googleapis.com
exp — Ablaufzeitpunkt als Unix-Timestamp; laut RFC maximal 24 Stunden in der Zukunft
sub — deine Kontaktadresse als mailto:-URI oder https:-URL,
damit der Betreiber des Push-Dienstes dich erreichen kann
Der Authorization-Header
RFC 8292 definiert dafür das Auth-Schema vapid mit zwei Parametern:
t trägt das signierte JWT, k den zugehörigen öffentlichen Schlüssel
(unkomprimierter P-256-Punkt, 65 Byte, base64url ohne Padding):
POST /wp/abcd1234 HTTP/1.1
Host: fcm.googleapis.com
Authorization: vapid t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOi…, k=BKxUj7mSc1nT2vQ3…
Content-Encoding: aes128gcm
TTL: 86400
Das JWT selbst besteht aus Header ({"typ":"JWT","alg":"ES256"}), den drei Claims und
der ES256-Signatur — je base64url-kodiert und mit Punkt verbunden. Der k-Parameter
ist derselbe öffentliche Schlüssel, gegen den der Push-Dienst die Signatur prüft.
Ältere Implementierungen nutzen noch das Vorgänger-Schema aus dem VAPID-Draft:
Authorization: WebPush <JWT> plus separaten Header
Crypto-Key: p256ecdsa=<public key>. Die meisten Push-Dienste akzeptieren beide
Varianten — vapid t=…, k=… ist die standardisierte Form.
Derselbe öffentliche Schlüssel wird im Browser als applicationServerKey an
pushManager.subscribe() übergeben. Stimmen Abo-Schlüssel und Signaturschlüssel nicht
überein, weist der Push-Dienst die Zustellung mit 403 ab — der häufigste Fehler bei
selbstgebauten Setups.
VAPID-Schlüssel erzeugen
Ein VAPID-Schlüssel ist ein gewöhnliches ECDSA-Schlüsselpaar auf der Kurve P-256
(prime256v1). Für ein eigenes Setup erzeugst du es einmalig und hinterlegst es auf
deinem Anwendungsserver — mit OpenSSL:
openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
openssl ec -in vapid_private.pem -pubout -out vapid_public.pem
Übertragen werden die Schlüssel aber nicht als PEM, sondern base64url ohne Padding:
der öffentliche als unkomprimierter Kurvenpunkt (65 Byte, erstes Byte 0x04 —
deshalb beginnt jeder VAPID-Public-Key mit einem B), der private als 32-Byte-Skalar.
Das Node-Paket web-push liefert beides direkt in der richtigen Kodierung:
npx web-push generate-vapid-keys
Danach beginnt die eigentliche Arbeit. Der private Schlüssel muss serverseitig sicher liegen, für
jeden Push-Endpoint wird ein frisches JWT signiert (exp höchstens 24 Stunden in
der Zukunft), und der öffentliche Schlüssel darf sich nie ändern: Jede bestehende
Subscription ist an genau diesen applicationServerKey gebunden und wird bei einer
Rotation wertlos — alle Abonnenten müssten neu zustimmen.
Bei PushPig entfällt dieser Schritt vollständig. Der Dienst hält das Schlüsselpaar, signiert jede
Zustellung und liefert den öffentlichen Schlüssel an den Browser aus — du brauchst weder einen
eigenen VAPID-Server noch einen Schlüssel in deinem Deployment.
VAPID ist keine Verschlüsselung
Ein weit verbreitetes Missverständnis: VAPID authentifiziert den Absender, es schützt
nicht den Inhalt. Die Nutzlast wird getrennt davon nach RFC 8291
mit aes128gcm verschlüsselt — mit dem p256dh-Schlüssel und dem
auth-Secret aus der Subscription des Empfängers. Der Push-Dienst des Browsers
transportiert also einen Blob, den er selbst nicht lesen kann.
Konkret führt der Absender einen ECDH-Austausch zwischen einem frisch erzeugten
Ephemeral-Key und dem p256dh des Empfängers durch, leitet daraus per
HKDF-SHA256 — gesalzen mit dem auth-Secret — Content-Encryption-Key
und Nonce ab und verschlüsselt den Klartext mit AES-128-GCM. Beide Verfahren sind unabhängig
voneinander: RFC 8292 entscheidet, ob der Push-Dienst die Nachricht annimmt,
RFC 8291 entscheidet, wer sie lesen kann. Die verschlüsselte Nutzlast darf dabei
höchstens 4.096 Byte groß sein.
Die Spezifikationen im Original
| RFC | Regelt |
| RFC 8030 |
Generic Event Delivery Using HTTP Push — das Push-Protokoll selbst |
| RFC 8291 |
Message Encryption for Web Push — Ende-zu-Ende-Verschlüsselung der Nutzlast |
| RFC 8292 |
VAPID — Identifikation des Anwendungsservers, vapid-Auth-Schema |
Was PushPig dir abnimmt
Alles oben Beschriebene ist der Grund, warum ein eigenes Web-Push-Setup mehr Arbeit ist als
erwartet. Bei PushPig ist es ein einzelner HTTP-Request:
curl -X POST https://pushpig.de/api/push/send \
-H "X-API-Key: $PUSHPIG_KEY" \
-H "Content-Type: application/json" \
-d '{"channel":"deploys","title":"Deploy fertig","body":"v2.4.1 ist live"}'
- Schlüsselpaar-Erzeugung, Rotation und JWT-Signatur pro Endpoint — erledigt
- Verschlüsselung nach RFC 8291 pro Empfänger — erledigt
- Service Worker, Web-App-Manifest und komplettes PWA-Setup — mitgeliefert
- Abgelaufene Subscriptions (
404/410) werden automatisch aufgeräumt
Unterstützte Browser
- Chrome, Edge, Firefox (Desktop & Android) — voll unterstützt
- Safari auf macOS — voll unterstützt
- iPhone / iPad (Safari 16.4+) — nach „Zum Home-Bildschirm hinzufügen" (PWA)
So funktioniert's
Nutzer abonnieren einen Kanal im Dashboard oder in der installierten PWA und erlauben
Browser-Benachrichtigungen. Ab dann wird jede gesendete Nachricht in Echtzeit zugestellt —
verschlüsselt nach RFC 8291 und VAPID-signiert nach RFC 8292.
iOS im Detail
Auf iPhone und iPad funktioniert Web Push nur aus einer zum Home-Bildschirm hinzugefügten PWA
heraus: In Safari über das Teilen-Symbol → Zum Home-Bildschirm, die App von dort
starten und in den Einstellungen die Browser-Benachrichtigungen aktivieren.
Was du bekommst
- Titel, Text und bis zu zwei Aktions-Buttons pro Nachricht
- Echtzeit-Feed im Dashboard über Server-Sent Events
- Delivery-Status pro Event — du siehst, wie viele Geräte erreicht wurden
- Opt-in-E-Mail-Fallback, wenn Push nicht zustellbar ist
Häufige Fragen
Wofür steht VAPID?
VAPID steht für Voluntary Application Server Identification for Web Push und ist in
RFC 8292 spezifiziert. Es erlaubt einem Anwendungsserver, sich gegenüber dem Push-Dienst des
Browsers freiwillig zu identifizieren, indem er jede Zustellung mit einem ECDSA-Schlüsselpaar
(P-256, ES256) signiert.
Wie sieht der VAPID-Authorization-Header aus?
RFC 8292 definiert das Auth-Schema vapid mit zwei Parametern:
Authorization: vapid t=<JWT>, k=<public key>. Der Parameter
t trägt das mit ES256 signierte JWT mit den Claims aud,
exp und sub, k den zugehörigen öffentlichen Schlüssel als
unkomprimierten P-256-Punkt in base64url ohne Padding. Ältere Implementierungen nutzen noch
Authorization: WebPush <JWT> zusammen mit einem separaten
Crypto-Key-Header.
Was ist der Unterschied zwischen RFC 8291 und RFC 8292?
RFC 8292 (VAPID) authentifiziert den Absender gegenüber dem Push-Dienst. RFC 8291 verschlüsselt
die Nutzlast Ende-zu-Ende mit aes128gcm, sodass der Push-Dienst den Inhalt nicht lesen kann.
Beide sind unabhängig voneinander und werden zusammen mit dem Push-Protokoll RFC 8030
eingesetzt.
Brauche ich einen eigenen VAPID-Server?
Nur bei einem selbstgebauten Setup. Dann musst du das Schlüsselpaar erzeugen, den privaten
Schlüssel sicher halten, pro Push-Endpoint ein JWT signieren und den öffentlichen Schlüssel
unverändert lassen. PushPig übernimmt Schlüsselverwaltung, Signatur und Verschlüsselung — du
sendest nur einen HTTP-POST.
Was passiert, wenn ich den VAPID-Schlüssel wechsle?
Alle bestehenden Subscriptions werden ungültig. Jede Subscription ist an den
applicationServerKey gebunden, mit dem sie angelegt wurde; nach einer Rotation
weist der Push-Dienst die Zustellung mit 403 ab und alle Abonnenten müssten erneut zustimmen.
Funktioniert Web Push auf dem iPhone?
Ja, ab Safari 16.4 — allerdings nur aus einer zum Home-Bildschirm hinzugefügten PWA heraus. In
Safari über das Teilen-Symbol „Zum Home-Bildschirm" wählen, die App von dort starten und die
Benachrichtigungen erlauben.
Hilfe & API ·
Preise ·
Kontakt ·
Impressum ·
Datenschutz