urbanairship 9.2.0 → 9.3.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: d8a262b36f56dcbbe4cd38fb926cff9ec835900abf5cc5564d780c3ea655fc32
4
- data.tar.gz: 7ffe155e6edd97f0a8899401b3bdc68a83e7cfd46073cf430dd129116a235111
3
+ metadata.gz: 4eec597e4717d02b44f452c7d1d634402e5957d5fe9df6a9cf052e3bb30d9357
4
+ data.tar.gz: 14be54ad8f59edcaa4ce0bfead99249571aa0f6c81d766956886abe994482a5f
5
5
  SHA512:
6
- metadata.gz: 7d3aaef8a3b3dea1058a9062b84c183bd8a9d97466c4f308c200f39f691cd6f510951541e5584a0ba0359c1f41cb10a5773ce4ef21925e6b38d4e67da35f1073
7
- data.tar.gz: b93ed256288f1ec16f97fd3e8bd4b0eeae0c57a1070534302c2386deb8098131e70f55fc55396f34b0e20950c4170b6f0335d2a98b9d0c8301a047b641a4f3cd
6
+ metadata.gz: 01f091cd844d9dfc38ea6104d4a37aef5afabff3b7ee5bc9c3fc479c492a8dc15c3dbdf71a675c77c6d4138559cdee206dc505438c2c3dabc2b6e7487287add6
7
+ data.tar.gz: 9f5706357ceec8f731412fa966ec40f75ad07e0dec229e2673e56793ebfe382e6e01791ba3fc6ee3e024bbc410cca22de527f222c50ebdf013aa5488298d7839
@@ -17,6 +17,9 @@ jobs:
17
17
  uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
18
18
  with:
19
19
  ruby-version: ${{ matrix.ruby-version }}
20
+ bundler: none
21
+ - name: Install bundler 2.4
22
+ run: gem install bundler -v 2.4.22
20
23
  - name: Install dependencies
21
24
  run: bundle install
22
25
  - name: Run tests
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ ## 9.3.0
2
+
3
+ - Adds Oauth support
4
+ - Changes default base URL from "go.airship.com" to "api.asnapius.com"
5
+
6
+ ---
7
+
1
8
  ## 9.2.0
2
9
 
3
10
  - Adds support for iOS Live Activity and Android Live Update
data/README.rst CHANGED
@@ -66,7 +66,8 @@ In your app initialization, you can do something like the following:
66
66
  require 'urbanairship'
67
67
 
68
68
  Urbanairship.configure do |config|
69
- config.server = 'go.airship.eu'
69
+ config.server = 'api.asnapieu.com'
70
+ config.oauth_server = 'oauth2.asnapieu.com'
70
71
  config.log_path = '/path/to/your/logfile'
71
72
  config.log_level = Logger::WARN
72
73
  config.timeout = 60
@@ -87,10 +88,11 @@ If you want to use a custom logger (e.g Rails.logger), you can do:
87
88
  Available Configurations
88
89
  ------------------------
89
90
 
90
- - **log_path**: Allows to define the folder where the log file will be created (the default is nil).
91
- - **log_level**: Allows to define the log level and only messages at that level or higher will be printed (the default is INFO).
92
- - **server**: Allow to define the Airship server you want to use ("go.airship.eu" or "go.urbanairship.com")
93
- - **timeout**: Allows to define the request timeout in seconds (the default is 5).
91
+ - **log_path**: Allows you to define the folder where the log file will be created (the default is nil).
92
+ - **log_level**: Allows you to define the log level and only messages at that level or higher will be printed (the default is INFO).
93
+ - **server**: Allows you to define the Airship server you want to use ("api.asnapieu.com" for EU or "api.asnapius.com" for US)
94
+ - **oauth_server** Allows you to define the Airship Oauth server you want to use ("oauth2.asnapieu.com" for EU or "oauth2.asnapius.com" for US)
95
+ - **timeout**: Allows you to define the request timeout in seconds (the default is 5).
94
96
 
95
97
 
96
98
  Usage
@@ -140,7 +142,7 @@ Simple Tag Push
140
142
 
141
143
  Specify the Airship server used to make your requests
142
144
  -----------------------------------------------------
143
- By default, the request will be sent to the 'go.urbanairship.com' server:
145
+ By default, the request will be sent to the 'api.asnapius.com' server:
144
146
 
145
147
  .. code-block:: ruby
146
148
 
@@ -155,11 +157,11 @@ You can change the server globally in the Urbanairship configuration:
155
157
  require 'urbanairship'
156
158
 
157
159
  Urbanairship.configure do |config|
158
- config.server = 'go.airship.eu'
160
+ config.server = 'api.asnapieu.com'
159
161
  end
160
162
 
161
163
  Urbanairship::Client.new(key:'application_key', secret:'master_secret')
162
- # request will be sent to the 'go.airship.eu' server
164
+ # request will be sent to the 'api.asnapieu.com' server
163
165
 
164
166
  Finally, you can change the targeted server on a request basis:
165
167
 
@@ -168,12 +170,12 @@ Finally, you can change the targeted server on a request basis:
168
170
  require 'urbanairship'
169
171
 
170
172
  Urbanairship.configure do |config|
171
- config.server = 'go.airship.eu'
173
+ config.server = 'api.asnapieu.com'
172
174
  end
173
175
 
174
- Urbanairship::Client.new(key:'application_key', secret:'master_secret', server: 'go.urbanairship.com')
176
+ Urbanairship::Client.new(key:'application_key', secret:'master_secret', server: 'api.asnapius.com')
175
177
  # The Urbanairship configuration is overridden by the client and the
176
- # request will be sent to the 'go.urbanairship.com' server
178
+ # request will be sent to the 'api.asnapius.com' server
177
179
 
178
180
  Using Bearer Token Auth
179
181
  -----------------------
@@ -191,6 +193,32 @@ will use bearer token auth. Bearer token auth is required for some
191
193
  endpoints, but not supported by others. Please check `the Airship
192
194
  docs site <https://docs.airship.com/>`_ to see where it is supported.
193
195
 
196
+ Using Oauth
197
+ -----------
198
+ .. code-block:: ruby
199
+
200
+ require 'urbanairship'
201
+
202
+ UA = Urbanairship
203
+ app_key = 'application_key'
204
+
205
+ oauth = UA::Oauth.new(
206
+ client_id: 'client_id',
207
+ key: app_key,
208
+ assertion_private_key: 'your_private_key',
209
+ scopes: ['psh', 'chn'], # Optional
210
+ ip_addresses: ['23.74.131.15/22'], # Optional
211
+ oauth_server: 'api.asnapieu.com' # Optional
212
+ )
213
+ airship = UA::Client.new(key: app_key, oauth: oauth)
214
+ # Then continue as you would otherwise
215
+
216
+ **Note**: You can not use both Oauth and bearer token auth
217
+ at the same time. Oauth also cannot be used with the older
218
+ 'api.urbanairship.com' and 'api.airship.eu' base URLs. Lastly
219
+ there are some endpoints in which Oauth is not supported.
220
+ Please check `the Airship docs site <https://docs.airship.com/>`_ to see where it is supported.
221
+
194
222
  Contributing
195
223
  ============
196
224
 
@@ -1,11 +1,12 @@
1
1
  require 'json'
2
2
  require 'rest-client'
3
3
  require 'urbanairship'
4
+ require 'jwt'
4
5
 
5
6
 
6
7
  module Urbanairship
7
8
  class Client
8
- attr_accessor :key, :secret
9
+ attr_accessor :key, :secret, :token
9
10
  include Urbanairship::Common
10
11
  include Urbanairship::Loggable
11
12
 
@@ -13,15 +14,21 @@ module Urbanairship
13
14
  #
14
15
  # @param [Object] key Application Key
15
16
  # @param [Object] secret Application Secret
16
- # @param [String] server Airship server to use ("go.airship.eu" or "go.urbanairship.com").
17
+ # @param [String] server Airship server to use ("api.asnapieu.com" for EU or "api.asnapius.com" for US).
17
18
  # Used only when the request is sent with a "path", not an "url".
18
19
  # @param [String] token Application Auth Token
20
+ # @param [Object] oauth Oauth object
19
21
  # @return [Object] Client
20
- def initialize(key: required('key'), secret: nil, server: Urbanairship.configuration.server, token: nil)
22
+ def initialize(key: required('key'), secret: nil, server: Urbanairship.configuration.server, token: nil, oauth: nil)
21
23
  @key = key
22
24
  @secret = secret
23
25
  @server = server
24
26
  @token = token
27
+ @oauth = oauth
28
+
29
+ if @oauth != nil && @token != nil
30
+ raise ArgumentError.new("oauth and token can't both be used at the same time.")
31
+ end
25
32
  end
26
33
 
27
34
  # Send a request to Airship's API
@@ -56,6 +63,16 @@ module Urbanairship
56
63
  headers['Content-Type'] = content_type unless content_type.nil?
57
64
  headers['Content-Encoding'] = encoding unless encoding.nil?
58
65
 
66
+ unless @oauth.nil?
67
+ begin
68
+ @token = @oauth.get_token
69
+ rescue RestClient::Exception => e
70
+ new_error = RestClient::Exception.new(e.response, e.response.code)
71
+ new_error.message = "error while getting oauth token: #{e.message}"
72
+ raise new_error
73
+ end
74
+ end
75
+
59
76
  if @token != nil
60
77
  auth_type = :bearer
61
78
  end
@@ -1,9 +1,10 @@
1
1
  module Urbanairship
2
2
  class Configuration
3
- attr_accessor :custom_logger, :log_path, :log_level, :server, :timeout
3
+ attr_accessor :custom_logger, :log_path, :log_level, :server, :oauth_server, :timeout
4
4
 
5
5
  def initialize
6
- @server = 'go.urbanairship.com'
6
+ @server = 'api.asnapius.com'
7
+ @oauth_server = 'oauth2.asnapius.com'
7
8
  @custom_logger = nil
8
9
  @log_path = nil
9
10
  @log_level = Logger::INFO
@@ -0,0 +1,129 @@
1
+ require 'urbanairship'
2
+ require 'base64'
3
+ require 'rest-client'
4
+
5
+ module Urbanairship
6
+ class Oauth
7
+ attr_accessor :client_id, :sub, :assertion_private_key, :ip_addresses, :scopes, :oauth_server
8
+
9
+ # Initialize Oauth class
10
+ #
11
+ # @param [String] client_id The Client ID found when creating Oauth credentials in the dashboard.
12
+ # @param [String] key The app key for the project.
13
+ # @param [String] assertion_private_key The private key found when creating Oauth credentials in the dashboard. Used for assertion token auth.
14
+ # @param [Array<String>] ip_addresses A list of CIDR representations of valid IP addresses to which the issued token is restricted. Example: ['24.20.40.0/22', '34.17.3.0/22']
15
+ # @param [Array<String>] scopes A list of scopes to which the issued token will be entitled. Example: ['psh', 'lst']
16
+ # @param [String] oauth_server The server to send Oauth token requests to. By default is 'oauth2.asnapius.com', but can be set to 'oauth2.asnapieu.com' if using the EU server.
17
+ # @return [Object] Oauth object
18
+ def initialize(client_id:, key:, assertion_private_key:, ip_addresses: [], scopes: [], oauth_server: Urbanairship.configuration.oauth_server)
19
+ @grant_type = 'client_credentials'
20
+ @client_id = client_id
21
+ @assertion_private_key = assertion_private_key
22
+ @ip_addresses = ip_addresses
23
+ @scopes = scopes
24
+ @sub = "app:#{key}"
25
+ @oauth_server = oauth_server
26
+ @token = nil
27
+ end
28
+
29
+ # Get an Oauth token from Airship Oauth servers.
30
+ #
31
+ # @return [String] JSON web token to be used in further Airship API requests.
32
+ def get_token
33
+ unless @token.nil?
34
+ decoded_jwt = JWT.decode(@token, nil, false)
35
+ current_time = Time.now.to_i
36
+ expiry_time = decoded_jwt[0]['exp']
37
+
38
+ if current_time < expiry_time
39
+ return @token
40
+ end
41
+ end
42
+
43
+ assertion_jwt = build_assertion_jwt
44
+
45
+ url = "https://#{@oauth_server}/token"
46
+ headers = {
47
+ 'Host': @oauth_server,
48
+ 'Content-Type': 'application/x-www-form-urlencoded',
49
+ 'Accept': 'application/json'
50
+ }
51
+
52
+ params = {
53
+ method: :post,
54
+ url: url,
55
+ headers: headers,
56
+ payload: {
57
+ grant_type: @grant_type,
58
+ assertion: assertion_jwt
59
+ },
60
+ timeout: 60
61
+ }
62
+
63
+ retries = 0
64
+ max_retries = 3
65
+ begin
66
+ response = RestClient::Request.execute(params)
67
+ @token = JSON.parse(response.body)['access_token']
68
+ return @token
69
+ rescue RestClient::ExceptionWithResponse => e
70
+ if [400, 401, 406].include?(e.response.code)
71
+ raise e
72
+ else
73
+ retries += 1
74
+ if retries <= max_retries
75
+ sleep(retries ** 2)
76
+ retry
77
+ else
78
+ new_error = RestClient::Exception.new(e.response, e.response.code)
79
+ new_error.message = "failed after 3 attempts with error: #{e}"
80
+ raise new_error
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ # Build an assertion JWT
87
+ #
88
+ # @return [String] Assertion JWT to be used when requesting an Oauth token from Airship servers.
89
+ def build_assertion_jwt
90
+ assertion_expiration = 61
91
+ private_key = OpenSSL::PKey::EC.new(@assertion_private_key)
92
+
93
+ headers = {
94
+ alg: 'ES384',
95
+ kid: @client_id
96
+ }
97
+
98
+ claims = {
99
+ aud: "https://#{@oauth_server}/token",
100
+ exp: Time.now.to_i + assertion_expiration,
101
+ iat: Time.now.to_i,
102
+ iss: @client_id,
103
+ nonce: SecureRandom.uuid,
104
+ sub: @sub
105
+ }
106
+
107
+ claims[:scope] = @scopes.join(' ') if @scopes.any?
108
+ claims[:ipaddr] = @ip_addresses.join(' ') if @ip_addresses.any?
109
+
110
+ JWT.encode(claims, private_key, 'ES384', headers)
111
+ end
112
+
113
+ # Verify a public key
114
+ #
115
+ # @param [String] key_id The key ID ('kid') found in the header when decoding an Oauth token granted from Airship's servers.
116
+ # @return [String] The public key associated with the Key ID.
117
+ def verify_public_key(key_id)
118
+ url = "https://#{@oauth_server}/verify/public_key/#{key_id}"
119
+
120
+ headers = {
121
+ 'Host': @oauth_server,
122
+ 'Accept': 'text/plain'
123
+ }
124
+
125
+ response = RestClient.get(url, headers)
126
+ response.body
127
+ end
128
+ end
129
+ end
@@ -1,3 +1,3 @@
1
1
  module Urbanairship
2
- VERSION = '9.2.0'
2
+ VERSION = '9.3.0'
3
3
  end
data/lib/urbanairship.rb CHANGED
@@ -15,6 +15,7 @@ require 'urbanairship/devices/create_and_send'
15
15
  require 'urbanairship/devices/attribute'
16
16
  require 'urbanairship/devices/attributes'
17
17
  require 'urbanairship/client'
18
+ require 'urbanairship/oauth'
18
19
  require 'urbanairship/common'
19
20
  require 'urbanairship/configuration'
20
21
  require 'urbanairship/loggable'
data/urbanairship.gemspec CHANGED
@@ -28,8 +28,9 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  spec.add_runtime_dependency 'rest-client', '>= 1.4', '< 4.0'
31
+ spec.add_runtime_dependency 'jwt', '>= 2.0', '< 3.0'
31
32
 
32
- spec.add_development_dependency 'bundler', '>= 1'
33
+ spec.add_development_dependency 'bundler', '>= 1', '< 2.5'
33
34
  spec.add_development_dependency 'guard-rspec'
34
35
  spec.add_development_dependency 'pry', '~> 0'
35
36
  spec.add_development_dependency 'rake', '~> 12.3.3'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanairship
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.2.0
4
+ version: 9.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airship
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-23 00:00:00.000000000 Z
11
+ date: 2024-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -30,6 +30,26 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '4.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: jwt
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '3.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '2.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.0'
33
53
  - !ruby/object:Gem::Dependency
34
54
  name: bundler
35
55
  requirement: !ruby/object:Gem::Requirement
@@ -37,6 +57,9 @@ dependencies:
37
57
  - - ">="
38
58
  - !ruby/object:Gem::Version
39
59
  version: '1'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '2.5'
40
63
  type: :development
41
64
  prerelease: false
42
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,6 +67,9 @@ dependencies:
44
67
  - - ">="
45
68
  - !ruby/object:Gem::Version
46
69
  version: '1'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '2.5'
47
73
  - !ruby/object:Gem::Dependency
48
74
  name: guard-rspec
49
75
  requirement: !ruby/object:Gem::Requirement
@@ -202,6 +228,7 @@ files:
202
228
  - lib/urbanairship/devices/static_lists.rb
203
229
  - lib/urbanairship/devices/tag_lists.rb
204
230
  - lib/urbanairship/loggable.rb
231
+ - lib/urbanairship/oauth.rb
205
232
  - lib/urbanairship/push/audience.rb
206
233
  - lib/urbanairship/push/payload.rb
207
234
  - lib/urbanairship/push/push.rb
@@ -230,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
257
  - !ruby/object:Gem::Version
231
258
  version: '0'
232
259
  requirements: []
233
- rubygems_version: 3.4.10
260
+ rubygems_version: 3.1.6
234
261
  signing_key:
235
262
  specification_version: 4
236
263
  summary: Ruby Gem for using the Airship API