Closed alexanderbeloiu closed 4 years ago
Short answer:
include a dict containing the schema and host for the endpoint as vapid_claims
e.g.
webpush(
subscription_info={
"endpoint": "https://example.com/v1/push...",
"keys": { ... }
},
data="mary had a little lamb",
vapid_claims={
"sub": "alex@example.org",
"aud": "https://example.com",
"exp": time.time()+300
},
vapid_private_key="..."
)
webpush()
tries to guess what vapid_claims.aud
should be from the subscription_info
, but it's best to be explicit. If you want to verify what the VAPID claims are, you can turn on the verbose
flag.
Longer answer:
Yeah, some push providers are like that. Technically, the VAPID header is optional and the only thing that's really Not Optional is the sub
field, but specifications have lots of words that can be hard to follow. (Sorry, that's not to you. Just a bit of general frustration.)
There are three components of the VAPID header:
1) sub
-> your email address as a URL (e.g. alexander@example.org or whatever)
2) aud
-> the Schema and Host of the push server you're talking to (e.g. if the push endpoint is https://example.com:8012/v1/push
the aud
would be https://example.com:8012/
3) exp
-> the UTC timestamp for when the VAPID header should expire. This one's tricky. A VAPID header can live for up to 24 hours, meaning you could reuse the same header for multiple messages. If you're not sending out thousands of messages a second, feel free to use something simple like time.time() + 300
everything except aud
is handled for you by the py_vapid
library, which pywebpush
calls. pywebpush
tries to figure out the aud
by looking in the subscription_info
if aud
isn't present. Often, it's just better to specify the values rather than use the "quick and easy" route.
If you don't mind, what is the WebPush Provider you're using? I'd like to know the various ones out there and the quirks they have.
Thanks! I use Google Cloud Messaging and Mozilla push as a WebPush Provider.
As this is the main result on Google for this error message, here is why this was happening "randomly" for me.
The dict
you are passing to the lib is completed as is by this library, and therefore if you’re just passing a dict from your settings, like:
webpush(
subscription_info=subscription,
data=json.dumps(payload),
vapid_private_key=settings.VAPID_PRIVATE_KEY,
vapid_claims=settings.VAPID_CLAIMS,
)
, in subsequent calls, the settings.VAPID_CLAIMS
will contain an aud
key already, and pywebpush
will not try to complete it. Depending on if this dict was overridden or not, the behaviour will differ and sometimes it will work.
For me, the fix was as simple as replacing the last line by:
vapid_claims=settings.VAPID_CLAIMS.copy()
.
(This is mentionned in the doc, and discussed in #130 )
When I send a notification from my server it says WebPushException: Push failed: 403 Forbidden Response body:aud claim in the token MUST include the origin of the push resource URL If I send it from pythonanywhere (a cloud hosting service) it works sometimes, and other times it has the error above.