urbanairship 9.2.0 → 9.3.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: 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