sherclockholmes / webpush-go Goto Github PK
View Code? Open in Web Editor NEWWeb Push API Encryption with VAPID support.
License: MIT License
Web Push API Encryption with VAPID support.
License: MIT License
Hi @SherClockHolmes ,
is there a simple demo available with client side javascript code?
I have js code optimized for web-push-php, but there a some differences (post content handling).
Hiya,
I've been looking to move the old GoogleChrome repo to web-push-libs org, but at the moment it's in a fairly sorry state of affairs and I suspect this library is much further along in terms of web-push support.
Would you be willing to move this repo into web-push-libs? The idea behind the org is to try and get good coverage of web-push in various languages. You'd still be the owner, it would just be easier for people to discover your repo.
On a side note, I'd love to add some integration tests, my Go is pretty poor, but I have some rough tests working in the integration tests branch here. It still needs some work, but it's essentially using web-push-testing-service to manage the browser set-up. If you are open to a PR for this on your repo, please let me know.
Cheers,
Matt
I tried to generate the key with the GenerateVAPIDKeys()
function. When subscribing the error applicationServerKey is not valid
showed up. I managed to get it working but with a public key of length 88 chars. The generated from the GenerateVAPIDKeys
is only 44.
Hi,
it might not be directly related to this library, but since yesterday we are getting HTTP 406 responses from nearly all Edge subscriptions.
Did anyone experience something similar?
Basically, the same as this old issue.
firefox and chrome works fine, but for edge, i get 406 error
When I inspect the header for the error response, I see these values
'x-wns-notificationstatus': 'appthrottled',
'x-wns-status': 'appthrottled',
Not sure why there is throttling involved...
Firstly, great work on this library, its working wonderfully for Chrome (Android/Desktop) and Firefox (Desktop), but I'm getting the following error when sending to Firefox on Android:
{"code": 413, "errno": 104, "error": "Payload Too Large", "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes", "message": "This message is intended for a constrained device and is limited to 3070 bytes. Converted buffer too long by 1366 bytes"}
I am using webpush-go over at https://gitlab.com/pennersr/shove -- thanks! One thing that I initially overlooked was the fact that SendNotification()
returns an http.Response
, for which the following holds:
If the returned error is nil, the Response will contain a non-nil Body which the user is expected to close. If the Body is not both read to EOF and closed, the Client's underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
The README/example contains this (it ignores the response):
// Send Notification
_, err := webpush.SendNotification(
So the fact that the caller is responsible for handling the caveat mentioned above is not very obvious.
Web push protocol dictates that a web push service must return a "201" status code to indicate a successful push.
At the moment the response is returned regardless of status code, should the library check the status code and throw if the response is invalid?
There is a CVE filed on github.com/dgrijalva/jwt-go. More details about the CVE-2020-26160 can be found on the link
This is can be resolved either by updating github.com/dgrijalva/jwt-go to >v3.2.0 or by using github.com/golang-jwt/jwt instead.
github.com/dgrijalva/jwt-go is no longer maintained and github.com/golang-jwt/jwt is the community maintained fork.
options.vapidPublicKey
is sent directly to getVAPIDAuthorizationHeader()
, but is never validated, so when not passing it, the Authorization header ends up with k=
. It would be useful if this returned an error.
I try this library but I got this error
Public key is not a valid point on the curve
when I use Node.js, it works but golang doesn't work
could you tell me what was wrong?
I've seen that there's been some chatter about this before but I didn't see my scenario mentioned specifically, so I wanted to raise this before I just fork and fix locally. I get my p256dh/auth with
p256dh = btoa(String.fromCharCode.apply(null, new Uint8Array(pushSubscription.getKey('p256dh'))));
auth = btoa(String.fromCharCode.apply(null, new Uint8Array(pushSubscription.getKey('auth'))));
and that gives me two values, the auth which is some alphanumeric chars ending in "==", and the p256dh which is alphanumeric chars plus "/" and "+", ending in "=". The auth decodes fine with the current code, the p56dh fails with "illegal base64 data at input byte 55" (which is the index of the first "/").
I would love to use the JSON.stringify
solution for collecting the keys but unfortunately I've been collecting keys the legacy way for a long time now, so I need to be able to support these.
Looking at
Line 205 in 84eef06
base64.URLEncoding
with base64.StdEncoding
, it works for me.Hi i'm getting this error in the example
Unmarshal Error: Public key is not a valid point on the curve
the script in the index.html has the public key in.
`function subscribe() {
navigator.serviceWorker.ready
.then(function(registration) {
const vapidPublicKey = 'BMj5tNfFHEwOW75bQUTHinmjhNZ6eDEveIsDjzRgM7YM8eWkU5CAQL69wFdgSWBHvB_N__X1QdN-LivIswOMtqQ';
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
});
})
.then(function(subscription) {
console.log(
JSON.stringify({
subscription: subscription,
})
);
})
.catch(err => console.error(err));
}`
In main.go file has the info in.
`const (
subscription = "test"
vapidPublicKey = "BMj5tNfFHEwOW75bQUTHinmjhNZ6eDEveIsDjzRgM7YM8eWkU5CAQL69wFdgSWBHvB_N__X1QdN-LivIswOMtqQ"
vapidPrivateKey = "QbHMh4l_RYWF76CZJ-q-FnKq5WvmTQph_xldpq1hdKk"
)
func main() {
// Decode subscription
s := &webpush.Subscription{}
json.Unmarshal([]byte(subscription), s)
// Send Notification
_, err := webpush.SendNotification([]byte("Test"), s, &webpush.Options{
Subscriber: "[email protected]", // Do not include "mailto:"
VAPIDPublicKey: vapidPublicKey,
VAPIDPrivateKey: vapidPrivateKey,
TTL: 30,
})
if err != nil {
log.Println(err)
}
}`
Any help would be appreciated, soory if this is a noob mistake.
Thanks
Using code from example and it works with chrome, but now with firefox.
webpush.SendNotification
dose not return any error. Program finish as if everything worked correctly.
Hi, is there a way to use fasthttp client with webpush-go package? I'm new to Go language, and reading source I can see that it has client option.
There is at least one case in the SendNotification function of webpush.go in which a nil error value may be returned in an error state:
// Shared secret
publicKeyX, publicKeyY := elliptic.Unmarshal(curve, clientPublicKey)
if publicKeyY == nil {
return &http.Response{}, err
}
A new error should be returned for this case; otherwise, the consuming project may incorrectly assume that the Response is valid.
Additionally, the comments from elliptic.Unmarshal indicate that the x value would be null in the case of an error, but this code is checking the y value. This may or may not be ok to do.
Wrong Subscription.Keys.Auth
value does not return an error
For example, if I were to append a random value to the Auth field as such,
sub := &webpush.Subscription{
Endpoint: endpoint,
Keys: webpush.Keys{
Auth: "my_auth" + "a",
P256dh: "my_p256dh",
},
}
I still get status code 201
when calling webpush.SendNotification()
, indicating that the request to send a push message was received and accepted
resp, err := webpush.SendNotification([]byte(message), sub, &webpush.Options{
Subscriber: "my_email",
VAPIDPublicKey: "my_public_key",
VAPIDPrivateKey: "my_private_key",
TTL: ttl,
})
fmt.Println(resp.Status, resp.StatusCode)
// "201 Created" 201
I tested this library on a different browsers and observed that firefox mobile is not able to handle a payload of standard 4KB size. To work around this problem, I disabled the padding in the source code. I would appreciate it if there was a way to turn off the padding option, for such cases.
When I use the default Options.TTL
of 0, the Windows Push Notification Service (WNS) rejects the request with status 400 and these headers:
X-Wns-Error-Description: Ttl value conflicts with X-WNS-Cache-Policy.
X-Wns-Notificationstatus: dropped
X-Wns-Status: dropped
This seems to be because webpush-go includes an explicit TTL: 0
header, which Microsoft interprets as "do not cache", but according to https://learn.microsoft.com/en-us/previous-versions/windows/apps/hh465435(v=win.10) the default X-WNS-Cache-Policy
is to enable caching, hence the conflict.
I was able to work around this by providing a non-zero TTL, but maybe this can be solved on library level by only setting the TTL header if the value isn't 0?
Hi
I'm experiencing this error while trying to send notifications
My private key has a "+" in the string and the input byte location points to this char. How can I get over this?
My public key also has a "+" in it. Same issue here as well
Any help appreciated
Thank you
Hi,
I wrote the below code that seems to work pretty well.
The frontend sends a subscription in the database, and then the backend gets it and sends a push.
I get a 200 status code, no errors but I don't receive any push.
I've tested the service-worker in my sveltekit app and the push handler works too (chrome > service worker > push payload)
sub := &webpush.Subscription{
Endpoint: pushSub.PushSubscription.Endpoint,
Keys: webpush.Keys{
P256dh: conf.PushVAPIDKeys.Public,
Auth: conf.PushVAPIDKeys.Private,
},
}
spew.Dump(sub)
// Send Notification
resp, err := webpush.SendNotification([]byte(push.Msg), sub, &webpush.Options{
Subscriber: push.FirstName,
VAPIDPublicKey: sub.Keys.P256dh,
VAPIDPrivateKey: sub.Keys.Auth,
TTL: 30,
})
if err != nil {
return fmt.Errorf("error_sending_notification %w", err)
}
defer resp.Body.Close()
I subscribed a fake user through Chrome and Firefox, and the subscriptions look like this:
(*webpush.Subscription)(0x140000b3ec0)({
Endpoint: (string) (len=234) "https://updates.push.services.mozilla.com/wpush/v2/XXX",
Keys: (webpush.Keys)
Auth: (string) (len=43) "awCf-XXX",
P256dh: (string) (len=87) "BC_Q-XXX"
}
})
(*webpush.Subscription)(0x140002bef00)({
Endpoint: (string) (len=188) "https://fcm.googleapis.com/fcm/send/XXX",
Keys: (webpush.Keys) {
Auth: (string) (len=43) "awCf-XXX",
P256dh: (string) (len=87) "BC_Q-XXX"
}
})
I feel like I'm missing something obvious...
Do I need to create a project for my application in FCM (Firebase Cloud Messaging) and provide some sort of credentials?
In some cases the panic occurred when called SendNotification
method.
go version go1.12.1 linux/amd64
also tried
go version go1.12.5 linux/amd64
runtime.gopanic
/usr/local/go/src/runtime/panic.go:522
runtime.panicmakeslicelen
/usr/local/go/src/runtime/slice.go:27
runtime.makeslice
/usr/local/go/src/runtime/slice.go:44
github.com/SherClockHolmes/webpush-go.pad
/home/danforth/Dev/go/pkg/mod/github.com/!sher!clock!holmes/[email protected]/webpush.go:250
github.com/SherClockHolmes/webpush-go.SendNotification
/home/danforth/Dev/go/pkg/mod/github.com/!sher!clock!holmes/[email protected]/webpush.go:169
It works for me to send push message to https://fcm.googleapis.com/fcm/send/
But if send to https://web.push.apple.com/
returns 403
{"reason":"BadJwtToken"}
Can you add tag prefix "v" on the most recent tags ?
I think it's required for Go modules.
See https://pkg.go.dev/github.com/SherClockHolmes/webpush-go?tab=versions
The recent versions are not detected.
At https://github.com/SherClockHolmes/webpush-go/blob/master/webpush.go#L186
the Content-Length
header is set to len(ciphertext)
.
This is the wrong value but it doesn't matter because somehow the net/http library
sets the value to the actual length of the actual content.
I discovered this because I had the same mistake and couldn't get my code to work after porting it to PHP, until I set the Content-Length
to recordSize
.
When I sent my request to my own server instead of to the notification endpoint, I discovered that the actual value of the Content-Length
header is different in Go vs. PHP.
I was setting the HTTPClient to provide a client that had a transport and client pool controlled by my code, and would pass this client into webpush.Options. Is there a reason this got lower-cased? Can a method be provided to override the transport? The problem later occurs in SendNotification:
// Send the request
if options.httpClient == nil {
options.httpClient = &http.Client{}
}
So now, every time a push is initiated a new client is created instead of taking an established client.
First off, thanks for this library.
RFC 8188 has been out for a while, and services will soon start deprecating the "aesgcm" encoding type. The differences aren't that much (the salt is included in the data prefix, and the nonce phrases changed to reflect the new content encoding schema).
Thanks!
I'm continuing to investigate this, but I'm having trouble sending push to subscriptions generated by Microsoft Edge - in the current implementation, Edge's push service responds (for a push integration that works for other browsers) with 411 (Length Required).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.