Skip to content

Chromium aesgcm/aes128gcm pushes are always refused with HTTP 400 #225

@stephanfuhrmanngesundde

Description

When using up-to-date Chromium browsers, endpoint URLs like https://jmt17.google.com/fcm/send/... return a HTTP 400 error.
Chrome and Edge use different webpush servers/endpoints are all ok.

Requests look like this:

POST https://jmt17.google.com/fcm/send/... Accept-Encoding: aesgcm,deflate,gzip,x-gzip Authorization: ... Content-Encoding: aesgcm Content-Type: application/octet-stream Crypto-Key: dh=...;p256ecdsa=... Encryption: salt=... Topic: ... TTL: 2592000 Urgency: normal User-Agent: ... 

The responses look like this:

HTTP/1.1 400 Bad Request Content-Security-Policy-Report-Only: script-src 'none'; form-action 'none'; frame-src 'none'; report-uri https://csp.withgoogle.com/csp/goa-520bfc14_2 Content-Type: text/plain; charset=utf-8 Cross-Origin-Opener-Policy: same-origin, Vary: Sec-Fetch-Site, Vary: Sec-Fetch-Mode, Vary: Sec-Fetch-Dest X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN, X-Xss-Protection: 0 Date: Wed, 16 Jul 2025 09:32:23 GMT, Content-Length: 13 Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 bad request. 

Unfortunately it's not telling much about the background.

When I'm removing both the Crypto-Key and the Encryption headers, I get from jmt17.google.com this info:

HTTP/1.1 403 Forbidden Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 Content-Length: 182 Content-Security-Policy-Report-Only: script-src 'none'; form-action 'none'; frame-src 'none'; report-uri https://csp.withgoogle.com/csp/goa-520bfc14_2 Content-Type: text/plain; charset=utf-8 Cross-Origin-Opener-Policy: same-origin Date: Wed, 16 Jul 2025 09:44:24 GMT Vary: Sec-Fetch-Site,Sec-Fetch-Mode,Sec-Fetch-Dest X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Xss-Protection: 0 permission denied: crypto-key header had no public application server key specified. crypto-key header should have the following format: p256ecdsa=base64(publicApplicationServerKey) 

The webpush demo website https://simple-push-demo.vercel.app/ is actually working with a request like this (no headers besides Authorization needed for aes128gcm:

curl \ "https://jmt17.google.com/fcm/send/..." \ --request POST \ --header "TTL: 60" \ --header "Content-Encoding: aes128gcm" \ --header "Authorization: vapid t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ptdDE3Lmdvb2dsZS5jb20iLCJleHAiOjE3NTI3MDM2MjQsInN1YiI6Im1haWx0bzpzaW1wbGUtcHVzaC1kZW1vQGdhdW50ZmFjZS5jby51ayJ9.t-B41LwJf5jab99aWu-TwKC9cdi5aJwJHj5dTVpGxCUPDzAJsunjHHgdwAxzG4_6HEXK_UwEzmlCyiAwmBJHSg, k=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo" \ --data-binary @payload.bin 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions