googleauth 1.13.1 → 1.15.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/Credentials.md +106 -0
  4. data/Errors.md +152 -0
  5. data/README.md +1 -1
  6. data/lib/googleauth/api_key.rb +164 -0
  7. data/lib/googleauth/application_default.rb +3 -1
  8. data/lib/googleauth/base_client.rb +5 -0
  9. data/lib/googleauth/bearer_token.rb +162 -0
  10. data/lib/googleauth/client_id.rb +9 -5
  11. data/lib/googleauth/compute_engine.rb +65 -19
  12. data/lib/googleauth/credentials.rb +23 -6
  13. data/lib/googleauth/credentials_loader.rb +11 -6
  14. data/lib/googleauth/default_credentials.rb +18 -6
  15. data/lib/googleauth/errors.rb +117 -0
  16. data/lib/googleauth/external_account/aws_credentials.rb +85 -18
  17. data/lib/googleauth/external_account/base_credentials.rb +31 -2
  18. data/lib/googleauth/external_account/external_account_utils.rb +15 -4
  19. data/lib/googleauth/external_account/identity_pool_credentials.rb +40 -15
  20. data/lib/googleauth/external_account/pluggable_credentials.rb +34 -19
  21. data/lib/googleauth/external_account.rb +30 -6
  22. data/lib/googleauth/helpers/connection.rb +7 -1
  23. data/lib/googleauth/iam.rb +19 -3
  24. data/lib/googleauth/id_tokens/errors.rb +13 -7
  25. data/lib/googleauth/id_tokens/key_sources.rb +13 -7
  26. data/lib/googleauth/id_tokens/verifier.rb +2 -3
  27. data/lib/googleauth/id_tokens.rb +4 -4
  28. data/lib/googleauth/impersonated_service_account.rb +64 -17
  29. data/lib/googleauth/json_key_reader.rb +11 -2
  30. data/lib/googleauth/oauth2/sts_client.rb +9 -4
  31. data/lib/googleauth/scope_util.rb +1 -1
  32. data/lib/googleauth/service_account.rb +17 -160
  33. data/lib/googleauth/service_account_jwt_header.rb +187 -0
  34. data/lib/googleauth/signet.rb +24 -6
  35. data/lib/googleauth/user_authorizer.rb +35 -7
  36. data/lib/googleauth/user_refresh.rb +25 -7
  37. data/lib/googleauth/version.rb +1 -1
  38. data/lib/googleauth/web_user_authorizer.rb +46 -9
  39. data/lib/googleauth.rb +8 -0
  40. metadata +14 -8
@@ -0,0 +1,187 @@
1
+ # Copyright 2025 Google, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "google/logging/message"
16
+ require "googleauth/credentials_loader"
17
+ require "googleauth/json_key_reader"
18
+ require "jwt"
19
+
20
+ module Google
21
+ # Module Auth provides classes that provide Google-specific authorization
22
+ # used to access Google APIs.
23
+ module Auth
24
+ # Authenticates requests using Google's Service Account credentials via
25
+ # JWT Header.
26
+ #
27
+ # This class allows authorizing requests for service accounts directly
28
+ # from credentials from a json key file downloaded from the developer
29
+ # console (via 'Generate new Json Key'). It is not part of any OAuth2
30
+ # flow, rather it creates a JWT and sends that as a credential.
31
+ #
32
+ # cf [Application Default Credentials](https://cloud.google.com/docs/authentication/production)
33
+ class ServiceAccountJwtHeaderCredentials
34
+ JWT_AUD_URI_KEY = :jwt_aud_uri
35
+ AUTH_METADATA_KEY = Google::Auth::BaseClient::AUTH_METADATA_KEY
36
+ TOKEN_CRED_URI = "https://www.googleapis.com/oauth2/v4/token".freeze
37
+ SIGNING_ALGORITHM = "RS256".freeze
38
+ EXPIRY = 60
39
+
40
+ extend CredentialsLoader
41
+ extend JsonKeyReader
42
+
43
+ attr_reader :project_id
44
+ attr_reader :quota_project_id
45
+ attr_accessor :universe_domain
46
+ attr_accessor :logger
47
+
48
+ # Create a ServiceAccountJwtHeaderCredentials.
49
+ #
50
+ # @param json_key_io [IO] An IO object containing the JSON key
51
+ # @param scope [string|array|nil] the scope(s) to access
52
+ def self.make_creds options = {}
53
+ json_key_io, scope = options.values_at :json_key_io, :scope
54
+ new json_key_io: json_key_io, scope: scope
55
+ end
56
+
57
+ # Initializes a ServiceAccountJwtHeaderCredentials.
58
+ #
59
+ # @param json_key_io [IO] An IO object containing the JSON key
60
+ def initialize options = {}
61
+ json_key_io = options[:json_key_io]
62
+ if json_key_io
63
+ @private_key, @issuer, @project_id, @quota_project_id, @universe_domain =
64
+ self.class.read_json_key json_key_io
65
+ else
66
+ @private_key = options.key?(:private_key) ? options[:private_key] : ENV[CredentialsLoader::PRIVATE_KEY_VAR]
67
+ @issuer = options.key?(:issuer) ? options[:issuer] : ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
68
+ @project_id = options.key?(:project_id) ? options[:project_id] : ENV[CredentialsLoader::PROJECT_ID_VAR]
69
+ @quota_project_id = options[:quota_project_id] if options.key? :quota_project_id
70
+ @universe_domain = options[:universe_domain] if options.key? :universe_domain
71
+ end
72
+ @universe_domain ||= "googleapis.com"
73
+ @project_id ||= CredentialsLoader.load_gcloud_project_id
74
+ @signing_key = OpenSSL::PKey::RSA.new @private_key
75
+ @scope = options[:scope] if options.key? :scope
76
+ @logger = options[:logger] if options.key? :logger
77
+ end
78
+
79
+ # Creates a duplicate of these credentials
80
+ #
81
+ # @param options [Hash] Overrides for the credentials parameters.
82
+ # The following keys are recognized
83
+ # * `private key` the private key in string form
84
+ # * `issuer` the SA issuer
85
+ # * `scope` the scope(s) to access
86
+ # * `project_id` the project id to use during the authentication
87
+ # * `quota_project_id` the quota project id to use
88
+ # * `universe_domain` the universe domain of the credentials
89
+ def duplicate options = {}
90
+ options = deep_hash_normalize options
91
+
92
+ options = {
93
+ private_key: @private_key,
94
+ issuer: @issuer,
95
+ scope: @scope,
96
+ project_id: project_id,
97
+ quota_project_id: quota_project_id,
98
+ universe_domain: universe_domain,
99
+ logger: logger
100
+ }.merge(options)
101
+
102
+ self.class.new options
103
+ end
104
+
105
+ # Construct a jwt token if the JWT_AUD_URI key is present in the input
106
+ # hash.
107
+ #
108
+ # The jwt token is used as the value of a 'Bearer '.
109
+ def apply! a_hash, opts = {}
110
+ jwt_aud_uri = a_hash.delete JWT_AUD_URI_KEY
111
+ return a_hash if jwt_aud_uri.nil? && @scope.nil?
112
+ jwt_token = new_jwt_token jwt_aud_uri, opts
113
+ a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}"
114
+ logger&.debug do
115
+ hash = Digest::SHA256.hexdigest jwt_token
116
+ Google::Logging::Message.from message: "Sending JWT auth token. (sha256:#{hash})"
117
+ end
118
+ a_hash
119
+ end
120
+
121
+ # Returns a clone of a_hash updated with the authorization header
122
+ def apply a_hash, opts = {}
123
+ a_copy = a_hash.clone
124
+ apply! a_copy, opts
125
+ a_copy
126
+ end
127
+
128
+ # Returns a reference to the #apply method, suitable for passing as
129
+ # a closure
130
+ def updater_proc
131
+ proc { |a_hash, opts = {}| apply a_hash, opts }
132
+ end
133
+
134
+ # Creates a jwt uri token.
135
+ def new_jwt_token jwt_aud_uri = nil, options = {}
136
+ now = Time.new
137
+ skew = options[:skew] || 60
138
+ assertion = {
139
+ "iss" => @issuer,
140
+ "sub" => @issuer,
141
+ "exp" => (now + EXPIRY).to_i,
142
+ "iat" => (now - skew).to_i
143
+ }
144
+
145
+ jwt_aud_uri = nil if @scope
146
+
147
+ assertion["scope"] = Array(@scope).join " " if @scope
148
+ assertion["aud"] = jwt_aud_uri if jwt_aud_uri
149
+
150
+ logger&.debug do
151
+ Google::Logging::Message.from message: "JWT assertion: #{assertion}"
152
+ end
153
+
154
+ JWT.encode assertion, @signing_key, SIGNING_ALGORITHM
155
+ end
156
+
157
+ # Duck-types the corresponding method from BaseClient
158
+ def needs_access_token?
159
+ false
160
+ end
161
+
162
+ # Returns the client email as the principal for service account JWT header credentials
163
+ # @private
164
+ # @return [String] the email address of the service account
165
+ def principal
166
+ @issuer
167
+ end
168
+
169
+ private
170
+
171
+ def deep_hash_normalize old_hash
172
+ sym_hash = {}
173
+ old_hash&.each { |k, v| sym_hash[k.to_sym] = recursive_hash_normalize_keys v }
174
+ sym_hash
175
+ end
176
+
177
+ # Convert all keys in this hash (nested) to symbols for uniform retrieval
178
+ def recursive_hash_normalize_keys val
179
+ if val.is_a? Hash
180
+ deep_hash_normalize val
181
+ else
182
+ val
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -16,6 +16,7 @@ require "base64"
16
16
  require "json"
17
17
  require "signet/oauth_2/client"
18
18
  require "googleauth/base_client"
19
+ require "googleauth/errors"
19
20
 
20
21
  module Signet
21
22
  # OAuth2 supports OAuth2 authentication.
@@ -109,17 +110,29 @@ module Signet
109
110
  end
110
111
  end
111
112
 
113
+ # rubocop:disable Metrics/MethodLength
114
+
115
+ # Retries the provided block with exponential backoff, handling and wrapping errors.
116
+ #
117
+ # @param [Integer] max_retry_count The maximum number of retries before giving up
118
+ # @yield The block to execute and potentially retry
119
+ # @return [Object] The result of the block if successful
120
+ # @raise [Google::Auth::AuthorizationError] If a Signet::AuthorizationError occurs or if retries are exhausted
121
+ # @raise [Google::Auth::ParseError] If a Signet::ParseError occurs during token parsing
112
122
  def retry_with_error max_retry_count = 5
113
123
  retry_count = 0
114
124
 
115
125
  begin
116
126
  yield.tap { |resp| log_response resp }
127
+ rescue Signet::AuthorizationError, Signet::ParseError => e
128
+ log_auth_error e
129
+ error_class = e.is_a?(Signet::ParseError) ? Google::Auth::ParseError : Google::Auth::AuthorizationError
130
+ raise error_class.with_details(
131
+ e.message,
132
+ credential_type_name: self.class.name,
133
+ principal: respond_to?(:principal) ? principal : :signet_client
134
+ )
117
135
  rescue StandardError => e
118
- if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError)
119
- log_auth_error e
120
- raise e
121
- end
122
-
123
136
  if retry_count < max_retry_count
124
137
  log_transient_error e
125
138
  retry_count += 1
@@ -128,10 +141,15 @@ module Signet
128
141
  else
129
142
  log_retries_exhausted e
130
143
  msg = "Unexpected error: #{e.inspect}"
131
- raise Signet::AuthorizationError, msg
144
+ raise Google::Auth::AuthorizationError.with_details(
145
+ msg,
146
+ credential_type_name: self.class.name,
147
+ principal: respond_to?(:principal) ? principal : :signet_client
148
+ )
132
149
  end
133
150
  end
134
151
  end
152
+ # rubocop:enable Metrics/MethodLength
135
153
 
136
154
  # Creates a duplicate of these credentials
137
155
  # without the Signet::OAuth2::Client-specific
@@ -63,12 +63,14 @@ module Google
63
63
  # @param [String] code_verifier
64
64
  # Random string of 43-128 chars used to verify the key exchange using
65
65
  # PKCE.
66
+ # @raise [Google::Auth::InitializationError]
67
+ # If client_id is nil or scope is nil
66
68
  def initialize client_id, scope, token_store,
67
69
  legacy_callback_uri = nil,
68
70
  callback_uri: nil,
69
71
  code_verifier: nil
70
- raise NIL_CLIENT_ID_ERROR if client_id.nil?
71
- raise NIL_SCOPE_ERROR if scope.nil?
72
+ raise InitializationError, NIL_CLIENT_ID_ERROR if client_id.nil?
73
+ raise InitializationError, NIL_SCOPE_ERROR if scope.nil?
72
74
 
73
75
  @client_id = client_id
74
76
  @scope = Array(scope)
@@ -133,14 +135,19 @@ module Google
133
135
  # the requested scopes
134
136
  # @return [Google::Auth::UserRefreshCredentials]
135
137
  # Stored credentials, nil if none present
138
+ # @raise [Google::Auth::CredentialsError]
139
+ # If the client ID in the stored token doesn't match the configured client ID
136
140
  def get_credentials user_id, scope = nil
137
141
  saved_token = stored_token user_id
138
142
  return nil if saved_token.nil?
139
143
  data = MultiJson.load saved_token
140
144
 
141
145
  if data.fetch("client_id", @client_id.id) != @client_id.id
142
- raise format(MISMATCHED_CLIENT_ID_ERROR,
143
- data["client_id"], @client_id.id)
146
+ raise CredentialsError.with_details(
147
+ format(MISMATCHED_CLIENT_ID_ERROR, data["client_id"], @client_id.id),
148
+ credential_type_name: self.class.name,
149
+ principal: principal
150
+ )
144
151
  end
145
152
 
146
153
  credentials = UserRefreshCredentials.new(
@@ -240,6 +247,8 @@ module Google
240
247
  # Unique ID of the user for loading/storing credentials.
241
248
  # @param [Google::Auth::UserRefreshCredentials] credentials
242
249
  # Credentials to store.
250
+ # @return [Google::Auth::UserRefreshCredentials]
251
+ # The stored credentials
243
252
  def store_credentials user_id, credentials
244
253
  json = MultiJson.dump(
245
254
  client_id: credentials.client_id,
@@ -269,6 +278,15 @@ module Google
269
278
  SecureRandom.alphanumeric random_number
270
279
  end
271
280
 
281
+ # Returns the principal identifier for this authorizer
282
+ # The client ID is used as the principal for user authorizers
283
+ #
284
+ # @private
285
+ # @return [String] The client ID associated with this authorizer
286
+ def principal
287
+ @client_id.id
288
+ end
289
+
272
290
  private
273
291
 
274
292
  # @private Fetch stored token with given user_id
@@ -276,9 +294,11 @@ module Google
276
294
  # @param [String] user_id
277
295
  # Unique ID of the user for loading/storing credentials.
278
296
  # @return [String] The saved token from @token_store
297
+ # @raise [Google::Auth::InitializationError]
298
+ # If user_id is nil or token_store is nil
279
299
  def stored_token user_id
280
- raise NIL_USER_ID_ERROR if user_id.nil?
281
- raise NIL_TOKEN_STORE_ERROR if @token_store.nil?
300
+ raise InitializationError, NIL_USER_ID_ERROR if user_id.nil?
301
+ raise InitializationError, NIL_TOKEN_STORE_ERROR if @token_store.nil?
282
302
 
283
303
  @token_store.load user_id
284
304
  end
@@ -303,9 +323,17 @@ module Google
303
323
  # Absolute URL to resolve the callback against if necessary.
304
324
  # @return [String]
305
325
  # Redirect URI
326
+ # @raise [Google::Auth::CredentialsError]
327
+ # If the callback URI is relative and base_url is nil or not absolute
306
328
  def redirect_uri_for base_url
307
329
  return @callback_uri if uri_is_postmessage?(@callback_uri) || !URI(@callback_uri).scheme.nil?
308
- raise format(MISSING_ABSOLUTE_URL_ERROR, @callback_uri) if base_url.nil? || URI(base_url).scheme.nil?
330
+ if base_url.nil? || URI(base_url).scheme.nil?
331
+ raise CredentialsError.with_details(
332
+ format(MISSING_ABSOLUTE_URL_ERROR, @callback_uri),
333
+ credential_type_name: self.class.name,
334
+ principal: principal
335
+ )
336
+ end
309
337
  URI.join(base_url, @callback_uri).to_s
310
338
  end
311
339
 
@@ -12,9 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require "googleauth/signet"
16
15
  require "googleauth/credentials_loader"
16
+ require "googleauth/errors"
17
17
  require "googleauth/scope_util"
18
+ require "googleauth/signet"
18
19
  require "multi_json"
19
20
 
20
21
  module Google
@@ -40,7 +41,7 @@ module Google
40
41
 
41
42
  # Create a UserRefreshCredentials.
42
43
  #
43
- # @param json_key_io [IO] an IO from which the JSON key can be read
44
+ # @param json_key_io [IO] An IO object containing the JSON key
44
45
  # @param scope [string|array|nil] the scope(s) to access
45
46
  def self.make_creds options = {}
46
47
  json_key_io, scope = options.values_at :json_key_io, :scope
@@ -64,13 +65,16 @@ module Google
64
65
  .configure_connection(options)
65
66
  end
66
67
 
67
- # Reads the client_id, client_secret and refresh_token fields from the
68
- # JSON key.
68
+ # Reads a JSON key from an IO object and extracts required fields.
69
+ #
70
+ # @param [IO] json_key_io An IO object containing the JSON key
71
+ # @return [Hash] The parsed JSON key
72
+ # @raise [Google::Auth::InitializationError] If the JSON is missing required fields
69
73
  def self.read_json_key json_key_io
70
74
  json_key = MultiJson.load json_key_io.read
71
75
  wanted = ["client_id", "client_secret", "refresh_token"]
72
76
  wanted.each do |key|
73
- raise "the json is missing the #{key} field" unless json_key.key? key
77
+ raise InitializationError, "the json is missing the #{key} field" unless json_key.key? key
74
78
  end
75
79
  json_key
76
80
  end
@@ -106,6 +110,10 @@ module Google
106
110
  end
107
111
 
108
112
  # Revokes the credential
113
+ #
114
+ # @param [Hash] options Options for revoking the credential
115
+ # @option options [Faraday::Connection] :connection The connection to use
116
+ # @raise [Google::Auth::AuthorizationError] If the revocation request fails
109
117
  def revoke! options = {}
110
118
  c = options[:connection] || Faraday.default_connection
111
119
 
@@ -117,8 +125,11 @@ module Google
117
125
  self.refresh_token = nil
118
126
  self.expires_at = 0
119
127
  else
120
- raise(Signet::AuthorizationError,
121
- "Unexpected error code #{resp.status}")
128
+ raise AuthorizationError.with_details(
129
+ "Unexpected error code #{resp.status}",
130
+ credential_type_name: self.class.name,
131
+ principal: principal
132
+ )
122
133
  end
123
134
  end
124
135
  end
@@ -157,6 +168,13 @@ module Google
157
168
 
158
169
  self
159
170
  end
171
+
172
+ # Returns the client ID as the principal for user refresh credentials
173
+ # @private
174
+ # @return [String, Symbol] the client ID or :user_refresh if not available
175
+ def principal
176
+ @client_id || :user_refresh
177
+ end
160
178
  end
161
179
  end
162
180
  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.13.1".freeze
19
+ VERSION = "1.15.0".freeze
20
20
  end
21
21
  end
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require "multi_json"
16
+ require "googleauth/errors"
16
17
  require "googleauth/signet"
17
18
  require "googleauth/user_authorizer"
18
19
  require "googleauth/user_refresh"
@@ -79,6 +80,8 @@ module Google
79
80
  #
80
81
  # @param [Rack::Request] request
81
82
  # Current request
83
+ # @return [String, nil]
84
+ # Redirect URI if successfully extracted, nil otherwise
82
85
  def self.handle_auth_callback_deferred request
83
86
  callback_state, redirect_uri = extract_callback_state request
84
87
  request.session[CALLBACK_STATE_KEY] = MultiJson.dump callback_state
@@ -151,11 +154,13 @@ module Google
151
154
  # Optional key-values to be returned to the oauth callback.
152
155
  # @return [String]
153
156
  # Authorization url
157
+ # @raise [Google::Auth::InitializationError]
158
+ # If request is nil or request.session is nil
154
159
  def get_authorization_url options = {}
155
160
  options = options.dup
156
161
  request = options[:request]
157
- raise NIL_REQUEST_ERROR if request.nil?
158
- raise NIL_SESSION_ERROR if request.session.nil?
162
+ raise InitializationError, NIL_REQUEST_ERROR if request.nil?
163
+ raise InitializationError, NIL_SESSION_ERROR if request.session.nil?
159
164
 
160
165
  state = options[:state] || {}
161
166
 
@@ -181,9 +186,9 @@ module Google
181
186
  # requested scopes
182
187
  # @return [Google::Auth::UserRefreshCredentials]
183
188
  # Stored credentials, nil if none present
184
- # @raise [Signet::AuthorizationError]
185
- # May raise an error if an authorization code is present in the session
186
- # and exchange of the code fails
189
+ # @raise [Google::Auth::AuthorizationError]
190
+ # If the authorization code is missing, there's an error in the request,
191
+ # or the state token doesn't match
187
192
  def get_credentials user_id, request = nil, scope = nil
188
193
  if request&.session&.key? CALLBACK_STATE_KEY
189
194
  # Note - in theory, no need to check required scope as this is
@@ -202,6 +207,12 @@ module Google
202
207
  end
203
208
  end
204
209
 
210
+ # Extract the callback state from the request
211
+ #
212
+ # @param [Rack::Request] request
213
+ # Current request
214
+ # @return [Array<Hash, String>]
215
+ # Callback state and redirect URI
205
216
  def self.extract_callback_state request
206
217
  state = MultiJson.load(request.params[STATE_PARAM] || "{}")
207
218
  redirect_uri = state[CURRENT_URI_KEY]
@@ -214,6 +225,15 @@ module Google
214
225
  [callback_state, redirect_uri]
215
226
  end
216
227
 
228
+ # Returns the principal identifier for this web authorizer
229
+ # This is a class method that returns a symbol since
230
+ # we might not have a client_id in the static callback context
231
+ #
232
+ # @return [Symbol] The symbol for web user authorization
233
+ def self.principal
234
+ :web_user_authorization
235
+ end
236
+
217
237
  # Verifies the results of an authorization callback
218
238
  #
219
239
  # @param [Hash] state
@@ -224,13 +244,30 @@ module Google
224
244
  # Error message if failed
225
245
  # @param [Rack::Request] request
226
246
  # Current request
247
+ # @raise [Google::Auth::AuthorizationError]
248
+ # If the authorization code is missing, there's an error in the callback state,
249
+ # or the state token doesn't match
227
250
  def self.validate_callback_state state, request
228
- raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR if state[AUTH_CODE_KEY].nil?
251
+ if state[AUTH_CODE_KEY].nil?
252
+ raise AuthorizationError.with_details(
253
+ MISSING_AUTH_CODE_ERROR,
254
+ credential_type_name: name,
255
+ principal: principal
256
+ )
257
+ end
258
+
229
259
  if state[ERROR_CODE_KEY]
230
- raise Signet::AuthorizationError,
231
- format(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY])
260
+ raise AuthorizationError.with_details(
261
+ format(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY]),
262
+ credential_type_name: name,
263
+ principal: principal
264
+ )
232
265
  elsif request.session[XSRF_KEY] != state[SESSION_ID_KEY]
233
- raise Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR
266
+ raise AuthorizationError.with_details(
267
+ INVALID_STATE_TOKEN_ERROR,
268
+ credential_type_name: name,
269
+ principal: principal
270
+ )
234
271
  end
235
272
  end
236
273
 
data/lib/googleauth.rb CHANGED
@@ -13,9 +13,17 @@
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/errors"
22
+ require "googleauth/external_account"
19
23
  require "googleauth/id_tokens"
24
+ require "googleauth/impersonated_service_account"
25
+ require "googleauth/service_account"
26
+ require "googleauth/service_account_jwt_header"
20
27
  require "googleauth/user_authorizer"
28
+ require "googleauth/user_refresh"
21
29
  require "googleauth/web_user_authorizer"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: googleauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.1
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
- - Tim Emiola
7
+ - Google LLC
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '1.4'
67
67
  - - "<"
68
68
  - !ruby/object:Gem::Version
69
- version: '3.0'
69
+ version: '4.0'
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '1.4'
77
77
  - - "<"
78
78
  - !ruby/object:Gem::Version
79
- version: '3.0'
79
+ version: '4.0'
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: multi_json
82
82
  requirement: !ruby/object:Gem::Requirement
@@ -134,7 +134,7 @@ dependencies:
134
134
  description: Implements simple authorization for accessing Google APIs, and provides
135
135
  support for Application Default Credentials.
136
136
  email:
137
- - temiola@google.com
137
+ - googleapis-packages@google.com
138
138
  executables: []
139
139
  extensions: []
140
140
  extra_rdoc_files: []
@@ -142,17 +142,22 @@ files:
142
142
  - ".yardopts"
143
143
  - CHANGELOG.md
144
144
  - CODE_OF_CONDUCT.md
145
+ - Credentials.md
146
+ - Errors.md
145
147
  - LICENSE
146
148
  - README.md
147
149
  - SECURITY.md
148
150
  - lib/googleauth.rb
151
+ - lib/googleauth/api_key.rb
149
152
  - lib/googleauth/application_default.rb
150
153
  - lib/googleauth/base_client.rb
154
+ - lib/googleauth/bearer_token.rb
151
155
  - lib/googleauth/client_id.rb
152
156
  - lib/googleauth/compute_engine.rb
153
157
  - lib/googleauth/credentials.rb
154
158
  - lib/googleauth/credentials_loader.rb
155
159
  - lib/googleauth/default_credentials.rb
160
+ - lib/googleauth/errors.rb
156
161
  - lib/googleauth/external_account.rb
157
162
  - lib/googleauth/external_account/aws_credentials.rb
158
163
  - lib/googleauth/external_account/base_credentials.rb
@@ -170,6 +175,7 @@ files:
170
175
  - lib/googleauth/oauth2/sts_client.rb
171
176
  - lib/googleauth/scope_util.rb
172
177
  - lib/googleauth/service_account.rb
178
+ - lib/googleauth/service_account_jwt_header.rb
173
179
  - lib/googleauth/signet.rb
174
180
  - lib/googleauth/stores/file_token_store.rb
175
181
  - lib/googleauth/stores/redis_token_store.rb
@@ -192,14 +198,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
198
  requirements:
193
199
  - - ">="
194
200
  - !ruby/object:Gem::Version
195
- version: '2.7'
201
+ version: '3.0'
196
202
  required_rubygems_version: !ruby/object:Gem::Requirement
197
203
  requirements:
198
204
  - - ">="
199
205
  - !ruby/object:Gem::Version
200
206
  version: '0'
201
207
  requirements: []
202
- rubygems_version: 3.6.2
208
+ rubygems_version: 3.6.9
203
209
  specification_version: 4
204
210
  summary: Google Auth Library for Ruby
205
211
  test_files: []