googleauth 1.15.0 → 1.15.1
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 +6 -0
- data/Credentials.md +6 -2
- data/lib/googleauth/credentials.rb +49 -34
- data/lib/googleauth/credentials_loader.rb +15 -0
- data/lib/googleauth/default_credentials.rb +59 -39
- data/lib/googleauth/external_account.rb +5 -0
- data/lib/googleauth/service_account.rb +25 -9
- data/lib/googleauth/user_refresh.rb +17 -9
- data/lib/googleauth/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b360d5a61b05e86f04c2eab04af61b421ffc5c2e1f6833741d59d9c96d94a19
|
4
|
+
data.tar.gz: 8727a84fa541a8e6a2abeb0544d4608d32d1e205a0d9371e695b079fb8d3fa0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 262a5af69278586d4a13e8776b7fd5c627591aa8434585ea3a80f6e24035e4c78498f02f236fb84b63b7c59ef23e4021f2f21aa5dcf49c5bf46a9a9bb80b66c9
|
7
|
+
data.tar.gz: 9356b779fbb2340328a55850ce434957715d50accb842d24a4233bdb7ce532b49c564d63a068c087439e9cd75d9dc3bfff7b17205cb30f811ddb0d3b0567e101
|
data/CHANGELOG.md
CHANGED
data/Credentials.md
CHANGED
@@ -38,17 +38,19 @@ that exposes common initialization functionality, such as creating credentials f
|
|
38
38
|
- For obtaining authentication tokens from GCE metadata server
|
39
39
|
- Used automatically when code is running on Google Compute Engine
|
40
40
|
- Fetches tokens from the metadata server with no additional configuration needed
|
41
|
+
- This credential type does not have a supported JSON form
|
41
42
|
|
42
43
|
4. **Google::Auth::IAMCredentials < Signet::OAuth2::Client** - `lib/googleauth/iam.rb`
|
43
44
|
- For IAM-based authentication (e.g. service-to-service)
|
44
45
|
- Implements authentication-as-a-service for systems already authenticated
|
45
46
|
- Exchanges existing credentials for a short-lived access token
|
47
|
+
- This credential type does not have a supported JSON form
|
46
48
|
|
47
49
|
## Service Account Authentication
|
48
50
|
|
49
51
|
5. **Google::Auth::ServiceAccountCredentials < Signet::OAuth2::Client** - `lib/googleauth/service_account.rb`
|
50
52
|
- Authenticates requests using Service Account credentials via an OAuth access token
|
51
|
-
- Created from JSON key file downloaded from Google Cloud Console
|
53
|
+
- Created from JSON key file downloaded from Google Cloud Console. The JSON form of this credential type has a `"type"` field with the value `"service_account"`.
|
52
54
|
- Supports both OAuth access tokens and self-signed JWT authentication
|
53
55
|
- Can specify scopes for access token requests
|
54
56
|
|
@@ -64,6 +66,7 @@ that exposes common initialization functionality, such as creating credentials f
|
|
64
66
|
- Allows a GCP principal identified by a set of source credentials to impersonate a service account
|
65
67
|
- Useful for delegation of authority and managing permissions across service accounts
|
66
68
|
- Source credentials must have the Service Account Token Creator role on the target
|
69
|
+
- This credential type does not have a supported JSON form
|
67
70
|
|
68
71
|
## User Authentication
|
69
72
|
|
@@ -71,7 +74,7 @@ that exposes common initialization functionality, such as creating credentials f
|
|
71
74
|
- For user refresh token authentication (from 3-legged OAuth flow)
|
72
75
|
- Authenticates on behalf of a user who has authorized the application
|
73
76
|
- Handles token refresh when original access token expires
|
74
|
-
- Typically obtained through web or installed application flow
|
77
|
+
- Typically obtained through web or installed application flow. The JSON form of this credential type has a `"type"` field with the value `"authorized_user"`.
|
75
78
|
|
76
79
|
`Google::Auth::UserAuthorizer` (`lib/googleauth/user_authorizer.rb`) and `Google::Auth::WebUserAuthorizer` (`lib/googleauth/web_user_authorizer.rb`)
|
77
80
|
are used to facilitate user authentication. The `UserAuthorizer` handles interactive 3-Legged-OAuth2 (3LO) user consent authorization for command-line applications.
|
@@ -83,6 +86,7 @@ that exposes common initialization functionality, such as creating credentials f
|
|
83
86
|
types based on credential source (similar to `Google::Auth::get_application_default`).
|
84
87
|
It is included in all External Account credentials types, and it itself includes `Google::Auth::BaseClient` module so all External
|
85
88
|
Account credentials types include `Google::Auth::BaseClient`.
|
89
|
+
The JSON form of this credential type has a `"type"` field with the value `"external_account"`.
|
86
90
|
|
87
91
|
9. **Google::Auth::ExternalAccount::AwsCredentials** - `lib/googleauth/external_account/aws_credentials.rb`
|
88
92
|
- Includes `Google::Auth::BaseClient` module
|
@@ -16,6 +16,7 @@ require "forwardable"
|
|
16
16
|
require "json"
|
17
17
|
require "pathname"
|
18
18
|
require "signet/oauth_2/client"
|
19
|
+
require "multi_json"
|
19
20
|
|
20
21
|
require "googleauth/credentials_loader"
|
21
22
|
require "googleauth/errors"
|
@@ -508,17 +509,61 @@ module Google
|
|
508
509
|
token_credential_uri: options[:token_credential_uri] || token_credential_uri,
|
509
510
|
audience: options[:audience] || audience
|
510
511
|
}
|
511
|
-
|
512
|
+
|
513
|
+
# Determine the class, which consumes the IO stream
|
514
|
+
json_key, clz = Google::Auth::DefaultCredentials.determine_creds_class creds_input[:json_key_io]
|
515
|
+
|
516
|
+
# Re-serialize the parsed JSON and replace the IO stream in creds_input
|
517
|
+
creds_input[:json_key_io] = StringIO.new MultiJson.dump(json_key)
|
518
|
+
|
519
|
+
client = clz.make_creds creds_input
|
512
520
|
options = options.select { |k, _v| k == :logger }
|
513
521
|
new client, options
|
514
522
|
end
|
515
523
|
|
524
|
+
# @private
|
525
|
+
# Initializes the Signet client.
|
526
|
+
def self.init_client hash, options = {}
|
527
|
+
options = update_client_options options
|
528
|
+
io = StringIO.new JSON.generate hash
|
529
|
+
|
530
|
+
# Determine the class, which consumes the IO stream
|
531
|
+
json_key, clz = Google::Auth::DefaultCredentials.determine_creds_class io
|
532
|
+
|
533
|
+
# Re-serialize the parsed JSON and create a new IO stream.
|
534
|
+
new_io = StringIO.new MultiJson.dump(json_key)
|
535
|
+
|
536
|
+
clz.make_creds options.merge!(json_key_io: new_io)
|
537
|
+
end
|
538
|
+
|
539
|
+
# @private
|
540
|
+
# Updates client options with defaults from the credential class
|
541
|
+
#
|
542
|
+
# @param [Hash] options Options to update
|
543
|
+
# @return [Hash] Updated options hash
|
544
|
+
# @raise [ArgumentError] If both scope and target_audience are specified
|
545
|
+
def self.update_client_options options
|
546
|
+
options = options.dup
|
547
|
+
|
548
|
+
# options have higher priority over constructor defaults
|
549
|
+
options[:token_credential_uri] ||= token_credential_uri
|
550
|
+
options[:audience] ||= audience
|
551
|
+
options[:scope] ||= scope
|
552
|
+
options[:target_audience] ||= target_audience
|
553
|
+
|
554
|
+
if !Array(options[:scope]).empty? && options[:target_audience]
|
555
|
+
raise ArgumentError, "Cannot specify both scope and target_audience"
|
556
|
+
end
|
557
|
+
options.delete :scope unless options[:target_audience].nil?
|
558
|
+
|
559
|
+
options
|
560
|
+
end
|
561
|
+
|
516
562
|
private_class_method :from_env_vars,
|
517
563
|
:from_default_paths,
|
518
564
|
:from_application_default,
|
519
565
|
:from_io
|
520
566
|
|
521
|
-
|
522
567
|
# Creates a duplicate of these credentials. This method tries to create the duplicate of the
|
523
568
|
# wrapped credentials if they support duplication and use them as is if they don't.
|
524
569
|
#
|
@@ -571,14 +616,6 @@ module Google
|
|
571
616
|
raise InitializationError, "The keyfile '#{keyfile}' is not a valid file." unless exists
|
572
617
|
end
|
573
618
|
|
574
|
-
# Initializes the Signet client.
|
575
|
-
def init_client hash, options = {}
|
576
|
-
options = update_client_options options
|
577
|
-
io = StringIO.new JSON.generate hash
|
578
|
-
options.merge! json_key_io: io
|
579
|
-
Google::Auth::DefaultCredentials.make_creds options
|
580
|
-
end
|
581
|
-
|
582
619
|
# returns a new Hash with string keys instead of symbol keys.
|
583
620
|
def stringify_hash_keys hash
|
584
621
|
hash.to_h.transform_keys(&:to_s)
|
@@ -589,28 +626,6 @@ module Google
|
|
589
626
|
hash.to_h.transform_keys(&:to_sym)
|
590
627
|
end
|
591
628
|
|
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
|
597
|
-
def update_client_options options
|
598
|
-
options = options.dup
|
599
|
-
|
600
|
-
# options have higher priority over constructor defaults
|
601
|
-
options[:token_credential_uri] ||= self.class.token_credential_uri
|
602
|
-
options[:audience] ||= self.class.audience
|
603
|
-
options[:scope] ||= self.class.scope
|
604
|
-
options[:target_audience] ||= self.class.target_audience
|
605
|
-
|
606
|
-
if !Array(options[:scope]).empty? && options[:target_audience]
|
607
|
-
raise ArgumentError, "Cannot specify both scope and target_audience"
|
608
|
-
end
|
609
|
-
options.delete :scope unless options[:target_audience].nil?
|
610
|
-
|
611
|
-
options
|
612
|
-
end
|
613
|
-
|
614
629
|
def update_from_client client
|
615
630
|
@project_id ||= client.project_id if client.respond_to? :project_id
|
616
631
|
@quota_project_id ||= client.quota_project_id if client.respond_to? :quota_project_id
|
@@ -624,7 +639,7 @@ module Google
|
|
624
639
|
hash["target_audience"] ||= options[:target_audience]
|
625
640
|
@project_id ||= hash["project_id"] || hash["project"]
|
626
641
|
@quota_project_id ||= hash["quota_project_id"]
|
627
|
-
@client = init_client hash, options
|
642
|
+
@client = self.class.init_client hash, options
|
628
643
|
end
|
629
644
|
|
630
645
|
def update_from_filepath path, options
|
@@ -634,7 +649,7 @@ module Google
|
|
634
649
|
json["target_audience"] ||= options[:target_audience]
|
635
650
|
@project_id ||= json["project_id"] || json["project"]
|
636
651
|
@quota_project_id ||= json["quota_project_id"]
|
637
|
-
@client = init_client json, options
|
652
|
+
@client = self.class.init_client json, options
|
638
653
|
end
|
639
654
|
|
640
655
|
def setup_logging logger: :default
|
@@ -158,6 +158,21 @@ module Google
|
|
158
158
|
nil
|
159
159
|
end
|
160
160
|
|
161
|
+
# @private
|
162
|
+
# Loads a JSON key from an IO object, verifies its type, and rewinds the IO.
|
163
|
+
#
|
164
|
+
# @param json_key_io [IO] An IO object containing the JSON key.
|
165
|
+
# @param expected_type [String] The expected credential type name.
|
166
|
+
# @raise [Google::Auth::InitializationError] If the JSON key type does not match the expected type.
|
167
|
+
def load_and_verify_json_key_type json_key_io, expected_type
|
168
|
+
json_key = MultiJson.load json_key_io.read
|
169
|
+
json_key_io.rewind # Rewind the stream so it can be read again.
|
170
|
+
return if json_key["type"] == expected_type
|
171
|
+
raise Google::Auth::InitializationError,
|
172
|
+
"The provided credentials were not of type '#{expected_type}'. " \
|
173
|
+
"Instead, the type was '#{json_key['type']}'."
|
174
|
+
end
|
175
|
+
|
161
176
|
private
|
162
177
|
|
163
178
|
def interpret_options scope, options
|
@@ -43,61 +43,81 @@ module Google
|
|
43
43
|
# information, refer to [Validate credential configurations from external
|
44
44
|
# sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
|
45
45
|
#
|
46
|
+
# @deprecated This method is deprecated and will be removed in a future version.
|
47
|
+
# Please use the `make_creds` method on the specific credential class you intend to load,
|
48
|
+
# e.g., `Google::Auth::ServiceAccountCredentials.make_creds`.
|
49
|
+
#
|
50
|
+
# This method does not validate the credential configuration. The security
|
51
|
+
# risk occurs when a credential configuration is accepted from a source that
|
52
|
+
# is not under your control and used without validation on your side.
|
53
|
+
#
|
54
|
+
# If you know that you will be loading credential configurations of a
|
55
|
+
# specific type, it is recommended to use a credential-type-specific
|
56
|
+
# `make_creds` method.
|
57
|
+
# This will ensure that an unexpected credential type with potential for
|
58
|
+
# malicious intent is not loaded unintentionally. You might still have to do
|
59
|
+
# validation for certain credential types. Please follow the recommendation
|
60
|
+
# for that method. For example, if you want to load only service accounts,
|
61
|
+
# you can use:
|
62
|
+
# ```
|
63
|
+
# creds = Google::Auth::ServiceAccountCredentials.make_creds
|
64
|
+
# ```
|
65
|
+
# @see Google::Auth::ServiceAccountCredentials.make_creds
|
66
|
+
#
|
67
|
+
# If you are loading your credential configuration from an untrusted source and have
|
68
|
+
# not mitigated the risks (e.g. by validating the configuration yourself), make
|
69
|
+
# these changes as soon as possible to prevent security risks to your environment.
|
70
|
+
#
|
71
|
+
# Regardless of the method used, it is always your responsibility to validate
|
72
|
+
# configurations received from external sources.
|
73
|
+
#
|
74
|
+
# See https://cloud.google.com/docs/authentication/external/externally-sourced-credentials for more details.
|
75
|
+
#
|
46
76
|
# @param options [Hash] Options for creating the credentials
|
47
77
|
# @return [Google::Auth::Credentials] The credentials instance
|
48
78
|
# @raise [Google::Auth::InitializationError] If the credentials cannot be determined
|
49
79
|
def self.make_creds options = {}
|
50
80
|
json_key_io = options[:json_key_io]
|
51
|
-
|
52
|
-
|
81
|
+
json_key, clz = determine_creds_class json_key_io
|
82
|
+
if json_key
|
53
83
|
io = StringIO.new MultiJson.dump(json_key)
|
54
84
|
clz.make_creds options.merge(json_key_io: io)
|
55
85
|
else
|
56
|
-
clz = read_creds
|
57
86
|
clz.make_creds options
|
58
87
|
end
|
59
88
|
end
|
60
89
|
|
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
|
65
|
-
def self.read_creds
|
66
|
-
env_var = CredentialsLoader::ACCOUNT_TYPE_VAR
|
67
|
-
type = ENV[env_var]
|
68
|
-
raise InitializationError, "#{env_var} is undefined in env" unless type
|
69
|
-
case type
|
70
|
-
when "service_account"
|
71
|
-
ServiceAccountCredentials
|
72
|
-
when "authorized_user"
|
73
|
-
UserRefreshCredentials
|
74
|
-
when "external_account"
|
75
|
-
ExternalAccount::Credentials
|
76
|
-
else
|
77
|
-
raise InitializationError, "credentials type '#{type}' is not supported"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
90
|
# Reads the input json and determines which creds class to use.
|
82
91
|
#
|
83
|
-
# @param json_key_io [IO] An IO object containing the JSON key
|
84
|
-
#
|
85
|
-
# @
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
[
|
94
|
-
when "authorized_user"
|
95
|
-
[json_key, UserRefreshCredentials]
|
96
|
-
when "external_account"
|
97
|
-
[json_key, ExternalAccount::Credentials]
|
92
|
+
# @param json_key_io [IO, nil] An optional IO object containing the JSON key.
|
93
|
+
# If nil, the credential type is determined from environment variables.
|
94
|
+
# @return [Array(Hash, Class)] The JSON key (or nil if from environment) and the credential class to use
|
95
|
+
# @raise [Google::Auth::InitializationError] If the JSON is missing the type field or has an unsupported type,
|
96
|
+
# or if the environment variable is undefined or unsupported.
|
97
|
+
def self.determine_creds_class json_key_io = nil
|
98
|
+
if json_key_io
|
99
|
+
json_key = MultiJson.load json_key_io.read
|
100
|
+
key = "type"
|
101
|
+
raise InitializationError, "the json is missing the '#{key}' field" unless json_key.key? key
|
102
|
+
type = json_key[key]
|
98
103
|
else
|
99
|
-
|
104
|
+
env_var = CredentialsLoader::ACCOUNT_TYPE_VAR
|
105
|
+
type = ENV[env_var]
|
106
|
+
raise InitializationError, "#{env_var} is undefined in env" unless type
|
107
|
+
json_key = nil
|
100
108
|
end
|
109
|
+
|
110
|
+
clz = case type
|
111
|
+
when ServiceAccountCredentials::CREDENTIAL_TYPE_NAME
|
112
|
+
ServiceAccountCredentials
|
113
|
+
when UserRefreshCredentials::CREDENTIAL_TYPE_NAME
|
114
|
+
UserRefreshCredentials
|
115
|
+
when ExternalAccount::Credentials::CREDENTIAL_TYPE_NAME
|
116
|
+
ExternalAccount::Credentials
|
117
|
+
else
|
118
|
+
raise InitializationError, "credentials type '#{type}' is not supported"
|
119
|
+
end
|
120
|
+
[json_key, clz]
|
101
121
|
end
|
102
122
|
end
|
103
123
|
end
|
@@ -34,6 +34,10 @@ module Google
|
|
34
34
|
MISSING_CREDENTIAL_SOURCE = "missing credential source for external account".freeze
|
35
35
|
INVALID_EXTERNAL_ACCOUNT_TYPE = "credential source is not supported external account type".freeze
|
36
36
|
|
37
|
+
# @private
|
38
|
+
# @type [::String] The type name for this credential.
|
39
|
+
CREDENTIAL_TYPE_NAME = "external_account".freeze
|
40
|
+
|
37
41
|
# Create a ExternalAccount::Credentials
|
38
42
|
#
|
39
43
|
# @param options [Hash] Options for creating credentials
|
@@ -49,6 +53,7 @@ module Google
|
|
49
53
|
json_key_io, scope = options.values_at :json_key_io, :scope
|
50
54
|
|
51
55
|
raise InitializationError, "A json file is required for external account credentials." unless json_key_io
|
56
|
+
CredentialsLoader.load_and_verify_json_key_type json_key_io, CREDENTIAL_TYPE_NAME
|
52
57
|
user_creds = read_json_key json_key_io
|
53
58
|
|
54
59
|
# AWS credentials is determined by aws subject token type
|
@@ -41,6 +41,10 @@ module Google
|
|
41
41
|
attr_reader :project_id
|
42
42
|
attr_reader :quota_project_id
|
43
43
|
|
44
|
+
# @private
|
45
|
+
# @type [::String] The type name for this credential.
|
46
|
+
CREDENTIAL_TYPE_NAME = "service_account".freeze
|
47
|
+
|
44
48
|
def enable_self_signed_jwt?
|
45
49
|
# Use a self-singed JWT if there's no information that can be used to
|
46
50
|
# obtain an OAuth token, OR if there are scopes but also an assertion
|
@@ -60,15 +64,13 @@ module Google
|
|
60
64
|
:audience, :token_credential_uri
|
61
65
|
raise ArgumentError, "Cannot specify both scope and target_audience" if scope && target_audience
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
universe_domain = nil
|
71
|
-
end
|
67
|
+
private_key, client_email, project_id, quota_project_id, universe_domain =
|
68
|
+
if json_key_io
|
69
|
+
CredentialsLoader.load_and_verify_json_key_type json_key_io, CREDENTIAL_TYPE_NAME
|
70
|
+
read_json_key json_key_io
|
71
|
+
else
|
72
|
+
creds_from_env
|
73
|
+
end
|
72
74
|
project_id ||= CredentialsLoader.load_gcloud_project_id
|
73
75
|
|
74
76
|
new(token_credential_uri: token_credential_uri || TOKEN_CRED_URI,
|
@@ -190,6 +192,20 @@ module Google
|
|
190
192
|
alt.logger = logger
|
191
193
|
alt.apply! a_hash
|
192
194
|
end
|
195
|
+
|
196
|
+
# @private
|
197
|
+
# Loads service account credential details from environment variables.
|
198
|
+
#
|
199
|
+
# @return [Array<String, String, String, nil, nil>] An array containing private_key,
|
200
|
+
# client_email, project_id, quota_project_id, and universe_domain.
|
201
|
+
def self.creds_from_env
|
202
|
+
private_key = unescape ENV[CredentialsLoader::PRIVATE_KEY_VAR]
|
203
|
+
client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
|
204
|
+
project_id = ENV[CredentialsLoader::PROJECT_ID_VAR]
|
205
|
+
[private_key, client_email, project_id, nil, nil]
|
206
|
+
end
|
207
|
+
|
208
|
+
private_class_method :creds_from_env
|
193
209
|
end
|
194
210
|
end
|
195
211
|
end
|
@@ -39,21 +39,29 @@ module Google
|
|
39
39
|
attr_reader :project_id
|
40
40
|
attr_reader :quota_project_id
|
41
41
|
|
42
|
+
# @private
|
43
|
+
# @type [::String] The type name for this credential.
|
44
|
+
CREDENTIAL_TYPE_NAME = "authorized_user".freeze
|
45
|
+
|
42
46
|
# Create a UserRefreshCredentials.
|
43
47
|
#
|
44
48
|
# @param json_key_io [IO] An IO object containing the JSON key
|
45
49
|
# @param scope [string|array|nil] the scope(s) to access
|
46
50
|
def self.make_creds options = {}
|
47
51
|
json_key_io, scope = options.values_at :json_key_io, :scope
|
48
|
-
user_creds =
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
user_creds = if json_key_io
|
53
|
+
CredentialsLoader.load_and_verify_json_key_type json_key_io, CREDENTIAL_TYPE_NAME
|
54
|
+
read_json_key json_key_io
|
55
|
+
else
|
56
|
+
{
|
57
|
+
"client_id" => ENV[CredentialsLoader::CLIENT_ID_VAR],
|
58
|
+
"client_secret" => ENV[CredentialsLoader::CLIENT_SECRET_VAR],
|
59
|
+
"refresh_token" => ENV[CredentialsLoader::REFRESH_TOKEN_VAR],
|
60
|
+
"project_id" => ENV[CredentialsLoader::PROJECT_ID_VAR],
|
61
|
+
"quota_project_id" => nil,
|
62
|
+
"universe_domain" => nil
|
63
|
+
}
|
64
|
+
end
|
57
65
|
new(token_credential_uri: TOKEN_CRED_URI,
|
58
66
|
client_id: user_creds["client_id"],
|
59
67
|
client_secret: user_creds["client_secret"],
|
data/lib/googleauth/version.rb
CHANGED