googleauth 1.8.1 → 1.13.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 +82 -0
- data/README.md +48 -0
- data/lib/googleauth/application_default.rb +1 -5
- data/lib/googleauth/base_client.rb +16 -4
- data/lib/googleauth/compute_engine.rb +180 -44
- data/lib/googleauth/credentials.rb +169 -56
- data/lib/googleauth/default_credentials.rb +12 -1
- data/lib/googleauth/external_account/base_credentials.rb +37 -5
- data/lib/googleauth/external_account.rb +2 -1
- data/lib/googleauth/id_tokens.rb +0 -2
- data/lib/googleauth/impersonated_service_account.rb +282 -0
- data/lib/googleauth/json_key_reader.rb +2 -1
- data/lib/googleauth/service_account.rb +137 -14
- data/lib/googleauth/signet.rb +149 -2
- data/lib/googleauth/token_store.rb +3 -3
- data/lib/googleauth/user_authorizer.rb +54 -4
- data/lib/googleauth/user_refresh.rb +47 -2
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +15 -4
- metadata +35 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d8ca5b2b0c7f4ce54f7971d8de2f23f3ee0837d08d7d3c568c503308fcf82ab
|
4
|
+
data.tar.gz: d5f8b8fd2fcb4fef4240db58bf90f54a8bfd021c550a7bc9063c9087285f3921
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a4de2b23f4dc0310a18568e0618c5d81fad54dfc8d57fe3c27b954c4bd21272fcc467c2c313f98f80fa127eab11ebe0d0fc55ceed7e6c5439764500e334df49
|
7
|
+
data.tar.gz: f4aff68138105ea19875bb7a51d4b6ced9ec2e7185ce725eca205ea1dc11beb9e6019c9dd89449866598ca6e4d3abb06b91f277f34e51ac7726d79a39fc40c67
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,87 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 1.13.1 (2025-01-24)
|
4
|
+
|
5
|
+
#### Bug Fixes
|
6
|
+
|
7
|
+
* Signet client subclasses no longer make the update! method private ([#516](https://github.com/googleapis/google-auth-library-ruby/issues/516))
|
8
|
+
|
9
|
+
### 1.13.0 (2025-01-22)
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
* create impersonated service credentials ([#499](https://github.com/googleapis/google-auth-library-ruby/issues/499))
|
14
|
+
#### Documentation
|
15
|
+
|
16
|
+
* Include note about validating externally-provided credentials ([#512](https://github.com/googleapis/google-auth-library-ruby/issues/512))
|
17
|
+
|
18
|
+
### 1.12.2 (2024-12-19)
|
19
|
+
|
20
|
+
#### Bug Fixes
|
21
|
+
|
22
|
+
* 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))
|
23
|
+
|
24
|
+
### 1.12.1 (2024-12-17)
|
25
|
+
|
26
|
+
#### Bug Fixes
|
27
|
+
|
28
|
+
* Restored previous behavior where the apply! method returns the auth header ([#506](https://github.com/googleapis/google-auth-library-ruby/issues/506))
|
29
|
+
|
30
|
+
### 1.12.0 (2024-12-05)
|
31
|
+
|
32
|
+
#### Features
|
33
|
+
|
34
|
+
* provided opt-in debug logging ([#490](https://github.com/googleapis/google-auth-library-ruby/issues/490))
|
35
|
+
|
36
|
+
### 1.11.2 (2024-10-23)
|
37
|
+
|
38
|
+
#### Bug Fixes
|
39
|
+
|
40
|
+
* Temporarily disable universe domain query from GCE metadata server ([#493](https://github.com/googleapis/google-auth-library-ruby/issues/493))
|
41
|
+
* Use updated metadata path for universe-domain ([#496](https://github.com/googleapis/google-auth-library-ruby/issues/496))
|
42
|
+
|
43
|
+
### 1.11.1 (2024-10-04)
|
44
|
+
|
45
|
+
#### Bug Fixes
|
46
|
+
|
47
|
+
* Fixed parsing of expiration timestamp from ID tokens ([#492](https://github.com/googleapis/google-auth-library-ruby/issues/492))
|
48
|
+
* Use NoMethodError instead of NotImplementedError for unimplemented base class methods ([#487](https://github.com/googleapis/google-auth-library-ruby/issues/487))
|
49
|
+
|
50
|
+
### 1.11.0 (2024-02-09)
|
51
|
+
|
52
|
+
#### Features
|
53
|
+
|
54
|
+
* Deprecate the positional argument for callback_uri, and introduce keyword argument instead ([#475](https://github.com/googleapis/google-auth-library-ruby/issues/475))
|
55
|
+
|
56
|
+
### 1.10.0 (2024-02-08)
|
57
|
+
|
58
|
+
#### Features
|
59
|
+
|
60
|
+
* add PKCE to 3 Legged OAuth exchange ([#471](https://github.com/googleapis/google-auth-library-ruby/issues/471))
|
61
|
+
#### Bug Fixes
|
62
|
+
|
63
|
+
* Client library credentials provide correct self-signed JWT and external account behavior when loading from a file path or JSON data ([#474](https://github.com/googleapis/google-auth-library-ruby/issues/474))
|
64
|
+
* Prioritize universe domain specified in GCECredentials arguments over metadata-fetched value ([#472](https://github.com/googleapis/google-auth-library-ruby/issues/472))
|
65
|
+
|
66
|
+
### 1.9.2 (2024-01-25)
|
67
|
+
|
68
|
+
#### Bug Fixes
|
69
|
+
|
70
|
+
* Prevent access tokens from being fetched at service account construction in the self-signed-jwt case ([#467](https://github.com/googleapis/google-auth-library-ruby/issues/467))
|
71
|
+
|
72
|
+
### 1.9.1 (2023-12-12)
|
73
|
+
|
74
|
+
#### Bug Fixes
|
75
|
+
|
76
|
+
* update expires_in for cached metadata-retrieved tokens ([#464](https://github.com/googleapis/google-auth-library-ruby/issues/464))
|
77
|
+
|
78
|
+
### 1.9.0 (2023-12-07)
|
79
|
+
|
80
|
+
#### Features
|
81
|
+
|
82
|
+
* Include universe_domain in credentials ([#460](https://github.com/googleapis/google-auth-library-ruby/issues/460))
|
83
|
+
* Use google-cloud-env for more robust Metadata Service access ([#459](https://github.com/googleapis/google-auth-library-ruby/issues/459))
|
84
|
+
|
3
85
|
### 1.8.1 (2023-09-19)
|
4
86
|
|
5
87
|
#### Documentation
|
data/README.md
CHANGED
@@ -64,6 +64,15 @@ well as a web variant tailored toward Rack-based applications.
|
|
64
64
|
The authorizers are intended for authorization use cases. For sign-on,
|
65
65
|
see [Google Identity Platform](https://developers.google.com/identity/)
|
66
66
|
|
67
|
+
## Important notes
|
68
|
+
|
69
|
+
If you accept a credential configuration (credential JSON/File/Stream) from an
|
70
|
+
external source for authentication to Google Cloud, you must validate it before
|
71
|
+
providing it to any Google API or library. Providing an unvalidated credential
|
72
|
+
configuration to Google APIs can compromise the security of your systems and data.
|
73
|
+
For more information, refer to [Validate credential configurations from external
|
74
|
+
sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
|
75
|
+
|
67
76
|
### Example (Web)
|
68
77
|
|
69
78
|
```ruby
|
@@ -97,6 +106,45 @@ get('/oauth2callback') do
|
|
97
106
|
end
|
98
107
|
```
|
99
108
|
|
109
|
+
### Example (Web with PKCE)
|
110
|
+
|
111
|
+
Proof Key for Code Exchange (PKCE) is an [RFC](https://www.rfc-editor.org/rfc/rfc7636) that aims to prevent malicious operating system processes from hijacking an OAUTH 2.0 exchange. PKCE mitigates the above vulnerability by including `code_challenge` and `code_challenge_method` parameters in the Authorization Request and a `code_verifier` parameter in the Access Token Request.
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
require 'googleauth'
|
115
|
+
require 'googleauth/web_user_authorizer'
|
116
|
+
require 'googleauth/stores/redis_token_store'
|
117
|
+
require 'redis'
|
118
|
+
|
119
|
+
client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
|
120
|
+
scope = ['https://www.googleapis.com/auth/drive']
|
121
|
+
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
|
122
|
+
authorizer = Google::Auth::WebUserAuthorizer.new(
|
123
|
+
client_id, scope, token_store, '/oauth2callback')
|
124
|
+
|
125
|
+
|
126
|
+
get('/authorize') do
|
127
|
+
# NOTE: Assumes the user is already authenticated to the app
|
128
|
+
user_id = request.session['user_id']
|
129
|
+
# User needs to take care of generating the code_verifier and storing it in
|
130
|
+
# the session.
|
131
|
+
request.session['code_verifier'] ||= Google::Auth::WebUserAuthorizer.generate_code_verifier
|
132
|
+
authorizer.code_verifier = request.session['code_verifier']
|
133
|
+
credentials = authorizer.get_credentials(user_id, request)
|
134
|
+
if credentials.nil?
|
135
|
+
redirect authorizer.get_authorization_url(login_hint: user_id, request: request)
|
136
|
+
end
|
137
|
+
# Credentials are valid, can call APIs
|
138
|
+
# ...
|
139
|
+
end
|
140
|
+
|
141
|
+
get('/oauth2callback') do
|
142
|
+
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
|
143
|
+
request)
|
144
|
+
redirect target_url
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
100
148
|
### Example (Command Line) [Deprecated]
|
101
149
|
|
102
150
|
The Google Auth OOB flow has been discontiued on January 31, 2023. The OOB flow is a legacy flow that is no longer considered secure. To continue using Google Auth, please migrate your applications to a more secure flow. For more information on how to do this, please refer to this [OOB Migration](https://developers.google.com/identity/protocols/oauth2/resources/oob-migration) guide.
|
@@ -55,11 +55,7 @@ module Google
|
|
55
55
|
DefaultCredentials.from_well_known_path(scope, options) ||
|
56
56
|
DefaultCredentials.from_system_default_path(scope, options)
|
57
57
|
return creds unless creds.nil?
|
58
|
-
unless GCECredentials.on_gce? options
|
59
|
-
# Clear cache of the result of GCECredentials.on_gce?
|
60
|
-
GCECredentials.reset_cache
|
61
|
-
raise NOT_FOUND_ERROR
|
62
|
-
end
|
58
|
+
raise NOT_FOUND_ERROR unless GCECredentials.on_gce? options
|
63
59
|
GCECredentials.new options.merge(scope: scope)
|
64
60
|
end
|
65
61
|
end
|
@@ -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
|
-
|
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
|
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
|
84
|
+
raise NoMethodError, "token_type not implemented"
|
73
85
|
end
|
74
86
|
|
75
87
|
def fetch_access_token!
|
76
|
-
raise
|
88
|
+
raise NoMethodError, "fetch_access_token! not implemented"
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require "
|
15
|
+
require "google-cloud-env"
|
16
16
|
require "googleauth/signet"
|
17
17
|
|
18
18
|
module Google
|
@@ -33,94 +33,230 @@ module Google
|
|
33
33
|
# Extends Signet::OAuth2::Client so that the auth token is obtained from
|
34
34
|
# the GCE metadata server.
|
35
35
|
class GCECredentials < Signet::OAuth2::Client
|
36
|
-
#
|
37
|
-
# systems.
|
36
|
+
# @private Unused and deprecated but retained to prevent breaking changes
|
38
37
|
DEFAULT_METADATA_HOST = "169.254.169.254".freeze
|
39
38
|
|
40
|
-
# @private Unused and deprecated
|
39
|
+
# @private Unused and deprecated but retained to prevent breaking changes
|
41
40
|
COMPUTE_AUTH_TOKEN_URI =
|
42
41
|
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token".freeze
|
43
|
-
# @private Unused and deprecated
|
42
|
+
# @private Unused and deprecated but retained to prevent breaking changes
|
44
43
|
COMPUTE_ID_TOKEN_URI =
|
45
44
|
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/identity".freeze
|
46
|
-
# @private Unused and deprecated
|
45
|
+
# @private Unused and deprecated but retained to prevent breaking changes
|
47
46
|
COMPUTE_CHECK_URI = "http://169.254.169.254".freeze
|
48
47
|
|
49
|
-
@on_gce_cache = {}
|
50
|
-
|
51
48
|
class << self
|
49
|
+
# @private Unused and deprecated
|
52
50
|
def metadata_host
|
53
51
|
ENV.fetch "GCE_METADATA_HOST", DEFAULT_METADATA_HOST
|
54
52
|
end
|
55
53
|
|
54
|
+
# @private Unused and deprecated
|
56
55
|
def compute_check_uri
|
57
56
|
"http://#{metadata_host}".freeze
|
58
57
|
end
|
59
58
|
|
59
|
+
# @private Unused and deprecated
|
60
60
|
def compute_auth_token_uri
|
61
61
|
"#{compute_check_uri}/computeMetadata/v1/instance/service-accounts/default/token".freeze
|
62
62
|
end
|
63
63
|
|
64
|
+
# @private Unused and deprecated
|
64
65
|
def compute_id_token_uri
|
65
66
|
"#{compute_check_uri}/computeMetadata/v1/instance/service-accounts/default/identity".freeze
|
66
67
|
end
|
67
68
|
|
68
69
|
# Detect if this appear to be a GCE instance, by checking if metadata
|
69
70
|
# is available.
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
@on_gce_cache.fetch options do
|
74
|
-
@on_gce_cache[options] = begin
|
75
|
-
# TODO: This should use google-cloud-env instead.
|
76
|
-
c = options[:connection] || Faraday.default_connection
|
77
|
-
headers = { "Metadata-Flavor" => "Google" }
|
78
|
-
resp = c.get compute_check_uri, nil, headers do |req|
|
79
|
-
req.options.timeout = 1.0
|
80
|
-
req.options.open_timeout = 0.1
|
81
|
-
end
|
82
|
-
return false unless resp.status == 200
|
83
|
-
resp.headers["Metadata-Flavor"] == "Google"
|
84
|
-
rescue Faraday::TimeoutError, Faraday::ConnectionFailed
|
85
|
-
false
|
86
|
-
end
|
87
|
-
end
|
71
|
+
# The parameters are deprecated and unused.
|
72
|
+
def on_gce? _options = {}, _reload = false # rubocop:disable Style/OptionalBooleanParameter
|
73
|
+
Google::Cloud.env.metadata?
|
88
74
|
end
|
89
75
|
|
90
76
|
def reset_cache
|
91
|
-
|
77
|
+
Google::Cloud.env.compute_metadata.reset_existence!
|
78
|
+
Google::Cloud.env.compute_metadata.cache.expire_all!
|
92
79
|
end
|
93
80
|
alias unmemoize_all reset_cache
|
94
81
|
end
|
95
82
|
|
83
|
+
# @private Temporary; remove when universe domain metadata endpoint is stable (see b/349488459).
|
84
|
+
attr_accessor :disable_universe_domain_check
|
85
|
+
|
86
|
+
# Construct a GCECredentials
|
87
|
+
def initialize options = {}
|
88
|
+
# Override the constructor to remember whether the universe domain was
|
89
|
+
# overridden by a constructor argument.
|
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
|
93
|
+
super options
|
94
|
+
end
|
95
|
+
|
96
|
+
# Creates a duplicate of these credentials
|
97
|
+
# without the Signet::OAuth2::Client-specific
|
98
|
+
# transient state (e.g. cached tokens)
|
99
|
+
#
|
100
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
101
|
+
# The following keys are recognized in addition to keys in the
|
102
|
+
# Signet::OAuth2::Client
|
103
|
+
# * `:universe_domain_overridden` Whether the universe domain was
|
104
|
+
# overriden during credentials creation
|
105
|
+
def duplicate options = {}
|
106
|
+
options = deep_hash_normalize options
|
107
|
+
super(
|
108
|
+
{
|
109
|
+
universe_domain_overridden: @universe_domain_overridden
|
110
|
+
}.merge(options)
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
# @private
|
115
|
+
# Overrides universe_domain getter to fetch lazily if it hasn't been
|
116
|
+
# fetched yet. This is necessary specifically for Compute Engine because
|
117
|
+
# the universe comes from the metadata service, and isn't known
|
118
|
+
# immediately on credential construction. All other credential types read
|
119
|
+
# the universe from their json key or other immediate input.
|
120
|
+
def universe_domain
|
121
|
+
value = super
|
122
|
+
return value unless value.nil?
|
123
|
+
fetch_access_token!
|
124
|
+
super
|
125
|
+
end
|
126
|
+
|
96
127
|
# Overrides the super class method to change how access tokens are
|
97
128
|
# fetched.
|
98
|
-
def fetch_access_token
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
129
|
+
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
|
137
|
+
begin
|
138
|
+
log_fetch_query
|
139
|
+
resp = Google::Cloud.env.lookup_metadata_response "instance", entry, query: query
|
140
|
+
log_fetch_resp resp
|
105
141
|
case resp.status
|
106
142
|
when 200
|
107
|
-
|
108
|
-
if ["text/html", "application/text"].include? content_type
|
109
|
-
{ (target_audience ? "id_token" : "access_token") => resp.body }
|
110
|
-
else
|
111
|
-
Signet::OAuth2.parse_credentials resp.body, content_type
|
112
|
-
end
|
143
|
+
build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
|
113
144
|
when 403, 500
|
114
|
-
|
115
|
-
raise Signet::UnexpectedStatusError, msg
|
145
|
+
raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
116
146
|
when 404
|
117
147
|
raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
|
118
148
|
else
|
119
|
-
|
120
|
-
raise Signet::AuthorizationError, msg
|
149
|
+
raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
121
150
|
end
|
151
|
+
rescue Google::Cloud::Env::MetadataServerNotResponding => e
|
152
|
+
log_fetch_err e
|
153
|
+
raise Signet::AuthorizationError, e.message
|
122
154
|
end
|
123
155
|
end
|
156
|
+
|
157
|
+
# Destructively updates these credentials.
|
158
|
+
#
|
159
|
+
# This method is called by `Signet::OAuth2::Client`'s constructor
|
160
|
+
#
|
161
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
162
|
+
# The following keys are recognized in addition to keys in the
|
163
|
+
# Signet::OAuth2::Client
|
164
|
+
# * `:universe_domain_overridden` Whether the universe domain was
|
165
|
+
# overriden during credentials creation
|
166
|
+
# @return [Google::Auth::GCECredentials]
|
167
|
+
def update! options = {}
|
168
|
+
# Normalize all keys to symbols to allow indifferent access.
|
169
|
+
options = deep_hash_normalize options
|
170
|
+
|
171
|
+
@universe_domain_overridden = options[:universe_domain_overridden] if options.key? :universe_domain_overridden
|
172
|
+
|
173
|
+
super(options)
|
174
|
+
|
175
|
+
self
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def log_fetch_query
|
181
|
+
if token_type == :id_token
|
182
|
+
logger&.info do
|
183
|
+
Google::Logging::Message.from(
|
184
|
+
message: "Requesting id token from MDS with aud=#{target_audience}",
|
185
|
+
"credentialsId" => object_id
|
186
|
+
)
|
187
|
+
end
|
188
|
+
else
|
189
|
+
logger&.info do
|
190
|
+
Google::Logging::Message.from(
|
191
|
+
message: "Requesting access token from MDS",
|
192
|
+
"credentialsId" => object_id
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def log_fetch_resp resp
|
199
|
+
logger&.info do
|
200
|
+
Google::Logging::Message.from(
|
201
|
+
message: "Received #{resp.status} from MDS",
|
202
|
+
"credentialsId" => object_id
|
203
|
+
)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def log_fetch_err _err
|
208
|
+
logger&.info do
|
209
|
+
Google::Logging::Message.from(
|
210
|
+
message: "MDS did not respond to token request",
|
211
|
+
"credentialsId" => object_id
|
212
|
+
)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def build_token_hash body, content_type, retrieval_time
|
217
|
+
hash =
|
218
|
+
if ["text/html", "application/text"].include? content_type
|
219
|
+
parse_encoded_token body
|
220
|
+
else
|
221
|
+
Signet::OAuth2.parse_credentials body, content_type
|
222
|
+
end
|
223
|
+
add_universe_domain_to hash
|
224
|
+
adjust_for_stale_expires_in hash, retrieval_time
|
225
|
+
hash
|
226
|
+
end
|
227
|
+
|
228
|
+
def parse_encoded_token body
|
229
|
+
hash = { token_type.to_s => body }
|
230
|
+
if token_type == :id_token
|
231
|
+
expires_at = expires_at_from_id_token body
|
232
|
+
hash["expires_at"] = expires_at if expires_at
|
233
|
+
end
|
234
|
+
hash
|
235
|
+
end
|
236
|
+
|
237
|
+
def add_universe_domain_to hash
|
238
|
+
return if @universe_domain_overridden
|
239
|
+
universe_domain =
|
240
|
+
if disable_universe_domain_check
|
241
|
+
# TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
|
242
|
+
"googleapis.com"
|
243
|
+
else
|
244
|
+
Google::Cloud.env.lookup_metadata "universe", "universe-domain"
|
245
|
+
end
|
246
|
+
universe_domain = "googleapis.com" if !universe_domain || universe_domain.empty?
|
247
|
+
hash["universe_domain"] = universe_domain.strip
|
248
|
+
end
|
249
|
+
|
250
|
+
# The response might have been cached, which means expires_in might be
|
251
|
+
# stale. Update it based on the time since the data was retrieved.
|
252
|
+
# We also ensure expires_in is conservative; subtracting at least 1
|
253
|
+
# second to offset any skew from metadata server latency.
|
254
|
+
def adjust_for_stale_expires_in hash, retrieval_time
|
255
|
+
return unless hash["expires_in"].is_a? Numeric
|
256
|
+
offset = 1 + (Process.clock_gettime(Process::CLOCK_MONOTONIC) - retrieval_time).round
|
257
|
+
hash["expires_in"] -= offset if offset.positive?
|
258
|
+
hash["expires_in"] = 0 if hash["expires_in"].negative?
|
259
|
+
end
|
124
260
|
end
|
125
261
|
end
|
126
262
|
end
|