webpush 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +43 -15
- data/lib/webpush.rb +14 -0
- data/lib/webpush/encryption.rb +2 -2
- data/lib/webpush/request.rb +1 -1
- data/lib/webpush/vapid_key.rb +3 -3
- data/lib/webpush/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18e5c11503abaf7212ca277dd336ae64dfede00f
|
4
|
+
data.tar.gz: 10fc83dcbc3f7deb76c1a53e76e031b68aac989c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8a099a95fc658ccc3fa5c84b75e142c65e5b0f34f81c78955c1116b4b6f6c8f83d961c288cacf90b40a7fe0aa6902a235e01af2d3d4f8352b94e97e66f32feb
|
7
|
+
data.tar.gz: e468dd4c140e9e925979e20d27add5c1c74d5e6c49ecbf6ac24260147fc0ceb2a92ec636e6d6905a45fca801851620b5328992c52dca0faaf2a89e833ace9d62
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -30,7 +30,7 @@ Sending a web push message to a visitor of your website requires a number of ste
|
|
30
30
|
|
31
31
|
1. Your server has (optionally) generated (one-time) a set of [Voluntary Application server Identification (VAPID)](https://tools.ietf.org/html/draft-ietf-webpush-vapid-01) keys.
|
32
32
|
2. To send messages through Chrome, you have registered your site through the [Google Developer Console](https://console.developers.google.com/) and have obtained a GCM sender id. For using Google's deprecated GCM protocol instead of VAPID, a separate GCM API key from your app settings would also be necessary.
|
33
|
-
3. A
|
33
|
+
3. A `manifest.json` file, linked from your user's page, identifies your app settings, including the GCM sender ID.
|
34
34
|
5. Also in the user's web browser, a `serviceWorker` is installed and activated and its `pushManager` property is subscribed to push events with your VAPID public key, with creates a `subscription` JSON object on the client side.
|
35
35
|
6. Your server uses the `webpush` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
|
36
36
|
7. Your service worker is set up to receive `'push'` events. To trigger a desktop notification, the user has accepted the prompt to receive notifications from your site.
|
@@ -75,9 +75,9 @@ Your application javascript must register a service worker script at an appropri
|
|
75
75
|
// Register the serviceWorker script at /serviceworker.js from your server if supported
|
76
76
|
if (navigator.serviceWorker) {
|
77
77
|
navigator.serviceWorker.register('/serviceworker.js')
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
.then(function(reg) {
|
79
|
+
console.log('Service worker change, registered the service worker');
|
80
|
+
});
|
81
81
|
}
|
82
82
|
// Otherwise, no push notifications :(
|
83
83
|
else {
|
@@ -87,13 +87,15 @@ else {
|
|
87
87
|
|
88
88
|
### Subscribing to push notifications
|
89
89
|
|
90
|
+
#### With VAPID
|
91
|
+
|
90
92
|
The VAPID public key you generated earlier is made available to the client as a `UInt8Array`. To do this, one way would be to expose the urlsafe-decoded bytes from Ruby to JavaScript when rendering the HTML template. (Global variables used here for simplicity).
|
91
93
|
|
92
94
|
```javascript
|
93
95
|
window.vapidPublicKey = new Uint8Array(<%= Base64.urlsafe_decode64(ENV['VAPID_PUBLIC_KEY']).bytes %>);
|
94
96
|
```
|
95
97
|
|
96
|
-
Your application javascript
|
98
|
+
Your application javascript uses the `navigator.serviceWorker.pushManager` to subscribe to push notifications, passing the VAPID public key to the subscription settings.
|
97
99
|
|
98
100
|
```javascript
|
99
101
|
// application.js
|
@@ -108,9 +110,21 @@ navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
|
108
110
|
});
|
109
111
|
```
|
110
112
|
|
111
|
-
|
112
|
-
|
113
|
-
`pushManager.subscribe` call.
|
113
|
+
#### Without VAPID
|
114
|
+
|
115
|
+
If you will not be sending VAPID details, then there is no need generate VAPID keys, and the `applicationServerKey` parameter may be omitted from the `pushManager.subscribe` call.
|
116
|
+
|
117
|
+
```javascript
|
118
|
+
// application.js
|
119
|
+
// When serviceWorker is supported, installed, and activated,
|
120
|
+
// subscribe the pushManager property with the vapidPublicKey
|
121
|
+
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
122
|
+
serviceWorkerRegistration.pushManager
|
123
|
+
.subscribe({
|
124
|
+
userVisibleOnly: true
|
125
|
+
});
|
126
|
+
});
|
127
|
+
```
|
114
128
|
|
115
129
|
### Triggering a web push notification
|
116
130
|
|
@@ -156,7 +170,7 @@ generated without the `applicationServerKey` parameter described earlier.
|
|
156
170
|
|
157
171
|
### Receiving the push event
|
158
172
|
|
159
|
-
Your `/serviceworker.js` script
|
173
|
+
Your `/serviceworker.js` script may respond to `'push'` events. One action it can take is to trigger desktop notifications by calling `showNotification` on the `registration` property.
|
160
174
|
|
161
175
|
```javascript
|
162
176
|
// serviceworker.js
|
@@ -222,11 +236,6 @@ Webpush.payload_send(
|
|
222
236
|
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
223
237
|
auth: "aW1hcmthcmFpa3V6ZQ==",
|
224
238
|
ttl: 600 #optional, ttl in seconds, defaults to 2419200 (4 weeks),
|
225
|
-
vapid: {
|
226
|
-
subject: "mailto:sender@example.com",
|
227
|
-
public_key: ENV['VAPID_PUBLIC_KEY'],
|
228
|
-
private_key: ENV['VAPID_PRIVATE_KEY']
|
229
|
-
}
|
230
239
|
)
|
231
240
|
```
|
232
241
|
|
@@ -235,10 +244,29 @@ Webpush.payload_send(
|
|
235
244
|
```ruby
|
236
245
|
Webpush.payload_send(
|
237
246
|
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
238
|
-
|
247
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
248
|
+
auth: "aW1hcmthcmFpa3V6ZQ=="
|
239
249
|
)
|
240
250
|
```
|
241
251
|
|
252
|
+
### With VAPID
|
253
|
+
|
254
|
+
VAPID details are given as a hash with `:subject`, `:public_key`, and
|
255
|
+
`:private_key`. The `:subject` is a contact URI for the application server as either a "mailto:" or an "https:" address. The `:public_key` and `:private_key` should be passed as the base64-encoded values generated with `Webpush.generate_key`.
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
Webpush.payload_send(
|
259
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
260
|
+
message: "A message",
|
261
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
262
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
263
|
+
vapid: {
|
264
|
+
subject: "mailto:sender@example.com"
|
265
|
+
public_key: ENV['VAPID_PUBLIC_KEY'],
|
266
|
+
private_key: ENV['VAPID_PRIVATE_KEY']
|
267
|
+
}
|
268
|
+
)
|
269
|
+
|
242
270
|
### ServiceWorker sample
|
243
271
|
|
244
272
|
see. https://github.com/zaru/web-push-sample
|
data/lib/webpush.rb
CHANGED
@@ -47,5 +47,19 @@ module Webpush
|
|
47
47
|
def generate_key
|
48
48
|
VapidKey.new
|
49
49
|
end
|
50
|
+
|
51
|
+
def encode64(bytes)
|
52
|
+
Base64.urlsafe_encode64(bytes)
|
53
|
+
end
|
54
|
+
|
55
|
+
def decode64(str)
|
56
|
+
# For Ruby < 2.3, Base64.urlsafe_decode64 strict decodes and will raise errors if encoded value is not properly padded
|
57
|
+
# Implementation: http://ruby-doc.org/stdlib-2.3.0/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_decode64
|
58
|
+
if !str.end_with?("=") && str.length % 4 != 0
|
59
|
+
str = str.ljust((str.length + 3) & ~3, "=")
|
60
|
+
end
|
61
|
+
|
62
|
+
Base64.urlsafe_decode64(str)
|
63
|
+
end
|
50
64
|
end
|
51
65
|
end
|
data/lib/webpush/encryption.rb
CHANGED
@@ -13,12 +13,12 @@ module Webpush
|
|
13
13
|
server_public_key_bn = server.public_key.to_bn
|
14
14
|
|
15
15
|
group = OpenSSL::PKey::EC::Group.new(group_name)
|
16
|
-
client_public_key_bn = OpenSSL::BN.new(
|
16
|
+
client_public_key_bn = OpenSSL::BN.new(Webpush.decode64(p256dh), 2)
|
17
17
|
client_public_key = OpenSSL::PKey::EC::Point.new(group, client_public_key_bn)
|
18
18
|
|
19
19
|
shared_secret = server.dh_compute_key(client_public_key)
|
20
20
|
|
21
|
-
client_auth_token =
|
21
|
+
client_auth_token = Webpush.decode64(auth)
|
22
22
|
|
23
23
|
prk = HKDF.new(shared_secret, salt: client_auth_token, algorithm: 'SHA256', info: "Content-Encoding: auth\0").next_bytes(32)
|
24
24
|
|
data/lib/webpush/request.rb
CHANGED
data/lib/webpush/vapid_key.rb
CHANGED
@@ -30,7 +30,7 @@ module Webpush
|
|
30
30
|
# Convenience
|
31
31
|
# @return base64 urlsafe-encoded binary representaion of 32-byte VAPID private key
|
32
32
|
def private_key
|
33
|
-
|
33
|
+
Webpush.encode64(curve.private_key.to_s(2))
|
34
34
|
end
|
35
35
|
|
36
36
|
def public_key=(key)
|
@@ -61,11 +61,11 @@ module Webpush
|
|
61
61
|
private
|
62
62
|
|
63
63
|
def to_big_num(key)
|
64
|
-
OpenSSL::BN.new(
|
64
|
+
OpenSSL::BN.new(Webpush.decode64(key), 2)
|
65
65
|
end
|
66
66
|
|
67
67
|
def encode64(bin)
|
68
|
-
|
68
|
+
Webpush.encode64(bin)
|
69
69
|
end
|
70
70
|
|
71
71
|
def trim_encode64(bin)
|
data/lib/webpush/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webpush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zaru@sakuraba
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hkdf
|