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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e40765a9a9b5858befa5702b61359c79941b70075618dbd071f32e8798dbceb0
4
- data.tar.gz: 4c0b3a037b50b85507e3344e1455ede6dc59c75953466a1a060294f8e89f00e6
3
+ metadata.gz: 1efb8423ce5ccb2549f6f3d65ddc659ab8c28a965888372b06845911b3e598ff
4
+ data.tar.gz: 4bc50573bada4e41fa89bb63ea02633435426f482722caafd10a904ca7a6b3ea
5
5
  SHA512:
6
- metadata.gz: f2b8d8a22e65833b766f17433786188b9d1d504109128fcc1cffd0bcfd3b1648897054e14089ebf85713165c453cd12b7e74ea9c7cb59785e7e53de9fc9c8c61
7
- data.tar.gz: '08a5577b9121dee24869d6c32e1f9eb25dca5d09e071d69e5b115b6cab756ddccd296f16e7e446b3be6dc6e26055346b5eee2935ea64a784b7b5a77d45a7b1f6'
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
- To check webhook signatures you'll also need to specify the `signature_secret` option. For example:
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
- if client.signature.check(request.GET)
187
- # valid signature
188
- else
189
- # invalid signature
190
- end
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
- Alternatively you can set the `VONAGE_SIGNATURE_SECRET` environment variable.
261
+ 2. Set `signature_secret` at `Client` instantiation.
262
+
263
+ ```ruby
264
+ client = Vonage::Client.new(
265
+ signature_secret: 'secret'
266
+ )
194
267
 
195
- Note: you'll need to contact support@nexmo.com to enable message signing on your account.
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
 
@@ -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
- # @param [Hash] params
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
- # @param [String] id
124
- # @param [Hash] params
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: `en`, `fr`, `de`, `es`, `pt`, `ca`, `he`
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
  #
@@ -6,6 +6,6 @@ class Vonage::Meetings::Sessions::ListResponse < Vonage::Response
6
6
  def each
7
7
  return enum_for(:each) unless block_given?
8
8
 
9
- @entity._embedded.each { |item| yield item }
9
+ @entity._embedded.recordings.each { |item| yield item }
10
10
  end
11
11
  end
@@ -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
@@ -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, @config.signature_secret, digest_string).upcase
45
+ OpenSSL::HMAC.hexdigest(signature_method, signature_secret, digest_string).upcase
46
46
  when 'md5hash'
47
- Digest::MD5.hexdigest("#{digest_string}#{@config.signature_secret}")
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
@@ -1,5 +1,5 @@
1
1
  # typed: strong
2
2
 
3
3
  module Vonage
4
- VERSION = "7.17.0"
4
+ VERSION = "7.18.0"
5
5
  end
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.1.3')
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.17.0
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-10-23 00:00:00.000000000 Z
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.1.3
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.1.3
26
+ version: 0.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: zeitwerk
29
29
  requirement: !ruby/object:Gem::Requirement