googleauth 1.11.0 → 1.12.2

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: 4912a601c0a234fa9faf150d7461cab993f775b715f6ac7d19db017ceae74e6d
4
- data.tar.gz: e08da21e12d58260944079d068a04099fa0c812eb486e760a3ab12dd002700f4
3
+ metadata.gz: 34f510693238aa2d0ac63fb3d7a91f8685d34dc9962e33952220b6ee8845beef
4
+ data.tar.gz: 97d0eb5127ac1c609740d8b422b2002bd8f983043ff1a11cc09130c3c650d30f
5
5
  SHA512:
6
- metadata.gz: b0346fcaf38cb783fd4d22f0734994298d63dfa1a89fd34df4d4f42b87160de410e34c93ab4773c3bbaf03b41160f10e3fd5bc0fa137d1ab6fb5dce15f72ba53
7
- data.tar.gz: c5ff10a04491e9f56dff9bcea24c67398e67713efc89c2d378075621da837b59c5fdbd36c0b97d5753fd0358befe8ce2ceacc86af1cce0a1c54d609d916903c6
6
+ metadata.gz: 821238707fdf60880359514bc2385a273b4d16fe6bc6bd8ad804fcd36d2255667ad4a4dd39e7fabbd5f422367208a7fc7b74949943cda444481a8da3edfd16e2
7
+ data.tar.gz: 792636b6a808d5c93dc7a3883a7c7d1e62cbb3d8b33b76e4da025cdbdac8cbd915c1cd4c5e1e698a58173d6fb2840e7623bd8c2a5673edc69113b662486029c4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Release History
2
2
 
3
+ ### 1.12.2 (2024-12-19)
4
+
5
+ #### Bug Fixes
6
+
7
+ * GCECredentials lazily fetches from the metadata server to ensure a universe domain is known ([#509](https://github.com/googleapis/google-auth-library-ruby/issues/509))
8
+
9
+ ### 1.12.1 (2024-12-17)
10
+
11
+ #### Bug Fixes
12
+
13
+ * Restored previous behavior where the apply! method returns the auth header ([#506](https://github.com/googleapis/google-auth-library-ruby/issues/506))
14
+
15
+ ### 1.12.0 (2024-12-05)
16
+
17
+ #### Features
18
+
19
+ * provided opt-in debug logging ([#490](https://github.com/googleapis/google-auth-library-ruby/issues/490))
20
+
21
+ ### 1.11.2 (2024-10-23)
22
+
23
+ #### Bug Fixes
24
+
25
+ * Temporarily disable universe domain query from GCE metadata server ([#493](https://github.com/googleapis/google-auth-library-ruby/issues/493))
26
+ * Use updated metadata path for universe-domain ([#496](https://github.com/googleapis/google-auth-library-ruby/issues/496))
27
+
28
+ ### 1.11.1 (2024-10-04)
29
+
30
+ #### Bug Fixes
31
+
32
+ * Fixed parsing of expiration timestamp from ID tokens ([#492](https://github.com/googleapis/google-auth-library-ruby/issues/492))
33
+ * Use NoMethodError instead of NotImplementedError for unimplemented base class methods ([#487](https://github.com/googleapis/google-auth-library-ruby/issues/487))
34
+
3
35
  ### 1.11.0 (2024-02-09)
4
36
 
5
37
  #### Features
@@ -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 "google/logging/message"
16
+
15
17
  module Google
16
18
  # Module Auth provides classes that provide Google-specific authorization
17
19
  # used to access Google APIs.
@@ -29,7 +31,14 @@ module Google
29
31
  # fetch the access token there is currently not one, or if the client
30
32
  # has expired
31
33
  fetch_access_token! opts if needs_access_token?
32
- a_hash[AUTH_METADATA_KEY] = "Bearer #{send token_type}"
34
+ token = send token_type
35
+ a_hash[AUTH_METADATA_KEY] = "Bearer #{token}"
36
+ logger&.debug do
37
+ hash = Digest::SHA256.hexdigest token
38
+ Google::Logging::Message.from message: "Sending auth token. (sha256:#{hash})"
39
+ end
40
+
41
+ a_hash[AUTH_METADATA_KEY]
33
42
  end
34
43
 
35
44
  # Returns a clone of a_hash updated with the authentication token
@@ -63,17 +72,20 @@ module Google
63
72
  end
64
73
 
65
74
  def expires_within?
66
- raise NotImplementedError
75
+ raise NoMethodError, "expires_within? not implemented"
67
76
  end
68
77
 
78
+ # The logger used to log operations on this client, such as token refresh.
79
+ attr_accessor :logger
80
+
69
81
  private
70
82
 
71
83
  def token_type
72
- raise NotImplementedError
84
+ raise NoMethodError, "token_type not implemented"
73
85
  end
74
86
 
75
87
  def fetch_access_token!
76
- raise NotImplementedError
88
+ raise NoMethodError, "fetch_access_token! not implemented"
77
89
  end
78
90
  end
79
91
  end
@@ -80,69 +80,144 @@ module Google
80
80
  alias unmemoize_all reset_cache
81
81
  end
82
82
 
83
+ # @private Temporary; remove when universe domain metadata endpoint is stable (see b/349488459).
84
+ attr_accessor :disable_universe_domain_check
85
+
83
86
  # Construct a GCECredentials
84
87
  def initialize options = {}
85
88
  # Override the constructor to remember whether the universe domain was
86
89
  # overridden by a constructor argument.
87
90
  @universe_domain_overridden = options["universe_domain"] || options[:universe_domain] ? true : false
91
+ # TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
92
+ @disable_universe_domain_check = true
88
93
  super options
89
94
  end
90
95
 
96
+ # @private
97
+ # Overrides universe_domain getter to fetch lazily if it hasn't been
98
+ # fetched yet. This is necessary specifically for Compute Engine because
99
+ # the universe comes from the metadata service, and isn't known
100
+ # immediately on credential construction. All other credential types read
101
+ # the universe from their json key or other immediate input.
102
+ def universe_domain
103
+ value = super
104
+ return value unless value.nil?
105
+ fetch_access_token!
106
+ super
107
+ end
108
+
91
109
  # Overrides the super class method to change how access tokens are
92
110
  # fetched.
93
111
  def fetch_access_token _options = {}
94
- if token_type == :id_token
95
- query = { "audience" => target_audience, "format" => "full" }
96
- entry = "service-accounts/default/identity"
97
- else
98
- query = {}
99
- entry = "service-accounts/default/token"
100
- end
112
+ query, entry =
113
+ if token_type == :id_token
114
+ [{ "audience" => target_audience, "format" => "full" }, "service-accounts/default/identity"]
115
+ else
116
+ [{}, "service-accounts/default/token"]
117
+ end
101
118
  query[:scopes] = Array(scope).join "," if scope
102
119
  begin
120
+ log_fetch_query
103
121
  resp = Google::Cloud.env.lookup_metadata_response "instance", entry, query: query
122
+ log_fetch_resp resp
104
123
  case resp.status
105
124
  when 200
106
125
  build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
107
126
  when 403, 500
108
- msg = "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
109
- raise Signet::UnexpectedStatusError, msg
127
+ raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
110
128
  when 404
111
129
  raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
112
130
  else
113
- msg = "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
114
- raise Signet::AuthorizationError, msg
131
+ raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
115
132
  end
116
133
  rescue Google::Cloud::Env::MetadataServerNotResponding => e
134
+ log_fetch_err e
117
135
  raise Signet::AuthorizationError, e.message
118
136
  end
119
137
  end
120
138
 
121
139
  private
122
140
 
141
+ def log_fetch_query
142
+ if token_type == :id_token
143
+ logger&.info do
144
+ Google::Logging::Message.from(
145
+ message: "Requesting id token from MDS with aud=#{target_audience}",
146
+ "credentialsId" => object_id
147
+ )
148
+ end
149
+ else
150
+ logger&.info do
151
+ Google::Logging::Message.from(
152
+ message: "Requesting access token from MDS",
153
+ "credentialsId" => object_id
154
+ )
155
+ end
156
+ end
157
+ end
158
+
159
+ def log_fetch_resp resp
160
+ logger&.info do
161
+ Google::Logging::Message.from(
162
+ message: "Received #{resp.status} from MDS",
163
+ "credentialsId" => object_id
164
+ )
165
+ end
166
+ end
167
+
168
+ def log_fetch_err _err
169
+ logger&.info do
170
+ Google::Logging::Message.from(
171
+ message: "MDS did not respond to token request",
172
+ "credentialsId" => object_id
173
+ )
174
+ end
175
+ end
176
+
123
177
  def build_token_hash body, content_type, retrieval_time
124
178
  hash =
125
179
  if ["text/html", "application/text"].include? content_type
126
- { token_type.to_s => body }
180
+ parse_encoded_token body
127
181
  else
128
182
  Signet::OAuth2.parse_credentials body, content_type
129
183
  end
130
- unless @universe_domain_overridden
131
- universe_domain = Google::Cloud.env.lookup_metadata "universe", "universe_domain"
132
- universe_domain = "googleapis.com" if !universe_domain || universe_domain.empty?
133
- hash["universe_domain"] = universe_domain.strip
134
- end
135
- # The response might have been cached, which means expires_in might be
136
- # stale. Update it based on the time since the data was retrieved.
137
- # We also ensure expires_in is conservative; subtracting at least 1
138
- # second to offset any skew from metadata server latency.
139
- if hash["expires_in"].is_a? Numeric
140
- offset = 1 + (Process.clock_gettime(Process::CLOCK_MONOTONIC) - retrieval_time).round
141
- hash["expires_in"] -= offset if offset.positive?
142
- hash["expires_in"] = 0 if hash["expires_in"].negative?
184
+ add_universe_domain_to hash
185
+ adjust_for_stale_expires_in hash, retrieval_time
186
+ hash
187
+ end
188
+
189
+ def parse_encoded_token body
190
+ hash = { token_type.to_s => body }
191
+ if token_type == :id_token
192
+ expires_at = expires_at_from_id_token body
193
+ hash["expires_at"] = expires_at if expires_at
143
194
  end
144
195
  hash
145
196
  end
197
+
198
+ def add_universe_domain_to hash
199
+ return if @universe_domain_overridden
200
+ universe_domain =
201
+ if disable_universe_domain_check
202
+ # TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
203
+ "googleapis.com"
204
+ else
205
+ Google::Cloud.env.lookup_metadata "universe", "universe-domain"
206
+ end
207
+ universe_domain = "googleapis.com" if !universe_domain || universe_domain.empty?
208
+ hash["universe_domain"] = universe_domain.strip
209
+ end
210
+
211
+ # The response might have been cached, which means expires_in might be
212
+ # stale. Update it based on the time since the data was retrieved.
213
+ # We also ensure expires_in is conservative; subtracting at least 1
214
+ # second to offset any skew from metadata server latency.
215
+ def adjust_for_stale_expires_in hash, retrieval_time
216
+ return unless hash["expires_in"].is_a? Numeric
217
+ offset = 1 + (Process.clock_gettime(Process::CLOCK_MONOTONIC) - retrieval_time).round
218
+ hash["expires_in"] -= offset if offset.positive?
219
+ hash["expires_in"] = 0 if hash["expires_in"].negative?
220
+ end
146
221
  end
147
222
  end
148
223
  end
@@ -299,6 +299,12 @@ module Google
299
299
  #
300
300
  attr_reader :quota_project_id
301
301
 
302
+ # @private Temporary; remove when universe domain metadata endpoint is stable (see b/349488459).
303
+ def disable_universe_domain_check
304
+ return false unless @client.respond_to? :disable_universe_domain_check
305
+ @client.disable_universe_domain_check
306
+ end
307
+
302
308
  # @private Delegate client methods to the client object.
303
309
  extend Forwardable
304
310
 
@@ -331,10 +337,13 @@ module Google
331
337
  # @!attribute [rw] universe_domain
332
338
  # @return [String] The universe domain issuing these credentials.
333
339
  #
340
+ # @!attribute [rw] logger
341
+ # @return [Logger] The logger used to log credential operations such as token refresh.
342
+ #
334
343
  def_delegators :@client,
335
344
  :token_credential_uri, :audience,
336
345
  :scope, :issuer, :signing_key, :updater_proc, :target_audience,
337
- :universe_domain, :universe_domain=
346
+ :universe_domain, :universe_domain=, :logger, :logger=
338
347
 
339
348
  ##
340
349
  # Creates a new Credentials instance with the provided auth credentials, and with the default
@@ -343,16 +352,17 @@ module Google
343
352
  # @param [String, Hash, Signet::OAuth2::Client] keyfile
344
353
  # The keyfile can be provided as one of the following:
345
354
  #
346
- # * The path to a JSON keyfile (as a +String+)
347
- # * The contents of a JSON keyfile (as a +Hash+)
348
- # * A +Signet::OAuth2::Client+ object
355
+ # * The path to a JSON keyfile (as a `String`)
356
+ # * The contents of a JSON keyfile (as a `Hash`)
357
+ # * A `Signet::OAuth2::Client` object
349
358
  # @param [Hash] options
350
359
  # The options for configuring the credentials instance. The following is supported:
351
360
  #
352
- # * +:scope+ - the scope for the client
353
- # * +"project_id"+ (and optionally +"project"+) - the project identifier for the client
354
- # * +:connection_builder+ - the connection builder to use for the client
355
- # * +:default_connection+ - the default connection to use for the client
361
+ # * `:scope` - the scope for the client
362
+ # * `project_id` (and optionally `project`) - the project identifier for the client
363
+ # * `:connection_builder` - the connection builder to use for the client
364
+ # * `:default_connection` - the default connection to use for the client
365
+ # * `:logger` - the logger used to log credential operations such as token refresh.
356
366
  #
357
367
  def initialize keyfile, options = {}
358
368
  verify_keyfile_provided! keyfile
@@ -367,8 +377,8 @@ module Google
367
377
  else
368
378
  update_from_filepath keyfile, options
369
379
  end
380
+ setup_logging logger: options.fetch(:logger, :default)
370
381
  @project_id ||= CredentialsLoader.load_gcloud_project_id
371
- @client.fetch_access_token! if @client.needs_access_token?
372
382
  @env_vars = nil
373
383
  @paths = nil
374
384
  @scope = nil
@@ -462,7 +472,8 @@ module Google
462
472
  audience: options[:audience] || audience
463
473
  }
464
474
  client = Google::Auth::DefaultCredentials.make_creds creds_input
465
- new client
475
+ options = options.select { |k, _v| k == :logger }
476
+ new client, options
466
477
  end
467
478
 
468
479
  private_class_method :from_env_vars,
@@ -543,6 +554,23 @@ module Google
543
554
  @quota_project_id ||= json["quota_project_id"]
544
555
  @client = init_client json, options
545
556
  end
557
+
558
+ def setup_logging logger: :default
559
+ return unless @client.respond_to? :logger=
560
+ logging_env = ENV["GOOGLE_SDK_RUBY_LOGGING_GEMS"].to_s.downcase
561
+ if ["false", "none"].include? logging_env
562
+ logger = nil
563
+ elsif @client.logger
564
+ logger = @client.logger
565
+ elsif logger == :default
566
+ logger = nil
567
+ if ["true", "all"].include?(logging_env) || logging_env.split(",").include?("googleauth")
568
+ formatter = Google::Logging::StructuredFormatter.new if Google::Cloud::Env.get.logging_agent_expected?
569
+ logger = Logger.new $stderr, progname: "googleauth", formatter: formatter
570
+ end
571
+ end
572
+ @client.logger = logger
573
+ end
546
574
  end
547
575
  end
548
576
  end
@@ -76,7 +76,7 @@ module Google
76
76
  # The retrieved subject token.
77
77
  #
78
78
  def retrieve_subject_token!
79
- raise NotImplementedError
79
+ raise NoMethodError, "retrieve_subject_token! not implemented"
80
80
  end
81
81
 
82
82
  # Returns whether the credentials represent a workforce pool (True) or
@@ -129,7 +129,7 @@ module Google
129
129
  if @client_id.nil? && @workforce_pool_user_project
130
130
  additional_options = { userProject: @workforce_pool_user_project }
131
131
  end
132
- @sts_client.exchange_token(
132
+ token_request = {
133
133
  audience: @audience,
134
134
  grant_type: STS_GRANT_TYPE,
135
135
  subject_token: retrieve_subject_token!,
@@ -137,10 +137,31 @@ module Google
137
137
  scopes: @service_account_impersonation_url ? IAM_SCOPE : @scope,
138
138
  requested_token_type: STS_REQUESTED_TOKEN_TYPE,
139
139
  additional_options: additional_options
140
- )
140
+ }
141
+ log_token_request token_request
142
+ @sts_client.exchange_token token_request
143
+ end
144
+
145
+ def log_token_request token_request
146
+ logger&.info do
147
+ Google::Logging::Message.from(
148
+ message: "Requesting access token from #{token_request[:grant_type]}",
149
+ "credentialsId" => object_id
150
+ )
151
+ end
152
+ logger&.debug do
153
+ digest = Digest::SHA256.hexdigest token_request[:subject_token].to_s
154
+ loggable_request = token_request.merge subject_token: "(sha256:#{digest})"
155
+ Google::Logging::Message.from(
156
+ message: "Request data",
157
+ "request" => loggable_request,
158
+ "credentialsId" => object_id
159
+ )
160
+ end
141
161
  end
142
162
 
143
163
  def get_impersonated_access_token token, _options = {}
164
+ log_impersonated_token_request token
144
165
  response = connection.post @service_account_impersonation_url do |req|
145
166
  req.headers["Authorization"] = "Bearer #{token}"
146
167
  req.headers["Content-Type"] = "application/json"
@@ -153,6 +174,16 @@ module Google
153
174
 
154
175
  MultiJson.load response.body
155
176
  end
177
+
178
+ def log_impersonated_token_request original_token
179
+ logger&.info do
180
+ digest = Digest::SHA256.hexdigest original_token
181
+ Google::Logging::Message.from(
182
+ message: "Requesting impersonated access token with original token (sha256:#{digest})",
183
+ "credentialsId" => object_id
184
+ )
185
+ end
186
+ end
156
187
  end
157
188
  end
158
189
  end
@@ -168,7 +168,6 @@ module Google
168
168
  aud: nil,
169
169
  azp: nil,
170
170
  iss: OIDC_ISSUERS
171
-
172
171
  verifier = Verifier.new key_source: oidc_key_source,
173
172
  aud: aud,
174
173
  azp: azp,
@@ -206,7 +205,6 @@ module Google
206
205
  aud: nil,
207
206
  azp: nil,
208
207
  iss: IAP_ISSUERS
209
-
210
208
  verifier = Verifier.new key_source: iap_key_source,
211
209
  aud: aud,
212
210
  azp: azp,
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require "google/logging/message"
15
16
  require "googleauth/signet"
16
17
  require "googleauth/credentials_loader"
17
18
  require "googleauth/json_key_reader"
@@ -123,6 +124,7 @@ module Google
123
124
  }
124
125
  key_io = StringIO.new MultiJson.dump(cred_json)
125
126
  alt = ServiceAccountJwtHeaderCredentials.make_creds json_key_io: key_io, scope: scope
127
+ alt.logger = logger
126
128
  alt.apply! a_hash
127
129
  end
128
130
  end
@@ -147,6 +149,7 @@ module Google
147
149
  attr_reader :project_id
148
150
  attr_reader :quota_project_id
149
151
  attr_accessor :universe_domain
152
+ attr_accessor :logger
150
153
 
151
154
  # Create a ServiceAccountJwtHeaderCredentials.
152
155
  #
@@ -187,10 +190,14 @@ module Google
187
190
  return a_hash if jwt_aud_uri.nil? && @scope.nil?
188
191
  jwt_token = new_jwt_token jwt_aud_uri, opts
189
192
  a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}"
193
+ logger&.debug do
194
+ hash = Digest::SHA256.hexdigest jwt_token
195
+ Google::Logging::Message.from message: "Sending JWT auth token. (sha256:#{hash})"
196
+ end
190
197
  a_hash
191
198
  end
192
199
 
193
- # Returns a clone of a_hash updated with the authoriation header
200
+ # Returns a clone of a_hash updated with the authorization header
194
201
  def apply a_hash, opts = {}
195
202
  a_copy = a_hash.clone
196
203
  apply! a_copy, opts
@@ -219,6 +226,10 @@ module Google
219
226
  assertion["scope"] = Array(@scope).join " " if @scope
220
227
  assertion["aud"] = jwt_aud_uri if jwt_aud_uri
221
228
 
229
+ logger&.debug do
230
+ Google::Logging::Message.from message: "JWT assertion: #{assertion}"
231
+ end
232
+
222
233
  JWT.encode assertion, @signing_key, SIGNING_ALGORITHM
223
234
  end
224
235
 
@@ -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,6 +31,8 @@ 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
@@ -61,6 +65,24 @@ module Signet
61
65
  info
62
66
  end
63
67
 
68
+ alias googleauth_orig_generate_access_token_request generate_access_token_request
69
+ def generate_access_token_request options = {}
70
+ parameters = googleauth_orig_generate_access_token_request options
71
+ logger&.info do
72
+ Google::Logging::Message.from(
73
+ message: "Requesting access token from #{parameters['grant_type']}",
74
+ "credentialsId" => object_id
75
+ )
76
+ end
77
+ logger&.debug do
78
+ Google::Logging::Message.from(
79
+ message: "Token fetch params: #{parameters}",
80
+ "credentialsId" => object_id
81
+ )
82
+ end
83
+ parameters
84
+ end
85
+
64
86
  def build_default_connection
65
87
  if !defined?(@connection_info)
66
88
  nil
@@ -75,20 +97,81 @@ module Signet
75
97
  retry_count = 0
76
98
 
77
99
  begin
78
- yield
100
+ yield.tap { |resp| log_response resp }
79
101
  rescue StandardError => e
80
- raise e if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError)
102
+ if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError)
103
+ log_auth_error e
104
+ raise e
105
+ end
81
106
 
82
107
  if retry_count < max_retry_count
108
+ log_transient_error e
83
109
  retry_count += 1
84
110
  sleep retry_count * 0.3
85
111
  retry
86
112
  else
113
+ log_retries_exhausted e
87
114
  msg = "Unexpected error: #{e.inspect}"
88
115
  raise Signet::AuthorizationError, msg
89
116
  end
90
117
  end
91
118
  end
119
+
120
+ private
121
+
122
+ def expires_at_from_id_token id_token
123
+ match = /^[\w=-]+\.([\w=-]+)\.[\w=-]+$/.match id_token.to_s
124
+ return unless match
125
+ json = JSON.parse Base64.urlsafe_decode64 match[1]
126
+ return unless json.key? "exp"
127
+ Time.at json["exp"].to_i
128
+ rescue StandardError
129
+ # Shouldn't happen unless we get a garbled ID token
130
+ nil
131
+ end
132
+
133
+ def log_response token_response
134
+ response_hash = JSON.parse token_response rescue {}
135
+ if response_hash["access_token"]
136
+ digest = Digest::SHA256.hexdigest response_hash["access_token"]
137
+ response_hash["access_token"] = "(sha256:#{digest})"
138
+ end
139
+ if response_hash["id_token"]
140
+ digest = Digest::SHA256.hexdigest response_hash["id_token"]
141
+ response_hash["id_token"] = "(sha256:#{digest})"
142
+ end
143
+ Google::Logging::Message.from(
144
+ message: "Received auth token response: #{response_hash}",
145
+ "credentialsId" => object_id
146
+ )
147
+ end
148
+
149
+ def log_auth_error err
150
+ logger&.info do
151
+ Google::Logging::Message.from(
152
+ message: "Auth error when fetching auth token: #{err}",
153
+ "credentialsId" => object_id
154
+ )
155
+ end
156
+ end
157
+
158
+ def log_transient_error err
159
+ logger&.info do
160
+ Google::Logging::Message.from(
161
+ message: "Transient error when fetching auth token: #{err}",
162
+ "credentialsId" => object_id
163
+ )
164
+ end
165
+ end
166
+
167
+ def log_retries_exhausted err
168
+ logger&.info do
169
+ Google::Logging::Message.from(
170
+ message: "Exhausted retries when fetching auth token: #{err}",
171
+ "credentialsId" => object_id
172
+ )
173
+ end
174
+ end
92
175
  end
93
176
  end
94
177
  end
@@ -29,7 +29,7 @@ module Google
29
29
  # @return [String]
30
30
  # The loaded token data.
31
31
  def load _id
32
- raise "Not implemented"
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 "Not implemented"
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 "Not implemented"
50
+ raise NoMethodError, "delete not implemented"
51
51
  end
52
52
  end
53
53
  end
@@ -16,6 +16,6 @@ module Google
16
16
  # Module Auth provides classes that provide Google-specific authorization
17
17
  # used to access Google APIs.
18
18
  module Auth
19
- VERSION = "1.11.0".freeze
19
+ VERSION = "1.12.2".freeze
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: googleauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Emiola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-14 00:00:00.000000000 Z
11
+ date: 2024-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -36,14 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '2.1'
39
+ version: '2.2'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.1'
46
+ version: '2.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: google-logging-utils
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.1'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: jwt
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -186,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
200
  - !ruby/object:Gem::Version
187
201
  version: '0'
188
202
  requirements: []
189
- rubygems_version: 3.5.3
203
+ rubygems_version: 3.5.23
190
204
  signing_key:
191
205
  specification_version: 4
192
206
  summary: Google Auth Library for Ruby