vonage 7.17.0 → 7.18.0
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/README.md +101 -9
- data/lib/vonage/applications.rb +12 -4
- data/lib/vonage/jwt.rb +17 -0
- data/lib/vonage/meetings/rooms.rb +1 -1
- data/lib/vonage/meetings/sessions/list_response.rb +1 -1
- data/lib/vonage/messaging.rb +11 -0
- data/lib/vonage/signature.rb +5 -5
- data/lib/vonage/sms.rb +20 -0
- data/lib/vonage/version.rb +1 -1
- data/lib/vonage/voice.rb +11 -0
- data/vonage.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1efb8423ce5ccb2549f6f3d65ddc659ab8c28a965888372b06845911b3e598ff
|
4
|
+
data.tar.gz: 4bc50573bada4e41fa89bb63ea02633435426f482722caafd10a904ca7a6b3ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 296c28e8d4a3f469f938ee2b5cad316a6e3a08696fbce2d17b8afcc3abac5a6d135be9acdb589f3ca4ab73d3ff25d77d37d1457d774bc1149043c6684c0387a4
|
7
|
+
data.tar.gz: 2cea85e954c16bd217efad49454183a68aac48aabb4d995eb1db5376902ff1fe13e296867ffadea0695c8586b6bc06e953004894e35cb487701a8327073315ec
|
data/README.md
CHANGED
@@ -168,7 +168,7 @@ claims = {
|
|
168
168
|
token = Vonage::JWT.generate(claims)
|
169
169
|
|
170
170
|
client = Vonage::Client.new(token: token)
|
171
|
-
|
171
|
+
```
|
172
172
|
|
173
173
|
Documentation for the Vonage Ruby JWT generator gem can be found at
|
174
174
|
[https://www.rubydoc.info/github/nexmo/nexmo-jwt-ruby](https://www.rubydoc.info/github/nexmo/nexmo-jwt-ruby).
|
@@ -176,23 +176,115 @@ The documentation outlines all the possible parameters you can use to customize
|
|
176
176
|
|
177
177
|
## Webhook signatures
|
178
178
|
|
179
|
-
|
179
|
+
Certain Vonage APIs provide signed [webhooks](https://developer.vonage.com/en/getting-started/concepts/webhooks) as a means of verifying the origin of the webhooks. The exact signing mechanism varies depending on the API.
|
180
|
+
|
181
|
+
### Signature in Request Body
|
182
|
+
|
183
|
+
The [SMS API](https://developer.vonage.com/en/messaging/sms/overview) signs the webhook request using a hash digest. This is assigned to a `sig` parameter in the request body.
|
184
|
+
|
185
|
+
You can verify the webhook request using the `Vonage::SMS#verify_webhook_sig` method. As well as the **request params** from the received webhook, the method also needs access to the signature secret associated with the Vonage account (available from the [Vonage Dashboard](https://dashboard.nexmo.com/settings)), and the signature method used for signing (e.g. `sha512`), again this is based on thes setting in the Dashboard.
|
186
|
+
|
187
|
+
There are a few different ways of providing these values to the method:
|
188
|
+
|
189
|
+
1. Pass all values to the method invocation.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
client = Vonage::Client.new
|
193
|
+
|
194
|
+
client.sms.verify_webhook_sig(
|
195
|
+
webhook_params: params,
|
196
|
+
signature_secret: 'secret',
|
197
|
+
signature_method: 'sha512'
|
198
|
+
) # => returns true if the signature is valid, false otherwise
|
199
|
+
```
|
200
|
+
|
201
|
+
2. Set `signature_secret` and `signature_method` at `Client` instantiation.
|
202
|
+
|
203
|
+
```ruby
|
204
|
+
client = Vonage::Client.new(
|
205
|
+
signature_secret: 'secret',
|
206
|
+
signature_method: 'sha512'
|
207
|
+
)
|
208
|
+
|
209
|
+
client.sms.verify_webhook_sig(webhook_params: params) # => returns true if the signature is valid, false otherwise
|
210
|
+
```
|
211
|
+
|
212
|
+
3. Set `signature_secret` and `signature_method` on the `Config` object.
|
180
213
|
|
181
214
|
```ruby
|
182
215
|
client = Vonage::Client.new
|
183
216
|
client.config.signature_secret = 'secret'
|
184
217
|
client.config.signature_method = 'sha512'
|
185
218
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
219
|
+
client.sms.verify_webhook_sig(webhook_params: params) # => returns true if the signature is valid, false otherwise
|
220
|
+
```
|
221
|
+
|
222
|
+
4. Set `signature_secret` and `signature_method` as environment variables named `VONAGE_SIGNATURE_SECRET` and `VONAGE_SIGNATURE_METHOD`
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
client = Vonage::Client.new
|
226
|
+
|
227
|
+
client.sms.verify_webhook_sig(webhook_params: params) # => returns true if the signature is valid, false otherwise
|
228
|
+
```
|
229
|
+
|
230
|
+
**Note:** Webhook signing for the SMS API is not switched on by default. You'll need to contact support@vonage.com to enable message signing on your account.
|
231
|
+
|
232
|
+
### Signed JWT in Header
|
233
|
+
|
234
|
+
The [Voice API](https://developer.vonage.com/en/voice/voice-api/overview) and [Messages API](https://developer.vonage.com/en/messages/overview) both include an `Authorization` header in their webhook requests. The value of this header includes a JSON Web Token (JWT) signed using the Signature Secret associated with your Vonage account.
|
235
|
+
|
236
|
+
The `Vonage::Voice` and `Vonage::Messaging` classes both define a `verify_webhook_token` method which can be used to verify the JWT received in the webhook `Authorization` header.
|
237
|
+
|
238
|
+
To verify the JWT, you'll first need to extract it from the `Authorization` header. The header value will look something like the following:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1OTUyN" # remainder of token omitted for brevity
|
242
|
+
```
|
243
|
+
|
244
|
+
Note: we are only interested in the token itself, which comes *after* the word `Bearer` and the space.
|
245
|
+
|
246
|
+
Once you have extrated the token, you can pass it to the `verify_webhook_token` method in order to verify it.
|
247
|
+
|
248
|
+
The method also needs access to the the method also needs access to the signature secret associated with the Vonage account (available from the [Vonage Dashboard](https://dashboard.nexmo.com/settings)). There are a few different ways of providing this value to the method:
|
249
|
+
|
250
|
+
1. Pass all values to the method invocation.
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
client = Vonage::Client.new
|
254
|
+
|
255
|
+
client.voice.verify_webhook_token(
|
256
|
+
token: extracted_token,
|
257
|
+
signature_secret: 'secret'
|
258
|
+
) # => returns true if the token is valid, false otherwise
|
191
259
|
```
|
192
260
|
|
193
|
-
|
261
|
+
2. Set `signature_secret` at `Client` instantiation.
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
client = Vonage::Client.new(
|
265
|
+
signature_secret: 'secret'
|
266
|
+
)
|
194
267
|
|
195
|
-
|
268
|
+
client.voice.verify_webhook_token(token: extracted_token) # => returns true if the token is valid, false otherwise
|
269
|
+
```
|
270
|
+
|
271
|
+
3. Set `signature_secret` on the `Config` object.
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
client = Vonage::Client.new
|
275
|
+
client.config.signature_secret = 'secret'
|
276
|
+
client.config.signature_method = 'sha512'
|
277
|
+
|
278
|
+
client.voice.verify_webhook_token(token: extracted_token) # => returns true if the token is valid, false otherwise
|
279
|
+
```
|
280
|
+
|
281
|
+
4. Set `signature_secret` as an environment variable named `VONAGE_SIGNATURE_SECRET`
|
282
|
+
|
283
|
+
```ruby
|
284
|
+
client = Vonage::Client.new
|
285
|
+
|
286
|
+
client.voice.verify_webhook_token(token: extracted_token) # => returns true if the token is valid, false otherwise
|
287
|
+
```
|
196
288
|
|
197
289
|
## Pagination
|
198
290
|
|
data/lib/vonage/applications.rb
CHANGED
@@ -33,6 +33,8 @@ module Vonage
|
|
33
33
|
#
|
34
34
|
# response = client.applications.create(params)
|
35
35
|
#
|
36
|
+
# @param [Hash] params
|
37
|
+
#
|
36
38
|
# @option params [required, String] :name
|
37
39
|
# Application name.
|
38
40
|
#
|
@@ -44,7 +46,9 @@ module Vonage
|
|
44
46
|
# This contains the configuration for each product.
|
45
47
|
# This replaces the application `type` from version 1 of the Application API.
|
46
48
|
#
|
47
|
-
# @
|
49
|
+
# @option params [Hash] :privacy
|
50
|
+
# - **:improve_ai** (Boolean) If set to `true``, Vonage may store and use your content and data for the improvement
|
51
|
+
# of Vonage's AI based services and technologies.
|
48
52
|
#
|
49
53
|
# @return [Response]
|
50
54
|
#
|
@@ -73,7 +77,7 @@ module Vonage
|
|
73
77
|
# Set this to `false` to not auto-advance through all the pages in the record
|
74
78
|
# and collect all the data. The default is `true`.
|
75
79
|
# @param [Hash] params
|
76
|
-
#
|
80
|
+
#
|
77
81
|
# @return [ListResponse]
|
78
82
|
#
|
79
83
|
# @see https://developer.nexmo.com/api/application.v2#listApplication
|
@@ -109,6 +113,9 @@ module Vonage
|
|
109
113
|
# @example
|
110
114
|
# response = client.applications.update(id, answer_method: 'POST')
|
111
115
|
#
|
116
|
+
# @param [String] id
|
117
|
+
# @param [Hash] params
|
118
|
+
#
|
112
119
|
# @option params [required, String] :name
|
113
120
|
# Application name.
|
114
121
|
#
|
@@ -120,8 +127,9 @@ module Vonage
|
|
120
127
|
# This contains the configuration for each product.
|
121
128
|
# This replaces the application `type` from version 1 of the Application API.
|
122
129
|
#
|
123
|
-
# @
|
124
|
-
#
|
130
|
+
# @option params [Hash] :privacy
|
131
|
+
# - **:improve_ai** (Boolean) If set to `true``, Vonage may store and use your content and data for the improvement
|
132
|
+
# of Vonage's AI based services and technologies.
|
125
133
|
#
|
126
134
|
# @return [Response]
|
127
135
|
#
|
data/lib/vonage/jwt.rb
CHANGED
@@ -39,5 +39,22 @@ module Vonage
|
|
39
39
|
payload[:private_key] = private_key if private_key && !payload[:private_key]
|
40
40
|
@token = Vonage::JWTBuilder.new(payload).jwt.generate
|
41
41
|
end
|
42
|
+
|
43
|
+
# Validate a JSON Web Token from a Vonage Webhook.
|
44
|
+
#
|
45
|
+
# Certain Vonage APIs include a JWT signed with a user's account signature secret in
|
46
|
+
# the Authorization header of Webhook requests. This method can be used to verify that those requests originate
|
47
|
+
# from the Vonage API.
|
48
|
+
#
|
49
|
+
# @param [String, required] :token The JWT from the Webhook's Authorization header
|
50
|
+
# @param [String, required] :signature_secret The account signature secret
|
51
|
+
#
|
52
|
+
# @return [Boolean] true, if the JWT is verified, false otherwise
|
53
|
+
#
|
54
|
+
# @see https://developer.vonage.com/en/getting-started/concepts/webhooks#decoding-signed-webhooks
|
55
|
+
#
|
56
|
+
def self.verify_hs256_signature(token:, signature_secret:)
|
57
|
+
verify_signature(token, signature_secret, 'HS256')
|
58
|
+
end
|
42
59
|
end
|
43
60
|
end
|
@@ -89,7 +89,7 @@ module Vonage
|
|
89
89
|
# @param [optional, Hash] :ui_settings Provides options to customize the user interface
|
90
90
|
# @option :ui_settings [String] :language
|
91
91
|
# The desired language of the UI. The default is `en` (English).
|
92
|
-
# Must be one of: `
|
92
|
+
# Must be one of: `ar`, `pt-br`, `ca`, `zh-tw`, `zh-cn`, `en`, `fr`, `de`, `he`, `it`, `es`
|
93
93
|
#
|
94
94
|
# @return [Response]
|
95
95
|
#
|
data/lib/vonage/messaging.rb
CHANGED
@@ -25,5 +25,16 @@ module Vonage
|
|
25
25
|
def send(params)
|
26
26
|
request('/v1/messages', params: params, type: Post)
|
27
27
|
end
|
28
|
+
|
29
|
+
# Validate a JSON Web Token from a Messages API Webhook.
|
30
|
+
#
|
31
|
+
# @param [String, required] :token The JWT from the Webhook's Authorization header
|
32
|
+
# @param [String, optional] :signature_secret The account signature secret. Required, unless `signature_secret`
|
33
|
+
# is set in `Config`
|
34
|
+
#
|
35
|
+
# @return [Boolean] true, if the JWT is verified, false otherwise
|
36
|
+
def verify_webhook_token(token:, signature_secret: @config.signature_secret)
|
37
|
+
JWT.verify_hs256_signature(token: token, signature_secret: signature_secret)
|
38
|
+
end
|
28
39
|
end
|
29
40
|
end
|
data/lib/vonage/signature.rb
CHANGED
@@ -27,24 +27,24 @@ module Vonage
|
|
27
27
|
#
|
28
28
|
# @see https://developer.nexmo.com/concepts/guides/signing-messages
|
29
29
|
#
|
30
|
-
def check(params, signature_method: @config.signature_method)
|
30
|
+
def check(params, signature_secret: @config.signature_secret, signature_method: @config.signature_method)
|
31
31
|
params = params.dup
|
32
32
|
|
33
33
|
signature = params.delete('sig')
|
34
34
|
|
35
|
-
::JWT::Algos::Hmac::SecurityUtils.secure_compare(signature, digest(params, signature_method))
|
35
|
+
::JWT::Algos::Hmac::SecurityUtils.secure_compare(signature, digest(params, signature_secret, signature_method))
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
def digest(params, signature_method)
|
40
|
+
def digest(params, signature_secret, signature_method)
|
41
41
|
digest_string = params.sort.map { |k, v| "&#{k}=#{v.tr('&=', '_')}" }.join
|
42
42
|
|
43
43
|
case signature_method
|
44
44
|
when 'md5', 'sha1', 'sha256', 'sha512'
|
45
|
-
OpenSSL::HMAC.hexdigest(signature_method,
|
45
|
+
OpenSSL::HMAC.hexdigest(signature_method, signature_secret, digest_string).upcase
|
46
46
|
when 'md5hash'
|
47
|
-
Digest::MD5.hexdigest("#{digest_string}#{
|
47
|
+
Digest::MD5.hexdigest("#{digest_string}#{signature_secret}")
|
48
48
|
else
|
49
49
|
raise ArgumentError, "Unknown signature algorithm: #{signature_method}. Expected: md5hash, md5, sha1, sha256, or sha512."
|
50
50
|
end
|
data/lib/vonage/sms.rb
CHANGED
@@ -91,11 +91,31 @@ module Vonage
|
|
91
91
|
response
|
92
92
|
end
|
93
93
|
|
94
|
+
# Validate a Signature from an SMS API Webhook.
|
95
|
+
#
|
96
|
+
# @param [Hash, required] :webhook_params The parameters from the webhook request body
|
97
|
+
# @param [String, optional] :signature_secret The account signature secret. Required, unless `signature_secret`
|
98
|
+
# is set in `Config`
|
99
|
+
# @param [String, optional] :signature_method The account signature method. Required, unless `signature_method`
|
100
|
+
# is set in `Config`
|
101
|
+
#
|
102
|
+
# @return [Boolean] true, if the JWT is verified, false otherwise
|
103
|
+
def verify_webhook_sig(webhook_params:, signature_secret: @config.signature_secret, signature_method: @config.signature_method)
|
104
|
+
signature.check(webhook_params, signature_secret: signature_secret, signature_method: signature_method)
|
105
|
+
end
|
106
|
+
|
94
107
|
private
|
95
108
|
|
96
109
|
sig { params(text: String).returns(T::Boolean) }
|
97
110
|
def unicode?(text)
|
98
111
|
!Vonage::GSM7.encoded?(text)
|
99
112
|
end
|
113
|
+
|
114
|
+
# @return [Signature]
|
115
|
+
#
|
116
|
+
sig { returns(T.nilable(Vonage::Signature)) }
|
117
|
+
def signature
|
118
|
+
@signature ||= T.let(Signature.new(@config), T.nilable(Vonage::Signature))
|
119
|
+
end
|
100
120
|
end
|
101
121
|
end
|
data/lib/vonage/version.rb
CHANGED
data/lib/vonage/voice.rb
CHANGED
@@ -279,5 +279,16 @@ module Vonage
|
|
279
279
|
def dtmf
|
280
280
|
@dtmf ||= DTMF.new(@config)
|
281
281
|
end
|
282
|
+
|
283
|
+
# Validate a JSON Web Token from a Voice API Webhook.
|
284
|
+
#
|
285
|
+
# @param [String, required] :token The JWT from the Webhook's Authorization header
|
286
|
+
# @param [String, optional] :signature_secret The account signature secret. Required, unless `signature_secret`
|
287
|
+
# is set in `Config`
|
288
|
+
#
|
289
|
+
# @return [Boolean] true, if the JWT is verified, false otherwise
|
290
|
+
def verify_webhook_token(token:, signature_secret: @config.signature_secret)
|
291
|
+
JWT.verify_hs256_signature(token: token, signature_secret: signature_secret)
|
292
|
+
end
|
282
293
|
end
|
283
294
|
end
|
data/vonage.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = 'This is the Ruby Server SDK for Vonage APIs. To use it you\'ll need a Vonage account. Sign up for free at https://www.vonage.com'
|
13
13
|
s.files = Dir.glob('lib/**/*.rb') + %w(LICENSE.txt README.md vonage.gemspec)
|
14
14
|
s.required_ruby_version = '>= 2.5.0'
|
15
|
-
s.add_dependency('vonage-jwt', '~> 0.
|
15
|
+
s.add_dependency('vonage-jwt', '~> 0.2.0')
|
16
16
|
s.add_dependency('zeitwerk', '~> 2', '>= 2.2')
|
17
17
|
s.add_dependency('sorbet-runtime', '~> 0.5')
|
18
18
|
s.add_dependency('multipart-post', '~> 2.0')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vonage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vonage
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: vonage-jwt
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: zeitwerk
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|