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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/Credentials.md +106 -0
- data/Errors.md +152 -0
- data/README.md +1 -1
- data/lib/googleauth/api_key.rb +164 -0
- data/lib/googleauth/application_default.rb +3 -1
- data/lib/googleauth/base_client.rb +5 -0
- data/lib/googleauth/bearer_token.rb +162 -0
- data/lib/googleauth/client_id.rb +9 -5
- data/lib/googleauth/compute_engine.rb +65 -19
- data/lib/googleauth/credentials.rb +23 -6
- data/lib/googleauth/credentials_loader.rb +11 -6
- data/lib/googleauth/default_credentials.rb +18 -6
- data/lib/googleauth/errors.rb +117 -0
- data/lib/googleauth/external_account/aws_credentials.rb +85 -18
- data/lib/googleauth/external_account/base_credentials.rb +31 -2
- data/lib/googleauth/external_account/external_account_utils.rb +15 -4
- data/lib/googleauth/external_account/identity_pool_credentials.rb +40 -15
- data/lib/googleauth/external_account/pluggable_credentials.rb +34 -19
- data/lib/googleauth/external_account.rb +30 -6
- data/lib/googleauth/helpers/connection.rb +7 -1
- data/lib/googleauth/iam.rb +19 -3
- data/lib/googleauth/id_tokens/errors.rb +13 -7
- data/lib/googleauth/id_tokens/key_sources.rb +13 -7
- data/lib/googleauth/id_tokens/verifier.rb +2 -3
- data/lib/googleauth/id_tokens.rb +4 -4
- data/lib/googleauth/impersonated_service_account.rb +64 -17
- data/lib/googleauth/json_key_reader.rb +11 -2
- data/lib/googleauth/oauth2/sts_client.rb +9 -4
- data/lib/googleauth/scope_util.rb +1 -1
- data/lib/googleauth/service_account.rb +17 -160
- data/lib/googleauth/service_account_jwt_header.rb +187 -0
- data/lib/googleauth/signet.rb +24 -6
- data/lib/googleauth/user_authorizer.rb +35 -7
- data/lib/googleauth/user_refresh.rb +25 -7
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +46 -9
- data/lib/googleauth.rb +8 -0
- metadata +14 -8
data/lib/googleauth/client_id.rb
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
|
15
15
|
require "multi_json"
|
16
16
|
require "googleauth/credentials_loader"
|
17
|
+
require "googleauth/errors"
|
17
18
|
|
18
19
|
module Google
|
19
20
|
module Auth
|
@@ -62,10 +63,11 @@ module Google
|
|
62
63
|
# @note Direct instantiation is discouraged to avoid embedding IDs
|
63
64
|
# and secrets in source. See {#from_file} to load from
|
64
65
|
# `client_secrets.json` files.
|
66
|
+
# @raise [Google::Auth::InitializationError] If id or secret is nil
|
65
67
|
#
|
66
68
|
def initialize id, secret
|
67
|
-
raise "Client id can not be nil" if id.nil?
|
68
|
-
raise "Client secret can not be nil" if secret.nil?
|
69
|
+
raise InitializationError, "Client id can not be nil" if id.nil?
|
70
|
+
raise InitializationError, "Client secret can not be nil" if secret.nil?
|
69
71
|
@id = id
|
70
72
|
@secret = secret
|
71
73
|
end
|
@@ -77,9 +79,10 @@ module Google
|
|
77
79
|
# @param [String, File] file
|
78
80
|
# Path of file to read from
|
79
81
|
# @return [Google::Auth::ClientID]
|
82
|
+
# @raise [Google::Auth::InitializationError] If file is nil
|
80
83
|
#
|
81
84
|
def self.from_file file
|
82
|
-
raise "File can not be nil." if file.nil?
|
85
|
+
raise InitializationError, "File can not be nil." if file.nil?
|
83
86
|
File.open file.to_s do |f|
|
84
87
|
json = f.read
|
85
88
|
config = MultiJson.load json
|
@@ -94,11 +97,12 @@ module Google
|
|
94
97
|
# @param [hash] config
|
95
98
|
# Parsed contents of the JSON file
|
96
99
|
# @return [Google::Auth::ClientID]
|
100
|
+
# @raise [Google::Auth::InitializationError] If config is nil or missing required elements
|
97
101
|
#
|
98
102
|
def self.from_hash config
|
99
|
-
raise "Hash can not be nil." if config.nil?
|
103
|
+
raise InitializationError, "Hash can not be nil." if config.nil?
|
100
104
|
raw_detail = config[INSTALLED_APP] || config[WEB_APP]
|
101
|
-
raise MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
|
105
|
+
raise InitializationError, MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
|
102
106
|
ClientId.new raw_detail[CLIENT_ID], raw_detail[CLIENT_SECRET]
|
103
107
|
end
|
104
108
|
end
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require "google-cloud-env"
|
16
|
+
require "googleauth/errors"
|
16
17
|
require "googleauth/signet"
|
17
18
|
|
18
19
|
module Google
|
@@ -87,7 +88,7 @@ module Google
|
|
87
88
|
def initialize options = {}
|
88
89
|
# Override the constructor to remember whether the universe domain was
|
89
90
|
# overridden by a constructor argument.
|
90
|
-
@universe_domain_overridden = options["universe_domain"] || options[:universe_domain]
|
91
|
+
@universe_domain_overridden = options["universe_domain"] || options[:universe_domain]
|
91
92
|
# TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
|
92
93
|
@disable_universe_domain_check = true
|
93
94
|
super options
|
@@ -126,31 +127,25 @@ module Google
|
|
126
127
|
|
127
128
|
# Overrides the super class method to change how access tokens are
|
128
129
|
# fetched.
|
130
|
+
#
|
131
|
+
# @param [Hash] _options Options for token fetch (not used)
|
132
|
+
# @return [Hash] The token data hash
|
133
|
+
# @raise [Google::Auth::UnexpectedStatusError] On unexpected HTTP status codes
|
134
|
+
# @raise [Google::Auth::AuthorizationError] If metadata server is unavailable or returns error
|
129
135
|
def fetch_access_token _options = {}
|
130
|
-
query, entry =
|
131
|
-
if token_type == :id_token
|
132
|
-
[{ "audience" => target_audience, "format" => "full" }, "service-accounts/default/identity"]
|
133
|
-
else
|
134
|
-
[{}, "service-accounts/default/token"]
|
135
|
-
end
|
136
|
-
query[:scopes] = Array(scope).join "," if scope
|
136
|
+
query, entry = build_metadata_request_params
|
137
137
|
begin
|
138
138
|
log_fetch_query
|
139
139
|
resp = Google::Cloud.env.lookup_metadata_response "instance", entry, query: query
|
140
140
|
log_fetch_resp resp
|
141
|
-
|
142
|
-
when 200
|
143
|
-
build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
|
144
|
-
when 403, 500
|
145
|
-
raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
146
|
-
when 404
|
147
|
-
raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
|
148
|
-
else
|
149
|
-
raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
150
|
-
end
|
141
|
+
handle_metadata_response resp
|
151
142
|
rescue Google::Cloud::Env::MetadataServerNotResponding => e
|
152
143
|
log_fetch_err e
|
153
|
-
raise
|
144
|
+
raise AuthorizationError.with_details(
|
145
|
+
e.message,
|
146
|
+
credential_type_name: self.class.name,
|
147
|
+
principal: principal
|
148
|
+
)
|
154
149
|
end
|
155
150
|
end
|
156
151
|
|
@@ -175,8 +170,47 @@ module Google
|
|
175
170
|
self
|
176
171
|
end
|
177
172
|
|
173
|
+
# Returns the principal identifier for GCE credentials
|
174
|
+
# @private
|
175
|
+
# @return [Symbol] :gce to represent Google Compute Engine identity
|
176
|
+
def principal
|
177
|
+
:gce_metadata
|
178
|
+
end
|
179
|
+
|
178
180
|
private
|
179
181
|
|
182
|
+
# @private
|
183
|
+
# Builds query parameters and endpoint for metadata request
|
184
|
+
# @return [Array] The query parameters and endpoint path
|
185
|
+
def build_metadata_request_params
|
186
|
+
query, entry =
|
187
|
+
if token_type == :id_token
|
188
|
+
[{ "audience" => target_audience, "format" => "full" }, "service-accounts/default/identity"]
|
189
|
+
else
|
190
|
+
[{}, "service-accounts/default/token"]
|
191
|
+
end
|
192
|
+
query[:scopes] = Array(scope).join "," if scope
|
193
|
+
[query, entry]
|
194
|
+
end
|
195
|
+
|
196
|
+
# @private
|
197
|
+
# Handles the response from the metadata server
|
198
|
+
# @param [Google::Cloud::Env::MetadataResponse] resp The metadata server response
|
199
|
+
# @return [Hash] The token hash on success
|
200
|
+
# @raise [Google::Auth::UnexpectedStatusError, Google::Auth::AuthorizationError] On error
|
201
|
+
def handle_metadata_response resp
|
202
|
+
case resp.status
|
203
|
+
when 200
|
204
|
+
build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
|
205
|
+
when 403, 500
|
206
|
+
raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
207
|
+
when 404
|
208
|
+
raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
|
209
|
+
else
|
210
|
+
raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
180
214
|
def log_fetch_query
|
181
215
|
if token_type == :id_token
|
182
216
|
logger&.info do
|
@@ -213,6 +247,18 @@ module Google
|
|
213
247
|
end
|
214
248
|
end
|
215
249
|
|
250
|
+
# Constructs a token hash from the metadata server response
|
251
|
+
#
|
252
|
+
# @private
|
253
|
+
# @param [String] body The response body from the metadata server
|
254
|
+
# @param [String] content_type The content type of the response
|
255
|
+
# @param [Float] retrieval_time The monotonic time when the response was retrieved
|
256
|
+
#
|
257
|
+
# @return [Hash] A hash containing:
|
258
|
+
# - access_token/id_token: The actual token depending on what was requested
|
259
|
+
# - token_type: The type of token (usually "Bearer")
|
260
|
+
# - expires_in: Seconds until token expiration (adjusted for freshness)
|
261
|
+
# - universe_domain: The universe domain for the token (if not overridden)
|
216
262
|
def build_token_hash body, content_type, retrieval_time
|
217
263
|
hash =
|
218
264
|
if ["text/html", "application/text"].include? content_type
|
@@ -14,9 +14,11 @@
|
|
14
14
|
|
15
15
|
require "forwardable"
|
16
16
|
require "json"
|
17
|
+
require "pathname"
|
17
18
|
require "signet/oauth_2/client"
|
18
19
|
|
19
20
|
require "googleauth/credentials_loader"
|
21
|
+
require "googleauth/errors"
|
20
22
|
|
21
23
|
module Google
|
22
24
|
module Auth
|
@@ -357,12 +359,13 @@ module Google
|
|
357
359
|
# Creates a new Credentials instance with the provided auth credentials, and with the default
|
358
360
|
# values configured on the class.
|
359
361
|
#
|
360
|
-
# @param [String, Hash,
|
362
|
+
# @param [String, Pathname, Hash, Google::Auth::BaseClient] source_creds
|
361
363
|
# The source of credentials. It can be provided as one of the following:
|
362
364
|
#
|
363
|
-
# * The path to a JSON keyfile (as a `String`)
|
365
|
+
# * The path to a JSON keyfile (as a `String` or a `Pathname`)
|
364
366
|
# * The contents of a JSON keyfile (as a `Hash`)
|
365
|
-
# * A `
|
367
|
+
# * A `Google::Auth::BaseClient` credentials object, including but not limited to
|
368
|
+
# a `Signet::OAuth2::Client` object.
|
366
369
|
# * Any credentials object that supports the methods this wrapper delegates to an inner client.
|
367
370
|
#
|
368
371
|
# If this parameter is an object (`Signet::OAuth2::Client` or other) it will be used as an inner client.
|
@@ -391,14 +394,20 @@ module Google
|
|
391
394
|
# parameters of the `Signet::OAuth2::Client`, such as connection parameters,
|
392
395
|
# timeouts, etc.
|
393
396
|
#
|
397
|
+
# @raise [Google::Auth::InitializationError] If source_creds is nil
|
398
|
+
# @raise [ArgumentError] If both scope and target_audience are specified
|
399
|
+
#
|
394
400
|
def initialize source_creds, options = {}
|
395
|
-
|
401
|
+
if source_creds.nil?
|
402
|
+
raise InitializationError,
|
403
|
+
"The source credentials passed to Google::Auth::Credentials.new were nil."
|
404
|
+
end
|
396
405
|
|
397
406
|
options = symbolize_hash_keys options
|
398
407
|
@project_id = options[:project_id] || options[:project]
|
399
408
|
@quota_project_id = options[:quota_project_id]
|
400
409
|
case source_creds
|
401
|
-
when String
|
410
|
+
when String, Pathname
|
402
411
|
update_from_filepath source_creds, options
|
403
412
|
when Hash
|
404
413
|
update_from_hash source_creds, options
|
@@ -554,9 +563,12 @@ module Google
|
|
554
563
|
protected
|
555
564
|
|
556
565
|
# Verify that the keyfile argument is a file.
|
566
|
+
#
|
567
|
+
# @param [String] keyfile Path to the keyfile
|
568
|
+
# @raise [Google::Auth::InitializationError] If the keyfile does not exist
|
557
569
|
def verify_keyfile_exists! keyfile
|
558
570
|
exists = ::File.file? keyfile
|
559
|
-
raise "The keyfile '#{keyfile}' is not a valid file." unless exists
|
571
|
+
raise InitializationError, "The keyfile '#{keyfile}' is not a valid file." unless exists
|
560
572
|
end
|
561
573
|
|
562
574
|
# Initializes the Signet client.
|
@@ -577,6 +589,11 @@ module Google
|
|
577
589
|
hash.to_h.transform_keys(&:to_sym)
|
578
590
|
end
|
579
591
|
|
592
|
+
# Updates client options with defaults from the credential class
|
593
|
+
#
|
594
|
+
# @param [Hash] options Options to update
|
595
|
+
# @return [Hash] Updated options hash
|
596
|
+
# @raise [ArgumentError] If both scope and target_audience are specified
|
580
597
|
def update_client_options options
|
581
598
|
options = options.dup
|
582
599
|
|
@@ -15,6 +15,8 @@
|
|
15
15
|
require "os"
|
16
16
|
require "rbconfig"
|
17
17
|
|
18
|
+
require "googleauth/errors"
|
19
|
+
|
18
20
|
module Google
|
19
21
|
# Module Auth provides classes that provide Google-specific authorization
|
20
22
|
# used to access Google APIs.
|
@@ -37,7 +39,7 @@ module Google
|
|
37
39
|
AWS_SESSION_TOKEN_VAR = "AWS_SESSION_TOKEN".freeze
|
38
40
|
GCLOUD_POSIX_COMMAND = "gcloud".freeze
|
39
41
|
GCLOUD_WINDOWS_COMMAND = "gcloud.cmd".freeze
|
40
|
-
GCLOUD_CONFIG_COMMAND = "config config-helper --format json --verbosity none".freeze
|
42
|
+
GCLOUD_CONFIG_COMMAND = "config config-helper --format json --verbosity none --quiet".freeze
|
41
43
|
|
42
44
|
CREDENTIALS_FILE_NAME = "application_default_credentials.json".freeze
|
43
45
|
NOT_FOUND_ERROR = "Unable to read the credential file specified by #{ENV_VAR}".freeze
|
@@ -71,11 +73,12 @@ module Google
|
|
71
73
|
# The following keys are recognized:
|
72
74
|
# * `:default_connection` The connection object to use.
|
73
75
|
# * `:connection_builder` A `Proc` that returns a connection.
|
76
|
+
# @raise [Google::Auth::InitializationError] If the credentials file cannot be read
|
74
77
|
def from_env scope = nil, options = {}
|
75
78
|
options = interpret_options scope, options
|
76
79
|
if ENV.key?(ENV_VAR) && !ENV[ENV_VAR].empty?
|
77
80
|
path = ENV[ENV_VAR]
|
78
|
-
raise "file #{path} does not exist" unless File.exist? path
|
81
|
+
raise InitializationError, "file #{path} does not exist" unless File.exist? path
|
79
82
|
File.open path do |f|
|
80
83
|
return make_creds options.merge(json_key_io: f)
|
81
84
|
end
|
@@ -83,7 +86,7 @@ module Google
|
|
83
86
|
make_creds options
|
84
87
|
end
|
85
88
|
rescue StandardError => e
|
86
|
-
raise "#{NOT_FOUND_ERROR}: #{e}"
|
89
|
+
raise InitializationError, "#{NOT_FOUND_ERROR}: #{e}"
|
87
90
|
end
|
88
91
|
|
89
92
|
# Creates an instance from a well known path.
|
@@ -97,6 +100,7 @@ module Google
|
|
97
100
|
# The following keys are recognized:
|
98
101
|
# * `:default_connection` The connection object to use.
|
99
102
|
# * `:connection_builder` A `Proc` that returns a connection.
|
103
|
+
# @raise [Google::Auth::InitializationError] If the credentials file cannot be read
|
100
104
|
def from_well_known_path scope = nil, options = {}
|
101
105
|
options = interpret_options scope, options
|
102
106
|
home_var = OS.windows? ? "APPDATA" : "HOME"
|
@@ -109,7 +113,7 @@ module Google
|
|
109
113
|
return make_creds options.merge(json_key_io: f)
|
110
114
|
end
|
111
115
|
rescue StandardError => e
|
112
|
-
raise "#{WELL_KNOWN_ERROR}: #{e}"
|
116
|
+
raise InitializationError, "#{WELL_KNOWN_ERROR}: #{e}"
|
113
117
|
end
|
114
118
|
|
115
119
|
# Creates an instance from the system default path
|
@@ -123,6 +127,7 @@ module Google
|
|
123
127
|
# The following keys are recognized:
|
124
128
|
# * `:default_connection` The connection object to use.
|
125
129
|
# * `:connection_builder` A `Proc` that returns a connection.
|
130
|
+
# @raise [Google::Auth::InitializationError] If the credentials file cannot be read or is invalid
|
126
131
|
def from_system_default_path scope = nil, options = {}
|
127
132
|
options = interpret_options scope, options
|
128
133
|
if OS.windows?
|
@@ -137,7 +142,7 @@ module Google
|
|
137
142
|
return make_creds options.merge(json_key_io: f)
|
138
143
|
end
|
139
144
|
rescue StandardError => e
|
140
|
-
raise "#{SYSTEM_DEFAULT_ERROR}: #{e}"
|
145
|
+
raise InitializationError, "#{SYSTEM_DEFAULT_ERROR}: #{e}"
|
141
146
|
end
|
142
147
|
|
143
148
|
module_function
|
@@ -146,7 +151,7 @@ module Google
|
|
146
151
|
def load_gcloud_project_id
|
147
152
|
gcloud = GCLOUD_WINDOWS_COMMAND if OS.windows?
|
148
153
|
gcloud = GCLOUD_POSIX_COMMAND unless OS.windows?
|
149
|
-
gcloud_json = IO.popen("#{gcloud} #{GCLOUD_CONFIG_COMMAND}",
|
154
|
+
gcloud_json = IO.popen("#{gcloud} #{GCLOUD_CONFIG_COMMAND}", err: :close, &:read)
|
150
155
|
config = MultiJson.load gcloud_json
|
151
156
|
config["configuration"]["properties"]["core"]["project"]
|
152
157
|
rescue StandardError
|
@@ -16,10 +16,11 @@ require "multi_json"
|
|
16
16
|
require "stringio"
|
17
17
|
|
18
18
|
require "googleauth/credentials_loader"
|
19
|
+
require "googleauth/errors"
|
20
|
+
require "googleauth/external_account"
|
19
21
|
require "googleauth/service_account"
|
22
|
+
require "googleauth/service_account_jwt_header"
|
20
23
|
require "googleauth/user_refresh"
|
21
|
-
require "googleauth/external_account"
|
22
|
-
require "googleauth/impersonated_service_account"
|
23
24
|
|
24
25
|
module Google
|
25
26
|
# Module Auth provides classes that provide Google-specific authorization
|
@@ -42,6 +43,9 @@ module Google
|
|
42
43
|
# information, refer to [Validate credential configurations from external
|
43
44
|
# sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
|
44
45
|
#
|
46
|
+
# @param options [Hash] Options for creating the credentials
|
47
|
+
# @return [Google::Auth::Credentials] The credentials instance
|
48
|
+
# @raise [Google::Auth::InitializationError] If the credentials cannot be determined
|
45
49
|
def self.make_creds options = {}
|
46
50
|
json_key_io = options[:json_key_io]
|
47
51
|
if json_key_io
|
@@ -54,10 +58,14 @@ module Google
|
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
61
|
+
# Reads the credential type from environment and returns the appropriate class
|
62
|
+
#
|
63
|
+
# @return [Class] The credential class to use
|
64
|
+
# @raise [Google::Auth::InitializationError] If the credentials type is undefined or unsupported
|
57
65
|
def self.read_creds
|
58
66
|
env_var = CredentialsLoader::ACCOUNT_TYPE_VAR
|
59
67
|
type = ENV[env_var]
|
60
|
-
raise "#{env_var} is undefined in env" unless type
|
68
|
+
raise InitializationError, "#{env_var} is undefined in env" unless type
|
61
69
|
case type
|
62
70
|
when "service_account"
|
63
71
|
ServiceAccountCredentials
|
@@ -66,15 +74,19 @@ module Google
|
|
66
74
|
when "external_account"
|
67
75
|
ExternalAccount::Credentials
|
68
76
|
else
|
69
|
-
raise "credentials type '#{type}' is not supported"
|
77
|
+
raise InitializationError, "credentials type '#{type}' is not supported"
|
70
78
|
end
|
71
79
|
end
|
72
80
|
|
73
81
|
# Reads the input json and determines which creds class to use.
|
82
|
+
#
|
83
|
+
# @param json_key_io [IO] An IO object containing the JSON key
|
84
|
+
# @return [Array(Hash, Class)] The JSON key and the credential class to use
|
85
|
+
# @raise [Google::Auth::InitializationError] If the JSON is missing the type field or has an unsupported type
|
74
86
|
def self.determine_creds_class json_key_io
|
75
87
|
json_key = MultiJson.load json_key_io.read
|
76
88
|
key = "type"
|
77
|
-
raise "the json is missing the '#{key}' field" unless json_key.key? key
|
89
|
+
raise InitializationError, "the json is missing the '#{key}' field" unless json_key.key? key
|
78
90
|
type = json_key[key]
|
79
91
|
case type
|
80
92
|
when "service_account"
|
@@ -84,7 +96,7 @@ module Google
|
|
84
96
|
when "external_account"
|
85
97
|
[json_key, ExternalAccount::Credentials]
|
86
98
|
else
|
87
|
-
raise "credentials type '#{type}' is not supported"
|
99
|
+
raise InitializationError, "credentials type '#{type}' is not supported"
|
88
100
|
end
|
89
101
|
end
|
90
102
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "signet/oauth_2/client"
|
4
|
+
|
5
|
+
# Copyright 2025 Google LLC
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Auth
|
21
|
+
##
|
22
|
+
# Error mixin module for Google Auth errors
|
23
|
+
# All Google Auth errors should include this module
|
24
|
+
#
|
25
|
+
module Error; end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Mixin module that contains detailed error information
|
29
|
+
# typically this is available if credentials initialization
|
30
|
+
# succeeds and credentials object is valid
|
31
|
+
#
|
32
|
+
module DetailedError
|
33
|
+
include Error
|
34
|
+
|
35
|
+
# The type of the credentials that the error was originated from
|
36
|
+
# @return [String, nil] The class name of the credential that raised the error
|
37
|
+
attr_reader :credential_type_name
|
38
|
+
|
39
|
+
# The principal for the authentication flow. Typically obtained from credentials
|
40
|
+
# @return [String, Symbol, nil] The principal identifier associated with the credentials
|
41
|
+
attr_reader :principal
|
42
|
+
|
43
|
+
# All details passed in the options hash when creating the error
|
44
|
+
# @return [Hash] Additional details about the error
|
45
|
+
attr_reader :details
|
46
|
+
|
47
|
+
# @private
|
48
|
+
def self.included base
|
49
|
+
base.extend ClassMethods
|
50
|
+
end
|
51
|
+
|
52
|
+
# Class methods to be added to including classes
|
53
|
+
module ClassMethods
|
54
|
+
# Creates a new error with detailed information
|
55
|
+
# @param message [String] The error message
|
56
|
+
# @param credential_type_name [String] The credential type that raised the error
|
57
|
+
# @param principal [String, Symbol] The principal for the authentication flow
|
58
|
+
# @return [Error] The new error with details
|
59
|
+
def with_details message, credential_type_name:, principal:
|
60
|
+
new(message).tap do |error|
|
61
|
+
error.instance_variable_set :@credential_type_name, credential_type_name
|
62
|
+
error.instance_variable_set :@principal, principal
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Error raised during Credentials initialization.
|
70
|
+
# All new code should use this instead of ArgumentError during initializtion.
|
71
|
+
#
|
72
|
+
class InitializationError < StandardError
|
73
|
+
include Error
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Generic error raised during operation of Credentials
|
78
|
+
# This should be used for all purposes not covered by other errors.
|
79
|
+
#
|
80
|
+
class CredentialsError < StandardError
|
81
|
+
include DetailedError
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# An error indicating the remote server refused to authorize the client.
|
86
|
+
# Maintains backward compatibility with Signet.
|
87
|
+
#
|
88
|
+
# Should not be used in the new code, even when wrapping `Signet::AuthorizationError`.
|
89
|
+
# New code should use CredentialsError instead.
|
90
|
+
#
|
91
|
+
class AuthorizationError < Signet::AuthorizationError
|
92
|
+
include DetailedError
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# An error indicating that the server sent an unexpected http status.
|
97
|
+
# Maintains backward compatibility with Signet.
|
98
|
+
#
|
99
|
+
# Should not be used in the new code, even when wrapping `Signet::UnexpectedStatusError`.
|
100
|
+
# New code should use CredentialsError instead.
|
101
|
+
#
|
102
|
+
class UnexpectedStatusError < Signet::UnexpectedStatusError
|
103
|
+
include DetailedError
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# An error indicating the client failed to parse a value.
|
108
|
+
# Maintains backward compatibility with Signet.
|
109
|
+
#
|
110
|
+
# Should not be used in the new code, even when wrapping `Signet::ParseError`.
|
111
|
+
# New code should use CredentialsError instead.
|
112
|
+
#
|
113
|
+
class ParseError < Signet::ParseError
|
114
|
+
include DetailedError
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|