webpush
webpush copied to clipboard
How to handle Net::HTTPBadRequest 400 InvalidTokenFormat?
From time to time we're getting this error:
vendor/bundle/ruby/2.4.0/gems/webpush-0.3.4/lib/webpush/request.rb:39:in `perform': host: fcm.googleapis.com, #<Net::HTTPBadRequest 400 InvalidTokenFormat readbody=true>
body:
<HTML>
<HEAD>
<TITLE>InvalidTokenFormat</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>InvalidTokenFormat</H1>
<H2>Error 400</H2>
</BODY>
</HTML>
(Webpush::ResponseError)
from vendor/bundle/ruby/2.4.0/gems/webpush-0.3.4/lib/webpush.rb:42:in `payload_send'
Any reason why this isn't handled as Webpush::InvalidSubscription
by the gem?
Seems like this could be added pretty easily: https://github.com/zaru/webpush/blob/f380b7666dcb24d757a81d6354c654d7a140163f/lib/webpush/request.rb#L29-L40
Maybe it was not a known error/response code before now?
Does InvalidTokenFormat
refers to the token in the endpoint URL? Can you try to reproduce that by changing a character inside the endpoint?
If this is the case I agree that Webpush::InvalidSubscription
is the right exception.
I did change some parts on p256dh
& endpoint
. On endpoint
I was able to reproduce two exceptions: Net::HTTPBadRequest 400
& Webpush::Unauthorized
, whereas wrong p256dh
gave OpenSSL::PKey::EC::Point::Error
for reason & invalid encoding
.
@Rubioli thanks for the information, however can you be more specific?
-
Net::HTTPBadRequest 400
: this is never raised directly... You will see aWebpush::ResponseError
, which is the best that we can do with just the status code (400). In order to raise something specific likeWebpush::InvalidSubscription
we need also a specific status name... what is the name near 400? A generalBad Request
or something specific? -
Webpush::Unauthorized
is already a specific exception and this cannot be further improved - "
OpenSSL::PKey::EC::Point::Error
for reason &invalid encoding
": can you report the exact / full exceptions that you get in this case? Also with the stack trace
I have spent some time investigating these issues, here's my results:
ID | Test | Push Service Response | Ruby Exception |
---|---|---|---|
1 | Add a letter inside token (Chrome) | 400 UnauthorizedRegistration | Webpush::Unauthorized |
2 | Add a letter inside token (Firefox) | 404 | Webpush::InvalidSubscription |
3 | Use an invalid URL for the endpoint | URI::InvalidURIError |
|
4 | Add a letter to p256dh | OpenSSL::PKey::EC::Point::Error lib/webpush/encryption.rb:17:in `initialize' |
|
5 | Add a letter to auth | ArgumentError: invalid base64 lib/webpush.rb:66:in `decode64' |
|
6 | Wrong p256dh / auth, but formally valid | 201 | |
7 | Use a completely wrong token (Chrome) | 400 InvalidTokenFormat | Webpush::ResponseError |
1-2: FCM and Autopush have slightly different behaviors and this library reflects that properly. FCM doesn't even check if the endpoint exists when the VAPID key is not associated to that endpoint, and thus returns an authentication failure. Autopush on the other hand first check if the endpoint exists, and thus returns 404.
3-4-5: This library lets the specific Ruby errors propagate. For me this is ok. However if someone believes that we should wrap those errors into a more general exception (e.g. Webpush::BadSubscription
), then we should create a separate issue for that.
6: This is absolutely correct. The client will fail to decrypt payload, but no error is raised because everything seems correct from server-side (you can't do anything to prevent that).
7: I agree that we can catch that specific 400 InvalidTokenFormat
and return Webpush::InvalidSubscription
. You can reproduce this using the endpoint https://fcm.googleapis.com/fcm/send/abc
.