vonage 7.17.0 → 7.18.0

Sign up to get free protection for your applications and to get access to all the features.
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