googleauth 1.9.2 → 1.14.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/CHANGELOG.md +77 -0
- data/README.md +49 -1
- data/lib/googleauth/api_key.rb +155 -0
- data/lib/googleauth/base_client.rb +16 -4
- data/lib/googleauth/bearer_token.rb +148 -0
- data/lib/googleauth/compute_engine.rb +147 -23
- data/lib/googleauth/credentials.rb +162 -56
- data/lib/googleauth/credentials_loader.rb +2 -2
- data/lib/googleauth/default_credentials.rb +13 -2
- data/lib/googleauth/external_account/base_credentials.rb +34 -3
- data/lib/googleauth/helpers/connection.rb +7 -1
- data/lib/googleauth/id_tokens.rb +0 -2
- data/lib/googleauth/impersonated_service_account.rb +282 -0
- data/lib/googleauth/service_account.rb +57 -104
- data/lib/googleauth/service_account_jwt_header.rb +180 -0
- data/lib/googleauth/signet.rb +137 -2
- data/lib/googleauth/token_store.rb +3 -3
- data/lib/googleauth/user_authorizer.rb +54 -4
- data/lib/googleauth/user_refresh.rb +43 -0
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +15 -4
- data/lib/googleauth.rb +7 -0
- metadata +26 -11
data/lib/googleauth/signet.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require "base64"
|
16
|
+
require "json"
|
15
17
|
require "signet/oauth_2/client"
|
16
18
|
require "googleauth/base_client"
|
17
19
|
|
@@ -29,11 +31,29 @@ module Signet
|
|
29
31
|
|
30
32
|
def update_token! options = {}
|
31
33
|
options = deep_hash_normalize options
|
34
|
+
id_token_expires_at = expires_at_from_id_token options[:id_token]
|
35
|
+
options[:expires_at] = id_token_expires_at if id_token_expires_at
|
32
36
|
update_token_signet_base options
|
33
37
|
self.universe_domain = options[:universe_domain] if options.key? :universe_domain
|
34
38
|
self
|
35
39
|
end
|
36
40
|
|
41
|
+
alias update_signet_base update!
|
42
|
+
def update! options = {}
|
43
|
+
# Normalize all keys to symbols to allow indifferent access.
|
44
|
+
options = deep_hash_normalize options
|
45
|
+
|
46
|
+
# This `update!` method "overide" adds the `@logger`` update and
|
47
|
+
# the `universe_domain` update.
|
48
|
+
#
|
49
|
+
# The `universe_domain` is also updated in `update_token!` but is
|
50
|
+
# included here for completeness
|
51
|
+
self.universe_domain = options[:universe_domain] if options.key? :universe_domain
|
52
|
+
@logger = options[:logger] if options.key? :logger
|
53
|
+
|
54
|
+
update_signet_base options
|
55
|
+
end
|
56
|
+
|
37
57
|
def configure_connection options
|
38
58
|
@connection_info =
|
39
59
|
options[:connection_builder] || options[:default_connection]
|
@@ -61,6 +81,24 @@ module Signet
|
|
61
81
|
info
|
62
82
|
end
|
63
83
|
|
84
|
+
alias googleauth_orig_generate_access_token_request generate_access_token_request
|
85
|
+
def generate_access_token_request options = {}
|
86
|
+
parameters = googleauth_orig_generate_access_token_request options
|
87
|
+
logger&.info do
|
88
|
+
Google::Logging::Message.from(
|
89
|
+
message: "Requesting access token from #{parameters['grant_type']}",
|
90
|
+
"credentialsId" => object_id
|
91
|
+
)
|
92
|
+
end
|
93
|
+
logger&.debug do
|
94
|
+
Google::Logging::Message.from(
|
95
|
+
message: "Token fetch params: #{parameters}",
|
96
|
+
"credentialsId" => object_id
|
97
|
+
)
|
98
|
+
end
|
99
|
+
parameters
|
100
|
+
end
|
101
|
+
|
64
102
|
def build_default_connection
|
65
103
|
if !defined?(@connection_info)
|
66
104
|
nil
|
@@ -75,20 +113,117 @@ module Signet
|
|
75
113
|
retry_count = 0
|
76
114
|
|
77
115
|
begin
|
78
|
-
yield
|
116
|
+
yield.tap { |resp| log_response resp }
|
79
117
|
rescue StandardError => e
|
80
|
-
|
118
|
+
if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError)
|
119
|
+
log_auth_error e
|
120
|
+
raise e
|
121
|
+
end
|
81
122
|
|
82
123
|
if retry_count < max_retry_count
|
124
|
+
log_transient_error e
|
83
125
|
retry_count += 1
|
84
126
|
sleep retry_count * 0.3
|
85
127
|
retry
|
86
128
|
else
|
129
|
+
log_retries_exhausted e
|
87
130
|
msg = "Unexpected error: #{e.inspect}"
|
88
131
|
raise Signet::AuthorizationError, msg
|
89
132
|
end
|
90
133
|
end
|
91
134
|
end
|
135
|
+
|
136
|
+
# Creates a duplicate of these credentials
|
137
|
+
# without the Signet::OAuth2::Client-specific
|
138
|
+
# transient state (e.g. cached tokens)
|
139
|
+
#
|
140
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
141
|
+
# @see Signet::OAuth2::Client#update!
|
142
|
+
def duplicate options = {}
|
143
|
+
options = deep_hash_normalize options
|
144
|
+
|
145
|
+
opts = {
|
146
|
+
authorization_uri: @authorization_uri,
|
147
|
+
token_credential_uri: @token_credential_uri,
|
148
|
+
client_id: @client_id,
|
149
|
+
client_secret: @client_secret,
|
150
|
+
scope: @scope,
|
151
|
+
target_audience: @target_audience,
|
152
|
+
redirect_uri: @redirect_uri,
|
153
|
+
username: @username,
|
154
|
+
password: @password,
|
155
|
+
issuer: @issuer,
|
156
|
+
person: @person,
|
157
|
+
sub: @sub,
|
158
|
+
audience: @audience,
|
159
|
+
signing_key: @signing_key,
|
160
|
+
extension_parameters: @extension_parameters,
|
161
|
+
additional_parameters: @additional_parameters,
|
162
|
+
access_type: @access_type,
|
163
|
+
universe_domain: @universe_domain,
|
164
|
+
logger: @logger
|
165
|
+
}.merge(options)
|
166
|
+
|
167
|
+
new_client = self.class.new opts
|
168
|
+
|
169
|
+
new_client.configure_connection options
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def expires_at_from_id_token id_token
|
175
|
+
match = /^[\w=-]+\.([\w=-]+)\.[\w=-]+$/.match id_token.to_s
|
176
|
+
return unless match
|
177
|
+
json = JSON.parse Base64.urlsafe_decode64 match[1]
|
178
|
+
return unless json.key? "exp"
|
179
|
+
Time.at json["exp"].to_i
|
180
|
+
rescue StandardError
|
181
|
+
# Shouldn't happen unless we get a garbled ID token
|
182
|
+
nil
|
183
|
+
end
|
184
|
+
|
185
|
+
def log_response token_response
|
186
|
+
response_hash = JSON.parse token_response rescue {}
|
187
|
+
if response_hash["access_token"]
|
188
|
+
digest = Digest::SHA256.hexdigest response_hash["access_token"]
|
189
|
+
response_hash["access_token"] = "(sha256:#{digest})"
|
190
|
+
end
|
191
|
+
if response_hash["id_token"]
|
192
|
+
digest = Digest::SHA256.hexdigest response_hash["id_token"]
|
193
|
+
response_hash["id_token"] = "(sha256:#{digest})"
|
194
|
+
end
|
195
|
+
Google::Logging::Message.from(
|
196
|
+
message: "Received auth token response: #{response_hash}",
|
197
|
+
"credentialsId" => object_id
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
def log_auth_error err
|
202
|
+
logger&.info do
|
203
|
+
Google::Logging::Message.from(
|
204
|
+
message: "Auth error when fetching auth token: #{err}",
|
205
|
+
"credentialsId" => object_id
|
206
|
+
)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def log_transient_error err
|
211
|
+
logger&.info do
|
212
|
+
Google::Logging::Message.from(
|
213
|
+
message: "Transient error when fetching auth token: #{err}",
|
214
|
+
"credentialsId" => object_id
|
215
|
+
)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def log_retries_exhausted err
|
220
|
+
logger&.info do
|
221
|
+
Google::Logging::Message.from(
|
222
|
+
message: "Exhausted retries when fetching auth token: #{err}",
|
223
|
+
"credentialsId" => object_id
|
224
|
+
)
|
225
|
+
end
|
226
|
+
end
|
92
227
|
end
|
93
228
|
end
|
94
229
|
end
|
@@ -29,7 +29,7 @@ module Google
|
|
29
29
|
# @return [String]
|
30
30
|
# The loaded token data.
|
31
31
|
def load _id
|
32
|
-
raise "
|
32
|
+
raise NoMethodError, "load not implemented"
|
33
33
|
end
|
34
34
|
|
35
35
|
# Put the token data into storage for the given ID.
|
@@ -39,7 +39,7 @@ module Google
|
|
39
39
|
# @param [String] token
|
40
40
|
# The token data to store.
|
41
41
|
def store _id, _token
|
42
|
-
raise "
|
42
|
+
raise NoMethodError, "store not implemented"
|
43
43
|
end
|
44
44
|
|
45
45
|
# Remove the token data from storage for the given ID.
|
@@ -47,7 +47,7 @@ module Google
|
|
47
47
|
# @param [String] id
|
48
48
|
# ID of the token data to delete
|
49
49
|
def delete _id
|
50
|
-
raise "
|
50
|
+
raise NoMethodError, "delete not implemented"
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -16,6 +16,7 @@ require "uri"
|
|
16
16
|
require "multi_json"
|
17
17
|
require "googleauth/signet"
|
18
18
|
require "googleauth/user_refresh"
|
19
|
+
require "securerandom"
|
19
20
|
|
20
21
|
module Google
|
21
22
|
module Auth
|
@@ -54,17 +55,26 @@ module Google
|
|
54
55
|
# Authorization scope to request
|
55
56
|
# @param [Google::Auth::Stores::TokenStore] token_store
|
56
57
|
# Backing storage for persisting user credentials
|
57
|
-
# @param [String]
|
58
|
+
# @param [String] legacy_callback_uri
|
58
59
|
# URL (either absolute or relative) of the auth callback.
|
59
|
-
# Defaults to '/oauth2callback'
|
60
|
-
|
60
|
+
# Defaults to '/oauth2callback'.
|
61
|
+
# @deprecated This field is deprecated. Instead, use the keyword
|
62
|
+
# argument callback_uri.
|
63
|
+
# @param [String] code_verifier
|
64
|
+
# Random string of 43-128 chars used to verify the key exchange using
|
65
|
+
# PKCE.
|
66
|
+
def initialize client_id, scope, token_store,
|
67
|
+
legacy_callback_uri = nil,
|
68
|
+
callback_uri: nil,
|
69
|
+
code_verifier: nil
|
61
70
|
raise NIL_CLIENT_ID_ERROR if client_id.nil?
|
62
71
|
raise NIL_SCOPE_ERROR if scope.nil?
|
63
72
|
|
64
73
|
@client_id = client_id
|
65
74
|
@scope = Array(scope)
|
66
75
|
@token_store = token_store
|
67
|
-
@callback_uri = callback_uri || "/oauth2callback"
|
76
|
+
@callback_uri = legacy_callback_uri || callback_uri || "/oauth2callback"
|
77
|
+
@code_verifier = code_verifier
|
68
78
|
end
|
69
79
|
|
70
80
|
# Build the URL for requesting authorization.
|
@@ -86,6 +96,18 @@ module Google
|
|
86
96
|
# Authorization url
|
87
97
|
def get_authorization_url options = {}
|
88
98
|
scope = options[:scope] || @scope
|
99
|
+
|
100
|
+
options[:additional_parameters] ||= {}
|
101
|
+
|
102
|
+
if @code_verifier
|
103
|
+
options[:additional_parameters].merge!(
|
104
|
+
{
|
105
|
+
code_challenge: generate_code_challenge(@code_verifier),
|
106
|
+
code_challenge_method: code_challenge_method
|
107
|
+
}
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
89
111
|
credentials = UserRefreshCredentials.new(
|
90
112
|
client_id: @client_id.id,
|
91
113
|
client_secret: @client_id.secret,
|
@@ -157,6 +179,8 @@ module Google
|
|
157
179
|
code = options[:code]
|
158
180
|
scope = options[:scope] || @scope
|
159
181
|
base_url = options[:base_url]
|
182
|
+
options[:additional_parameters] ||= {}
|
183
|
+
options[:additional_parameters].merge!({ code_verifier: @code_verifier })
|
160
184
|
credentials = UserRefreshCredentials.new(
|
161
185
|
client_id: @client_id.id,
|
162
186
|
client_secret: @client_id.secret,
|
@@ -228,6 +252,23 @@ module Google
|
|
228
252
|
credentials
|
229
253
|
end
|
230
254
|
|
255
|
+
# The code verifier for PKCE for OAuth 2.0. When set, the
|
256
|
+
# authorization URI will contain the Code Challenge and Code
|
257
|
+
# Challenge Method querystring parameters, and the token URI will
|
258
|
+
# contain the Code Verifier parameter.
|
259
|
+
#
|
260
|
+
# @param [String|nil] new_code_erifier
|
261
|
+
def code_verifier= new_code_verifier
|
262
|
+
@code_verifier = new_code_verifier
|
263
|
+
end
|
264
|
+
|
265
|
+
# Generate the code verifier needed to be sent while fetching
|
266
|
+
# authorization URL.
|
267
|
+
def self.generate_code_verifier
|
268
|
+
random_number = rand 32..96
|
269
|
+
SecureRandom.alphanumeric random_number
|
270
|
+
end
|
271
|
+
|
231
272
|
private
|
232
273
|
|
233
274
|
# @private Fetch stored token with given user_id
|
@@ -272,6 +313,15 @@ module Google
|
|
272
313
|
def uri_is_postmessage? uri
|
273
314
|
uri.to_s.casecmp("postmessage").zero?
|
274
315
|
end
|
316
|
+
|
317
|
+
def generate_code_challenge code_verifier
|
318
|
+
digest = Digest::SHA256.digest code_verifier
|
319
|
+
Base64.urlsafe_encode64 digest, padding: false
|
320
|
+
end
|
321
|
+
|
322
|
+
def code_challenge_method
|
323
|
+
"S256"
|
324
|
+
end
|
275
325
|
end
|
276
326
|
end
|
277
327
|
end
|
@@ -85,6 +85,26 @@ module Google
|
|
85
85
|
super options
|
86
86
|
end
|
87
87
|
|
88
|
+
# Creates a duplicate of these credentials
|
89
|
+
# without the Signet::OAuth2::Client-specific
|
90
|
+
# transient state (e.g. cached tokens)
|
91
|
+
#
|
92
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
93
|
+
# The following keys are recognized in addition to keys in the
|
94
|
+
# Signet::OAuth2::Client
|
95
|
+
# * `project_id` the project id to use during the authentication
|
96
|
+
# * `quota_project_id` the quota project id to use
|
97
|
+
# during the authentication
|
98
|
+
def duplicate options = {}
|
99
|
+
options = deep_hash_normalize options
|
100
|
+
super(
|
101
|
+
{
|
102
|
+
project_id: @project_id,
|
103
|
+
quota_project_id: @quota_project_id
|
104
|
+
}.merge(options)
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
88
108
|
# Revokes the credential
|
89
109
|
def revoke! options = {}
|
90
110
|
c = options[:connection] || Faraday.default_connection
|
@@ -114,6 +134,29 @@ module Google
|
|
114
134
|
Google::Auth::ScopeUtil.normalize(scope)
|
115
135
|
missing_scope.empty?
|
116
136
|
end
|
137
|
+
|
138
|
+
# Destructively updates these credentials
|
139
|
+
#
|
140
|
+
# This method is called by `Signet::OAuth2::Client`'s constructor
|
141
|
+
#
|
142
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
143
|
+
# The following keys are recognized in addition to keys in the
|
144
|
+
# Signet::OAuth2::Client
|
145
|
+
# * `project_id` the project id to use during the authentication
|
146
|
+
# * `quota_project_id` the quota project id to use
|
147
|
+
# during the authentication
|
148
|
+
# @return [Google::Auth::UserRefreshCredentials]
|
149
|
+
def update! options = {}
|
150
|
+
# Normalize all keys to symbols to allow indifferent access.
|
151
|
+
options = deep_hash_normalize options
|
152
|
+
|
153
|
+
@project_id = options[:project_id] if options.key? :project_id
|
154
|
+
@quota_project_id = options[:quota_project_id] if options.key? :quota_project_id
|
155
|
+
|
156
|
+
super(options)
|
157
|
+
|
158
|
+
self
|
159
|
+
end
|
117
160
|
end
|
118
161
|
end
|
119
162
|
end
|
data/lib/googleauth/version.rb
CHANGED
@@ -93,11 +93,22 @@ module Google
|
|
93
93
|
# Authorization scope to request
|
94
94
|
# @param [Google::Auth::Stores::TokenStore] token_store
|
95
95
|
# Backing storage for persisting user credentials
|
96
|
-
# @param [String]
|
96
|
+
# @param [String] legacy_callback_uri
|
97
97
|
# URL (either absolute or relative) of the auth callback. Defaults
|
98
|
-
# to '/oauth2callback'
|
99
|
-
|
100
|
-
|
98
|
+
# to '/oauth2callback'.
|
99
|
+
# @deprecated This field is deprecated. Instead, use the keyword
|
100
|
+
# argument callback_uri.
|
101
|
+
# @param [String] code_verifier
|
102
|
+
# Random string of 43-128 chars used to verify the key exchange using
|
103
|
+
# PKCE.
|
104
|
+
def initialize client_id, scope, token_store,
|
105
|
+
legacy_callback_uri = nil,
|
106
|
+
callback_uri: nil,
|
107
|
+
code_verifier: nil
|
108
|
+
super client_id, scope, token_store,
|
109
|
+
legacy_callback_uri,
|
110
|
+
code_verifier: code_verifier,
|
111
|
+
callback_uri: callback_uri
|
101
112
|
end
|
102
113
|
|
103
114
|
# Handle the result of the oauth callback. Exchanges the authorization
|
data/lib/googleauth.rb
CHANGED
@@ -13,9 +13,16 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require "googleauth/application_default"
|
16
|
+
require "googleauth/api_key"
|
17
|
+
require "googleauth/bearer_token"
|
16
18
|
require "googleauth/client_id"
|
17
19
|
require "googleauth/credentials"
|
18
20
|
require "googleauth/default_credentials"
|
21
|
+
require "googleauth/external_account"
|
19
22
|
require "googleauth/id_tokens"
|
23
|
+
require "googleauth/impersonated_service_account"
|
24
|
+
require "googleauth/service_account"
|
25
|
+
require "googleauth/service_account_jwt_header"
|
20
26
|
require "googleauth/user_authorizer"
|
27
|
+
require "googleauth/user_refresh"
|
21
28
|
require "googleauth/web_user_authorizer"
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googleauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Google LLC
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-14 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -36,14 +35,28 @@ dependencies:
|
|
36
35
|
requirements:
|
37
36
|
- - "~>"
|
38
37
|
- !ruby/object:Gem::Version
|
39
|
-
version: '2.
|
38
|
+
version: '2.2'
|
40
39
|
type: :runtime
|
41
40
|
prerelease: false
|
42
41
|
version_requirements: !ruby/object:Gem::Requirement
|
43
42
|
requirements:
|
44
43
|
- - "~>"
|
45
44
|
- !ruby/object:Gem::Version
|
46
|
-
version: '2.
|
45
|
+
version: '2.2'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: google-logging-utils
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0.1'
|
53
|
+
type: :runtime
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.1'
|
47
60
|
- !ruby/object:Gem::Dependency
|
48
61
|
name: jwt
|
49
62
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,7 +134,7 @@ dependencies:
|
|
121
134
|
description: Implements simple authorization for accessing Google APIs, and provides
|
122
135
|
support for Application Default Credentials.
|
123
136
|
email:
|
124
|
-
-
|
137
|
+
- googleapis-packages@google.com
|
125
138
|
executables: []
|
126
139
|
extensions: []
|
127
140
|
extra_rdoc_files: []
|
@@ -133,8 +146,10 @@ files:
|
|
133
146
|
- README.md
|
134
147
|
- SECURITY.md
|
135
148
|
- lib/googleauth.rb
|
149
|
+
- lib/googleauth/api_key.rb
|
136
150
|
- lib/googleauth/application_default.rb
|
137
151
|
- lib/googleauth/base_client.rb
|
152
|
+
- lib/googleauth/bearer_token.rb
|
138
153
|
- lib/googleauth/client_id.rb
|
139
154
|
- lib/googleauth/compute_engine.rb
|
140
155
|
- lib/googleauth/credentials.rb
|
@@ -152,10 +167,12 @@ files:
|
|
152
167
|
- lib/googleauth/id_tokens/errors.rb
|
153
168
|
- lib/googleauth/id_tokens/key_sources.rb
|
154
169
|
- lib/googleauth/id_tokens/verifier.rb
|
170
|
+
- lib/googleauth/impersonated_service_account.rb
|
155
171
|
- lib/googleauth/json_key_reader.rb
|
156
172
|
- lib/googleauth/oauth2/sts_client.rb
|
157
173
|
- lib/googleauth/scope_util.rb
|
158
174
|
- lib/googleauth/service_account.rb
|
175
|
+
- lib/googleauth/service_account_jwt_header.rb
|
159
176
|
- lib/googleauth/signet.rb
|
160
177
|
- lib/googleauth/stores/file_token_store.rb
|
161
178
|
- lib/googleauth/stores/redis_token_store.rb
|
@@ -171,7 +188,6 @@ metadata:
|
|
171
188
|
changelog_uri: https://github.com/googleapis/google-auth-library-ruby/blob/main/CHANGELOG.md
|
172
189
|
source_code_uri: https://github.com/googleapis/google-auth-library-ruby
|
173
190
|
bug_tracker_uri: https://github.com/googleapis/google-auth-library-ruby/issues
|
174
|
-
post_install_message:
|
175
191
|
rdoc_options: []
|
176
192
|
require_paths:
|
177
193
|
- lib
|
@@ -179,15 +195,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
195
|
requirements:
|
180
196
|
- - ">="
|
181
197
|
- !ruby/object:Gem::Version
|
182
|
-
version: '
|
198
|
+
version: '3.0'
|
183
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
200
|
requirements:
|
185
201
|
- - ">="
|
186
202
|
- !ruby/object:Gem::Version
|
187
203
|
version: '0'
|
188
204
|
requirements: []
|
189
|
-
rubygems_version: 3.5
|
190
|
-
signing_key:
|
205
|
+
rubygems_version: 3.6.5
|
191
206
|
specification_version: 4
|
192
207
|
summary: Google Auth Library for Ruby
|
193
208
|
test_files: []
|