Skip to content

ernaniaz/webpush

Repository files navigation

PHP Web Push – Quick-start

Web Push overview

The Web Push process allows a website to send notifications to a user even when the site is not open. It begins when the browser asks the user for permission to receive notifications. If the user agrees, the browser creates a subscription with a push service, such as Firebase, Mozilla Push Service, or Apple Push Service. This subscription contains a unique endpoint URL, along with a public key and an authentication secret. The browser then provides this information to the web application.

The web application sends the subscription details to its server, where they are securely stored, often in a database. When the application wants to send a notification, the server prepares a message payload and encrypts it using the public key provided in the subscription. The server then sends this encrypted payload to the push service endpoint, authenticating the request using the VAPID (Voluntary Application Server Identification) standard.

The push service verifies the message and forwards it to the appropriate browser. Even if the website is closed, the browser can still receive the push message. When this happens, it activates the registered Service Worker in the background, which processes the message and displays a notification to the user.

In essence, Web Push creates a secure communication chain between the web application, the push service, and the browser, enabling reliable delivery of messages and notifications directly to users.

Technical overview

This repo demonstrates end-to-end Web Push with minimal dependencies:

  1. Front-end (Service-Worker + page script) acquires a subscription using the W3C Push API and sends it to the back-end.
  2. Back-end PHP stores that JSON and later builds a standards-compliant push request using webpush_send.php which implements VAPID, ECDH, HKDF and AES-GCM in ~400 lines of functions.
  3. The push request is sent over HTTP/2 to the vendor’s push service (FCM for Chromium, Mozilla Push Service for Firefox, etc.). The browser then delivers a push event to the Service-Worker which displays (or routes) a notification.

For an illustrated explanation of each layer see the linked technical docs below.

This repository shows a minimal, pure-PHP way to experiment with the Web Push API – both from the browser’s Service-Worker side and from the server that delivers the push messages. If you're looking for a PHP class implementation, I recommend web-push-libs/web-push-php implementation.

Technical deep-dives:

Browser JavaScript flow
Browser implementation details
Low-level push request construction


1. Requirements

  • PHP 8.1+ with OpenSSL extension
  • Any modern browser (Chrome, Firefox, Edge, Brave, Safari 17-plus)

Everything else is vendored – no Composer install needed for a quick demo.


2. Generate your VAPID keys

php generate_vapid_keys.php

This creates two URL-safe base64 files:

  • vapid_public.key
  • vapid_private.key ← keep this one secret

3. Run the demo site

php -S 127.0.0.1:8000

Then visit http://127.0.0.1:8000/ and click Subscribe. The page will:

  1. Register service-worker.js
  2. Ask for notification permission
  3. Generate a Push Subscription and POST it to handle_subscription.php

The subscription JSON lands in subscription.json (or similar).


4. Send a push from PHP

Use webpush_send.php to send a notification to your browser.

Examples:

# Modern encoding – works in all current browsers
php webpush_send.php subscription.json aes128gcm

# Legacy old browsers compatibility
php webpush_send.php subscription.json aesgcm

If no parameters are provided, the script will read the client subscription keys from subscription.json (the file created by handle_subscription.php when you register your browser) and use the default encryption method (aes128gcm by default, or the legacy aesgcm).

You'll see a debug output as a result.


5. Security

This project is a simple, pure-PHP implementation designed to easily test and understand Web Push technology.

There are some important points to consider if you plan to use this code in production:

  • Never expose the vapid_private.key file.
  • Store client subscription data in a secure location or in a database.
  • In the example app.js, the server’s public VAPID key is loaded from vapid_public.key. In production, inject the key directly into the JavaScript file.
  • For production use, webpush_send.php should be optimized. The current implementation is intentionally unoptimized to make the protocol easier to understand.

6. Clean-up

rm subscription.json vapid_public.key vapid_private.key

7. License

This project is released under MIT license.

Happy pushing 📯

About

Pure PHP Web Push full example implementation

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors