When a real software agent needs to send a browser notification, Web Push VAPID can identify the application server making the push request. The application server signs a short-lived JSON Web Token with its private key; the push service verifies the signature, intended push-service origin and expiration. If the subscription was restricted to the application’s public key, the push service can reject requests signed by another key. This authenticates an application server to a push service; it is not evidence that artificial superintelligence exists.
A secure implementation has several separate jobs: obtain permission and a subscription from the user agent, store its endpoint safely, encrypt the payload for the user agent, construct a valid VAPID token, send a bounded request to the correct push service, handle expired subscriptions and rate limits, and enforce application-level consent before any agent is allowed to initiate a notification. VAPID alone does not encrypt message content, guarantee delivery, authorise a particular business action or replace access control over the notification workflow.
Reading map
What VAPID solves that plain Web Push does not · The three principal components · A subscription endpoint is a capability · Where the VAPID signing key belongs · What is inside the signed token? · The audience is a push-service origin · A request should not use one token for every provider · Expiry uses time, not a message counter
A precise elapsed-time example · The optional contact claim is not a user identity · How the HTTP Authorization header is structured · Unrestricted and restricted subscriptions are different · A subscription is not consent to send anything forever · Why VAPID signing and message encryption use different keys · The push service is not the final recipient · RFC 8291 encryption is a distinct protocol
TTL controls delivery retention, not cryptographic identity · Urgency is about delivery scheduling · Topic replacement can prevent redundant notifications · What a successful send response actually proves · The real challenge of asynchronous notification · Missing VAPID authentication and invalid VAPID authentication · A valid signature with the wrong audience must still fail · A stale subscription is not a credential failure
Rate limits need bounded backoff · A short numerical retry budget · Retries can create duplicates · The VAPID token itself can be replayed within its window · A restricted subscription raises the stakes of key rotation · Separate server signing authority from agent planning · Consent and recipient routing are independent · An illustrative three-user push workflow
A denominator check for endpoint outcomes · Why the user-agent public key is not a password · Do not let endpoint URLs become arbitrary outbound destinations · A changed-context transfer: two tenants share one sender · Transfer answer with a verifiable plan · An even harder transfer: rotating keys across both tenants · Diagnostic: a correct signature still yields 403 · Diagnostic: requests are accepted but nobody sees notices
Diagnostic: the same alert appears repeatedly · Diagnostic: one provider works and another fails · Diagnostic: key rotation breaks only old devices · A practical diagnostic matrix for operators · Privacy-safe monitoring without hoarding tokens · A small test harness before public rollout · What the standard does not promise · Primary standards and useful connected reading
The security boundary to remember
What VAPID solves that plain Web Push does not
Web Push routes messages from an application server through an intermediary push service to a user agent such as a browser. The push service cannot assume it has a pre-existing login relationship with every application that may send to a user agent. RFC 8030 therefore describes the message delivery mechanism without requiring a universal application-server authentication system. That design accommodates diverse deployments, but it leaves services needing a way to attribute requests.
RFC 8292 adds Voluntary Application Server Identification, abbreviated VAPID. The server presents a signed token and public key so the push service can associate requests with an application server. The mechanism can also bind a subscription to that key. A signed token identifies the key holder, not the person who asked an AI assistant to perform some task. A secure agent product must make that distinction explicit.
The three principal components
The application server decides whether a message should be sent, prepares its encrypted payload and contacts the push service. The push service accepts eligible messages, manages delivery toward devices and may apply limits. The user agent owns the subscription on the receiving side and exposes permitted events to the application code, usually through a browser service worker. Each component has a separate responsibility and trust boundary.
The network path is not a direct socket from an agent into every device. The server sends an HTTP request to a subscription endpoint that belongs to a push service. The push service then handles an asynchronous delivery process. This indirect design is useful when devices sleep or change networks, but it means a successful HTTP acceptance response should not be conflated with proof that the intended user saw, read or acted on the notification.
A subscription endpoint is a capability
The receiving user agent supplies an application with a push subscription, including an endpoint URL and, for encrypted payloads, associated keying material. The endpoint points to a resource at a push service. Possession of that URL can enable attempts to send push messages under the service’s rules. It therefore deserves secrecy and careful handling even when the subscription is additionally restricted by a VAPID key.
Store endpoints in an access-controlled database, not in analytics query strings, public logs or error screenshots. Scope a stored endpoint to the authenticated user, the application and the consent state that justified creating it. If a user revokes permission or unsubscribes, stop using the endpoint. A server-side agent cannot assume that an endpoint discovered in a document remains authorised forever.
Where the VAPID signing key belongs
The application server holds an elliptic-curve private signing key corresponding to a P-256 public key. The public key may be shared with a user agent while creating a restricted subscription and is included with VAPID authentication so the push service can verify signatures. The private key is a sensitive server-side credential; it should not be embedded in JavaScript sent to users or exposed to ordinary agents.
A practical service stores the private key in a suitable secret-management system, restricts signing operations to a narrow service identity and records when the key is used. Publishing the public key is normal. Publishing the private key allows another actor to imitate the application server’s VAPID identity and potentially send to subscriptions restricted to that key, subject to possession of relevant endpoints and service policy.
What is inside the signed token?
RFC 8292 specifies a JSON Web Token carried with a VAPID HTTP authentication scheme. The token is signed as a JSON Web Signature using ECDSA with the NIST P-256 curve, identified as ES256. Relevant claims include aud for the intended push-service origin and exp for the token’s expiration. A contact-oriented sub claim may be included, but it is optional under the specification.
A valid signature proves that whoever constructed this token held the relevant signing key at signing time, assuming the cryptography and implementation were sound. It does not certify the truth of every optional claim, grant arbitrary API permissions, or encrypt the token body. Treat it as a narrowly purposed authentication artifact for the push service, not a substitute for a separate business authorisation system.
The audience is a push-service origin
The aud claim must contain the origin of the push resource URL, not an arbitrary application homepage and not necessarily the entire subscription path. For an illustrative endpoint https://push.example.net/p/abc123, the origin is https://push.example.net. It comprises the scheme, host and applicable port. Another endpoint under the same origin can use a token with the same audience, subject to expiration and other checks.
An application serving its website from https://school.example is not correct to place https://school.example into aud merely because that is where users signed up. VAPID’s receiving audience is the push service. When an agent moves a message across provider-specific endpoints, derive and validate the actual endpoint origin before signing. Never allow arbitrary untrusted strings to rewrite intended audience values without an endpoint allowlist or equivalent routing controls.
A request should not use one token for every provider
Imagine two users whose push endpoints are https://push-one.example/send/A and https://push-two.example/send/B. A token signed for https://push-one.example is not correctly addressed to the second service. The signing key might be identical, but aud still identifies the destination origin. Generate or select a token for each push-service origin, not one token for all destinations.
A safe implementation can cache short-lived tokens by origin and signing key identifier. Such a cache must also account for expiration and key rotation. The key point is semantic: audience binding limits where a token should be accepted. It is not enough that both destinations use HTTPS or that the same user previously allowed notifications at the application level.
Expiry uses time, not a message counter
The exp claim indicates when the VAPID token expires, and RFC 8292 forbids an expiry more than twenty-four hours after the time of the request. This reduces the usefulness of a stolen token while permitting bounded reuse. The value is a JWT NumericDate, conventionally seconds since the Unix epoch. Engineers must not confuse seconds with milliseconds.
The token’s expiry is separate from the TTL of the push message. A message can ask a push service to retain delivery eligibility for a period while the authentication token that allowed the original request expires sooner. A client should not assume that because the stored message might still be pending, an expired VAPID token remains valid for new submissions.
A precise elapsed-time example
Suppose a service sends a request at 10:00 UTC and sets exp to 10:40 UTC. The maximum intended validity from submission is 40 minutes, or 2,400 seconds. This is within the RFC’s 24-hour ceiling of 86,400 seconds. Setting exp to 11:00 on the following day would make the interval 25 hours and would violate that maximum.
This toy clock exercise is intentionally independent of a real server’s current time. In production, compute timestamps from a trustworthy clock and allow for expected clock skew without extending the standard’s maximum lifespan. Log safe metadata such as key identifier and relative age, not full bearer-like tokens. If a service rejects a token after its expiry, refresh the token rather than repeating an expired request indefinitely.
The optional contact claim is not a user identity
RFC 8292 permits a sub claim containing an application-server contact URI, usually mailto: or https:. This is meant to help the push-service operator contact the sending application operator. It does not need to contain the name or email address of the end user receiving notifications. Placing personal information into the token adds unnecessary exposure to intermediaries and logs.
An application may choose a monitored operational contact such as mailto:push-admin@example.org rather than a personal address. The contact does not determine which user should receive which event; that mapping belongs in the application server’s subscription and consent records. A client should not decide notification authorisation by reading a contact URI from the VAPID token.
How the HTTP Authorization header is structured
RFC 8292 defines a vapid authentication scheme whose t parameter contains the signed JWT and whose k parameter contains the associated public key in base64url representation. A request is conceptually accompanied by an Authorization header like vapid t=TOKEN,k=PUBLIC_KEY. Production code should let a standards-compliant library construct and encode these values rather than concatenating user-controlled strings into a header.
This header differs from sending an ordinary application login cookie to the push service. The push service verifies the VAPID token against the provided public key and the subscription’s restrictions where applicable. The public key in the header is not secret; security depends on signature verification and, for restricted subscriptions, matching the key bound when the subscription was created.
Unrestricted and restricted subscriptions are different
A subscription created without a binding to one application-server public key can have different abuse properties from a subscription restricted to a VAPID key. Under RFC 8292’s restricted-subscription mechanism, the user agent supplies an application-server public key during subscription creation. Requests to that subscription must then carry valid VAPID authentication with the corresponding key.
This restriction does not eliminate the need to protect the endpoint or authenticate the application server’s own users. It adds a push-service-level check: even if an attacker obtains a restricted endpoint URL, a request signed with some unrelated key should not satisfy the subscription restriction. Product teams should verify which restriction semantics their browser and push-service combination actually implements rather than assuming all endpoints behave identically.
A subscription is not consent to send anything forever
A user may consent to notifications about a particular class schedule or an important account event. That consent is not a blanket authorisation for an autonomous agent to send unlimited speculative recommendations, confidential records or marketing. Push permission is a browser-level capability; application-level rules should constrain message purpose, frequency, recipient and sensitive content separately.
Build a permission ledger identifying who enabled notifications, what categories were chosen, when those choices changed and which service identity may issue a send. When an agent proposes a message, a separate authorisation check should evaluate that ledger before retrieving a subscription endpoint. The cryptographic validity of a VAPID signature answers who holds the signing key; it does not answer whether this particular notification was appropriate.
Why VAPID signing and message encryption use different keys
VAPID authenticates the application server to the push service. Web Push payload encryption under RFC 8291 protects message content against inspection or modification by the intermediary push service. These are different security goals with distinct keying material. A receiver subscription commonly carries values needed for payload encryption, while the application server has its VAPID signing pair.
Do not treat a VAPID signature as if it encrypts a notification body. Likewise, the fact that a payload is encrypted does not prove the sending application was authorised for a restricted subscription. A secure deployment performs the right procedure for both purposes. Key-management documentation should name each key’s role explicitly so an engineer cannot accidentally reuse a signing key where an encryption-related key was expected.
The push service is not the final recipient
The intermediary push service can process delivery metadata and policy even when it cannot decrypt the application payload. It sees requests, timing, subscription resources and technical headers needed for routing. End-to-end payload encryption therefore reduces what the push service learns about message content but does not promise that all metadata are invisible. Frequency and destination patterns can still reveal operational facts.
A notification design should minimise sensitive information in payloads and avoid putting secrets in unencrypted URLs or metadata. For example, a school portal might send a neutral notice that a new message is available and require authenticated access to display details. That is an application choice rather than a new VAPID rule, but it reflects the separation between network delivery and business confidentiality.
RFC 8291 encryption is a distinct protocol
RFC 8291 describes how a Web Push application server encrypts data for a user agent using the relevant user-agent keying material. The specification applies encrypted content coding and defines how key agreement and authentication secrets participate. A push service forwards an encrypted payload without needing to learn its plaintext content. Intermediary TLS and payload encryption protect different portions of the route.
For an implementation review, trace each secret’s lifecycle: user-agent subscription keys, application-server ephemeral encryption keying material, authentication secrets and VAPID signing key. Make sure the key used to authenticate VAPID claims does not accidentally stand in for payload encryption inputs. The easiest test is to ask what each key is protecting and who legitimately possesses the corresponding private or secret material.
TTL controls delivery retention, not cryptographic identity
RFC 8030 defines a Time-To-Live for push delivery requests. A TTL communicates how long the push service may retain a message for delivery while a user agent is temporarily unavailable. It is not the expiration of a VAPID JWT and not necessarily the lifetime of the business event the notification describes.
If an attendance notice becomes irrelevant after ten minutes, an application can consider a TTL consistent with that relevance period. The correct duration also depends on product behaviour and push-service support. Sending a stale alert can be worse than dropping it. When an agent generates notifications, the application should determine the event’s freshness budget from the domain’s rules rather than giving every payload the same retention time.
Urgency is about delivery scheduling
Web Push includes delivery-related mechanisms such as urgency. An urgent security notice may warrant different timing from an ordinary informational update, but the requested urgency is not evidence that the content is actually critical. A sending agent could label every event urgent; a responsible application should reserve priority for events that meet objective criteria.
Define a mapping between event types and supported urgency levels, along with caps on high-priority traffic. Record the reason for each priority decision. If a push service rate-limits urgent traffic or devices defer some delivery, the application should maintain a trustworthy server-side record rather than relying on a phone notification as the only auditable event channel.
Topic replacement can prevent redundant notifications
RFC 8030 includes a mechanism for replacing pending push messages with the same topic at a push service. Where supported and appropriate, replacement is useful for updates where only the newest state matters. A timetable change repeatedly revised within a short period might be better represented by the latest pending notice than by a queue of obsolete messages.
Do not confuse replacement with exactly-once processing at the recipient. A previous message might already have been delivered before the replacement arrives, and client-side display code may still choose to show more than one notification. A product needs its own event identifiers and recipient-side deduplication where repeated processing would be harmful.
What a successful send response actually proves
When an application server sends a valid request to a push service, an HTTP success response establishes at most that the push service accepted the request under that transaction’s semantics. It does not establish that a device was online, that a service worker ran, that the intended person read the message or that a subsequent human action occurred.
Operational systems should distinguish submitted, accepted, delivered where independently observable, displayed where the application can observe it, and acknowledged by a user. Those states must not be collapsed into one field named success. For safety-critical workflows, use a separate authenticated acknowledgement or primary communication channel rather than assuming that Web Push acceptance is equivalent to completed communication.
The real challenge of asynchronous notification
Devices may sleep, become disconnected, revoke permission or uninstall an application. Subscriptions can expire or rotate. Push service policies and network errors can prevent delivery. These are normal system conditions, not proof that the cryptographic layer malfunctioned. A robust agent workflow should treat notifications as best-effort prompts with explicit state and recovery rules.
Keep the authoritative business event on the server and use push as a signal to retrieve it securely. If a student opens a portal after missing a notification, the correct information should still be there. This architecture avoids building correctness on a channel whose delivery timing is partly outside the application’s control.
Missing VAPID authentication and invalid VAPID authentication
For restricted subscriptions, RFC 8292 requires the push service to reject a delivery request lacking valid VAPID authentication. A missing token may produce a 401 response; an invalid one may produce 403. The specification describes these as possible codes rather than promising identical error bodies from all services. The application should interpret provider responses consistently with the normative restrictions.
The correct repair depends on the failure: a missing header needs a constructed token; an expired claim needs a fresh token; a wrong audience needs origin correction; a wrong signing key may require subscription migration. Blindly retrying the same invalid request with unchanged credentials usually wastes traffic. Classify authentication failures before running a bounded retry policy.
A valid signature with the wrong audience must still fail
Suppose an agent signs an otherwise correct ES256 token whose aud is https://push-a.example but sends it to an endpoint at https://push-b.example. Even if both services are trusted by the application and the signature verifies against the included public key, the audience claim is wrong for the second destination. The correct response is to refuse the token for that request.
Do not work around this by ignoring aud or broadening the token to an unrelated web application domain. The audience rule protects against presenting the same token at a different service origin. A controlled test should issue two tokens, one for each intended origin, and verify that each is accepted only where its claims and subscription restrictions are applicable.
A stale subscription is not a credential failure
When a recipient revokes permission or the user agent rotates subscriptions, the old endpoint may cease to exist. Some push services signal this with an appropriate terminal status, often including 404 or 410 depending on provider behaviour. Such a response does not necessarily mean the VAPID signing key is invalid; it may mean that a particular subscription resource is no longer usable.
The safe repair is to stop targeting that endpoint, mark the subscription inactive and request a fresh subscription through the user agent’s normal permission path if the person still wants notifications. Do not automatically try guessed endpoint variants or transfer a user’s previous consent to a new unapproved device.
Rate limits need bounded backoff
A push service can rate-limit an application’s submissions. If a response or provider documentation signals a temporary capacity problem, apply bounded exponential backoff and respect Retry-After when appropriate. An autonomous agent should not loop at maximum speed merely because a planned notification remains pending. That can amplify outages and harm the application’s standing with the service.
Record attempts per endpoint and per application identity. A practical queue may cap retries, apply jitter to spread load and route persistent failures to monitoring. The retry policy should also consider event freshness: an alert whose purpose expires in five minutes should not be resurrected an hour later because its retry counter has not reached the maximum.
A short numerical retry budget
Imagine a service allows at most three submission attempts for a routine event within a fifteen-minute validity window. The first is immediate, the second follows a one-minute backoff and the third follows a two-minute further backoff, assuming transient failures and no conflicting Retry-After instruction. The planned elapsed time to the third attempt is 0+1+2=3 minutes from the first submission.
This example is a product policy, not a mandate of RFC 8292. If a 403 reveals a wrong VAPID key, more attempts using that same key do not help. If a 410 marks the subscription invalid, the service should retire it without exhausting the transient retry budget. Separating permanent, authentication and transient errors prevents a simple queue from becoming a denial-of-service generator.
Retries can create duplicates
Network failures can leave a sender uncertain whether a request reached the push service before the connection was lost. If it retries, a recipient might receive more than one notification for the same logical event. VAPID proves application-server key possession, but the JWT is not an exactly-once business-event identifier and does not by itself prevent duplicate submissions.
Give each logical event a stable internal ID, record send attempts and teach the receiving application to handle duplicates safely where feasible. For a reminder, duplicate display may be merely annoying. For a workflow with sensitive actions, notification delivery should never be the operation that executes the action; the recipient should authenticate and confirm it against the authoritative server state.
The VAPID token itself can be replayed within its window
RFC 8292 notes that a valid token can be replayed if an attacker obtains it. HTTPS protects it in transit, and short expiration limits its potential reuse, but the scheme does not supply a distinct one-time proof for every send. A VAPID JWT should therefore be treated as security-sensitive even though its claims may look innocuous.
Reduce exposure by keeping tokens out of logs, traces and support messages, restricting who can invoke the signing service, using short practical lifetimes, and securing transport. If a stronger sender-level anti-replay property is required for a separate internal API, implement it there with appropriately scoped nonces, request IDs or transaction binding rather than pretending VAPID already supplies the feature.
A restricted subscription raises the stakes of key rotation
When a subscription is bound to one VAPID public key, changing the private signing key can invalidate the application’s ability to send to that subscription. RFC 8292 explains that a replacement key requires the user agent to create a new subscription restricted to the updated key. Rotating a secret in the server’s environment is not automatically enough to migrate every browser endpoint.
Plan rotation as a staged application procedure: identify affected subscriptions, deliver updated public-key configuration, obtain new subscriptions through supported user-agent behaviour, mark the replacements as active and retire old endpoints according to policy. Preserve user permission and communication continuity without silently overriding revoked consent. Emergency rotation may require accepting a temporary loss of push delivery while preserving security.
Separate server signing authority from agent planning
An autonomous workflow might inspect a timetable, decide that a lesson changed, and request a notification. It should not be handed the raw VAPID private key. Instead, the agent produces a structured proposal with event ID, recipient eligibility, purpose, urgency, TTL and expected content. A trusted delivery service validates that proposal and signs a push request only after its own policy checks.
This division limits how far a prompt-injection error can travel. If untrusted web content tells the agent to notify every subscriber, the service can reject requests outside the actor’s scope or daily quota. VAPID authenticates that trusted delivery service toward the push service; the delivery service still needs authenticated application identity, authorisation and audit trails inward.
Consent and recipient routing are independent
Suppose a parent has two devices and one notification category enabled. The application may have two valid endpoints for the same account, but it must decide whether a message should go to both or only one. That decision depends on the person’s settings, device validity, content sensitivity and application policy, not on the cryptographic validity of a single VAPID token.
Avoid mapping a device endpoint to an account solely by a value supplied by the requesting agent. Resolve recipients from authoritative application records and evaluate consent at send time. If an account changes ownership or a person logs out of a shared device, the subscription’s relationship to that user may need to be removed. Cryptographic key binding does not repair stale account associations.
An illustrative three-user push workflow
Consider an educational portal with three consenting recipients: one parent, one student and one tutor. The parent and tutor each have one active subscription; the student has two devices, giving four endpoints in total. An agent identifies a legitimate event that the three accounts may receive. A trusted service resolves four endpoints, checks that the event category is allowed for each account and prepares four individually encrypted push payloads.
Suppose the endpoints are split across two push-service origins, with three endpoints at service A and one at service B. The application needs VAPID tokens addressed to each appropriate origin, potentially reusing one correctly scoped token across multiple endpoints at the same origin before it expires. It should not send one token signed for A to service B. These counts are illustrative engineering arithmetic, not observed usage figures.
A denominator check for endpoint outcomes
From the four-endpoint example, imagine three push requests are accepted and one is rejected because the subscription is expired. The observed acceptance fraction for this artificial batch is 3 accepted / 4 attempted endpoints=75%. The recipient-level acceptance metric is different: if the student’s two devices include the rejected one but another device succeeds, all three accounts have at least one accepted request.
Neither calculation proves that all three people read a message. A dashboard needs clear denominators: submissions, accepted endpoints, recipient accounts with at least one accepted endpoint, confirmed user acknowledgements and failed subscriptions. Mixing these categories can make a service appear more reliable than it is.
Why the user-agent public key is not a password
A VAPID public key is meant to be distributable; it allows a browser to restrict subscriptions to a sending application identity. Treating it as a hidden password confuses public-key cryptography with bearer secret authentication. A compromised public key string does not let someone forge valid signatures without the private key, assuming the signing algorithm is sound.
The corresponding private key, by contrast, is a secret and must be access-controlled. Encryption-related user-agent subscription material has a different job again. During an incident response, determine exactly which kind of key leaked before choosing a remedy. Public-key exposure, private-signing-key compromise, subscription endpoint disclosure and payload-key compromise have different effects and recovery requirements.
Do not let endpoint URLs become arbitrary outbound destinations
A compromised or confused agent might supply a supposed subscription endpoint whose host is actually an internal metadata service or an attacker-controlled site. A backend that blindly POSTs to any supplied URL creates a server-side request forgery risk. Signed VAPID headers would not make that network destination safe.
Store endpoints obtained from validated user-agent subscription flows, associate them with approved origins and enforce outbound request policy. Reject private or loopback destinations and unexpected schemes or ports as appropriate for the application. Revalidate endpoints during processing, especially after redirects. A safe sender should not treat a string in an LLM output as a trusted routing instruction.
A changed-context transfer: two tenants share one sender
Imagine a platform that serves two independent organisations, Alpha and Beta. Each has approved users and Web Push subscriptions, but their notification data must remain separated. Both organisations might technically use the same push service origin and even a shared infrastructure signing key. Does one valid VAPID token establish that a request for a Beta recipient was authorised by Alpha’s agent?
No. The VAPID audience is the push-service origin, not a business-tenant identifier, and the signature identifies the application-server key. Application-level tenant controls must determine who can send to which stored endpoints. If the product chooses separate signing keys per tenant for isolation, that may aid operational separation, but consent and account-level authorisation remain necessary.
Transfer answer with a verifiable plan
A safe delivery request carries authenticated tenant identity, event ID, permitted notification type and authorised recipient references. The delivery service looks up endpoints constrained by the same tenant, checks recipient consent, constructs an encrypted payload, then signs a VAPID token for the actual push-service origin. It does not accept raw endpoint URLs or recipient IDs from a lower-trust agent without cross-checking.
To test this, create Alpha and Beta fixtures with two active endpoints each. An Alpha request directed at Beta’s endpoint must fail before any network send, yielding zero cross-tenant submissions out of the two prohibited cases. Separately, valid Alpha requests should pass the application policy and then face normal push-service checks. These are design tests; no measured deployment outcome is claimed.
An even harder transfer: rotating keys across both tenants
Suppose the organisations initially shared a VAPID signing key and now decide to separate keys. Each existing restricted subscription may be bound to the old public key. The platform cannot simply swap the key in an environment variable and assume the same endpoints will accept messages from both new keys. Subscription restriction must be handled through user-agent resubscription as required.
A migration ledger should track old-key subscriptions, newly bound endpoints, consent state and safe cutover. Use a stable account identity to associate replacements correctly while avoiding unnecessary retention of obsolete endpoints. If a device stays offline throughout the migration, the system should degrade gracefully and show the same important event when the user next authenticates through the portal.
Diagnostic: a correct signature still yields 403
Start by checking claims and binding. Is aud precisely the push-service origin for this endpoint? Is exp valid and no more than twenty-four hours after the request? Is the signature ES256 and verifiable against the included public key? Does that public key match a restricted subscription’s bound key? Are any headers malformed? A cryptographic library returning true for signature verification answers only one of these questions.
Repair the particular failed invariant and avoid logging complete tokens. If the subscription was created under a different VAPID public key, token refresh alone will not solve the mismatch. If all claims are correct but the provider rejects the request, consult the service’s documented constraints rather than weakening audience validation or signature checking.
Diagnostic: requests are accepted but nobody sees notices
Inspect the delivery chain beyond VAPID. The push service may have accepted the request while the user agent is offline, permission is revoked, message TTL is too short, payload decryption fails, or service-worker handling is broken. A status at the first network boundary should not be interpreted as a status at the last human boundary.
Check subscription freshness, permission state, encryption inputs, payload size, service-worker event handling and browser platform restrictions. Keep test event IDs that can be correlated across controlled logs without disclosing private payloads. If a human acknowledgement is required, design one explicitly through an authenticated app interaction.
Diagnostic: the same alert appears repeatedly
Duplicates can arise from at-least-once processing in an internal queue, ambiguous network failures, provider retries or a browser displaying both automatic and application-managed notices. The signed VAPID token is not a deduplication key and has no single-event identity semantics.
Use a stable business event ID, track send decisions and apply idempotent downstream handling where possible. Suppress repeats according to an event-type-specific policy rather than globally hiding all similar text. For changed information, determine whether replacing a pending topic message is suitable; for a safety notice, ensure that deduplication does not accidentally suppress a genuinely new event.
Diagnostic: one provider works and another fails
A common cause is a VAPID aud claim derived from the application’s website or from the first endpoint, then reused against another push-service origin. Another is a provider-specific subscription restriction or header-format expectation. Begin with a separate origin and signing trace for each destination and compare against RFC requirements.
A sound architecture groups endpoints by approved push-service origin, obtains a suitable token per group and sends each request with the correct endpoint and encrypted payload. It does not assume all push services use identical URLs or error formats. Cross-provider tests should include an intentionally wrong audience and an expired token to confirm rejection.
Diagnostic: key rotation breaks only old devices
If recently created subscriptions work but older restricted ones fail after a signing-key change, the old endpoints may still be tied to the retired public key. The chronology is informative: new devices obtained subscriptions under the new key, while dormant devices never completed migration.
Do not restore the compromised old private key merely to hide the symptom. Ask affected clients to obtain new subscriptions under the authorised key when they reconnect. Track migration progress with aggregate metrics and preserve unrelated permission settings. A correct rotation plan may temporarily leave some offline devices unreachable via push, which should be reflected in reliability reporting.
A practical diagnostic matrix for operators
A 401-class authentication failure on a restricted subscription suggests missing authentication; a 403-class failure can involve invalid signatures, audience, expiry or key binding. A terminal endpoint-invalid response suggests resubscription. A temporary service-capacity response suggests bounded backoff. Accepted requests without a human-visible result suggest investigating the downstream delivery and display path.
These are decision aids, not a universal table of fixed provider responses. Code should preserve safe diagnostic reason categories, avoid infinite retries, and retain the business event independently of notification delivery. Operators should measure how often each category occurs and whether repairs restore a valid path without weakening verification.
Privacy-safe monitoring without hoarding tokens
Operational metrics can include counts of attempted endpoints, accepted submissions, invalid subscriptions, provider-origin mismatches, authentication failures, transient retries and time to recipient acknowledgement where independently available. Aggregate by consented notification type or tenant without exposing raw subscription URLs or VAPID tokens to general dashboards.
Keep only the identifiers and retention periods necessary for debugging and compliance. When a support engineer needs evidence, provide a redacted request trace and a correlation ID rather than a complete credential-bearing header. Data minimisation matters because logs often cross more organisational boundaries than the encrypted notification payload itself.
A small test harness before public rollout
Generate a test VAPID key pair using an audited library. Create a controlled subscription through a supported user-agent flow and register its approved endpoint. Test a correctly signed request with the right audience and acceptable expiry. Then deliberately introduce one error at a time: wrong audience, expired token, malformed key, unrelated signer and an endpoint whose subscription binding does not match.
For every test, record the intended rejection or acceptance and whether the provider actually delivered an event to the test user agent. Run a separate payload-decryption and service-worker test, since neither is validated by VAPID signature checks alone. Finally, exercise consent withdrawal and subscription rotation, verifying that previously approved automation can no longer send after the authoritative permission is withdrawn.
What the standard does not promise
VAPID does not prove that an AI agent is competent, safe, honest or superintelligent. It does not encode the reasons a business event should be sent, guarantee that a notification will reach an offline device, provide exactly-once semantics, or establish whether the recipient read the content. It also does not encrypt message payloads on its own. These claims belong to separate layers or require actual measurement.
For application-security decisions, make every claimed guarantee traceable to its layer: identity through signed tokens and key binding; payload secrecy through Web Push encryption; endpoint eligibility through consent and application policy; delivery through the push service’s actual behaviour; human acknowledgement through authenticated application interaction. Confusing these boundaries creates unsafe expectations.
Primary standards and useful connected reading
The central standard is RFC 8292, Voluntary Application Server Identification for Web Push. Read its sections on token claims, the vapid authentication scheme, restricted subscriptions and security considerations. RFC 8030 explains generic event delivery, subscription resources, TTL and reliability limitations. RFC 8291 explains payload encryption and why the intermediary need not read notification content.
For other authenticated delivery and event patterns, see eduKate’s WebSub subscriptions and signed delivery discussion and the How Superintelligence Works hub. WebSub’s callback verification and Web Push’s user-agent subscription are distinct mechanisms; their operational comparisons help readers select the right delivery model rather than blurring protocols.
The security boundary to remember
A VAPID JWT is a bounded assertion by an application-server key holder, presented to one push-service origin. A restricted subscription can require that same key. This is valuable for accountability and for resisting misuse of disclosed subscription endpoints, but the signature is only one checkpoint along the delivery route. The application must still protect its signing key, honour recipient consent, encrypt payloads and control what agents may request.
A reliable agent system therefore makes notification delivery a policy-checked service action, not an unconstrained tool call. Identify the event, select recipients from authorised records, validate freshness, sign for the correct audience, send with appropriate retries, and record an outcome whose meaning is not exaggerated. That is concrete engineering of trustworthy automation, without claims that artificial superintelligence currently exists.