machina-auth 0.3.0 → 0.4.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60692b69e1db477292fba2a947650c2ac15099a616a05318071860a02a550694
|
|
4
|
+
data.tar.gz: 3625e766f4645037333365f8771e6363be979de0c484ff086b61ced3b335b84b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10cb1b5e52daf7e76f344bfb8445e2ecca186d5cda9b1693dd376cd7ad4e503306229eabe510879ab72cd10c0a275b5c51ba2d84275758539b5fe1d8ca12b482
|
|
7
|
+
data.tar.gz: a168a7dd638f5663394dda922ba91582bfef041922325c635deff9d2ce79b7828916f21553ab5357d12a8b88276e6f8c560584898c212a9daaea0a4b560a7b98
|
|
@@ -10,12 +10,14 @@ module Machina
|
|
|
10
10
|
:product_slug,
|
|
11
11
|
:cache_store,
|
|
12
12
|
:cache_ttl,
|
|
13
|
+
:negative_cache_ttl,
|
|
13
14
|
:manifest,
|
|
14
15
|
:skip_paths,
|
|
15
16
|
:identity_callback_uri
|
|
16
17
|
|
|
17
18
|
def initialize
|
|
18
19
|
@cache_ttl = 5.minutes
|
|
20
|
+
@negative_cache_ttl = 30.seconds
|
|
19
21
|
@skip_paths = []
|
|
20
22
|
end
|
|
21
23
|
end
|
|
@@ -8,7 +8,11 @@ module Machina
|
|
|
8
8
|
# resolves them against the identity service, and sets Current.authorized.
|
|
9
9
|
class Authentication
|
|
10
10
|
TRANSIENT_FAILURE = :transient_failure
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
# Negative-cache marker for a rejected token. A Hash, so it round-trips through any cache coder.
|
|
13
|
+
INVALID_SESSION = { '__machina_invalid__' => true }.freeze
|
|
14
|
+
|
|
15
|
+
private_constant :TRANSIENT_FAILURE, :INVALID_SESSION
|
|
12
16
|
|
|
13
17
|
def initialize(app)
|
|
14
18
|
@app = app
|
|
@@ -39,7 +43,7 @@ module Machina
|
|
|
39
43
|
if transient_failure?(session_data)
|
|
40
44
|
@app.call(env)
|
|
41
45
|
else
|
|
42
|
-
handle_expired_token(env, request, token
|
|
46
|
+
handle_expired_token(env, request, token)
|
|
43
47
|
end
|
|
44
48
|
end
|
|
45
49
|
|
|
@@ -62,10 +66,9 @@ module Machina
|
|
|
62
66
|
end
|
|
63
67
|
end
|
|
64
68
|
|
|
65
|
-
# Clears the
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
# Clears the cookie for a rejected token. The cache holds the INVALID_SESSION
|
|
70
|
+
# sentinel (written in fetch_from_identity_service) and must not be cleared here.
|
|
71
|
+
def handle_expired_token(env, request, token)
|
|
69
72
|
status, headers, body = @app.call(env)
|
|
70
73
|
Rack::Utils.delete_cookie_header!(headers, 'machina_session') if request.cookies['machina_session'] == token
|
|
71
74
|
[status, headers, body]
|
|
@@ -92,6 +95,7 @@ module Machina
|
|
|
92
95
|
|
|
93
96
|
def resolve_session(token, hints)
|
|
94
97
|
cached = Machina.cache.read(cache_key(token, hints))
|
|
98
|
+
return nil if cached == INVALID_SESSION
|
|
95
99
|
return cached if cached.present? && !(cached.is_a?(Hash) && cached['stale'])
|
|
96
100
|
|
|
97
101
|
fetch_from_identity_service(token, hints)
|
|
@@ -109,7 +113,7 @@ module Machina
|
|
|
109
113
|
response = Machina.identity_client.resolve_session(token, **hints.to_resolve_kwargs)
|
|
110
114
|
|
|
111
115
|
unless response.success?
|
|
112
|
-
Machina.cache.
|
|
116
|
+
Machina.cache.write(cache_key(token, hints), INVALID_SESSION, expires_in: Machina.config.negative_cache_ttl)
|
|
113
117
|
return nil
|
|
114
118
|
end
|
|
115
119
|
|
data/lib/machina/version.rb
CHANGED
|
@@ -154,7 +154,7 @@ RSpec.describe Machina::Middleware::Authentication do
|
|
|
154
154
|
expect(JSON.parse(body.first)).to eq('user_id' => nil, 'permissions' => nil)
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
it '
|
|
157
|
+
it 'negative-caches the rejection and passes through when Console returns non-200 on stale re-fetch' do
|
|
158
158
|
token = 'ps_stale_token'
|
|
159
159
|
cache_key = "machina:session:#{token}"
|
|
160
160
|
stale_data = MockResponses.session_resolution_minimal['data'].merge('stale' => true)
|
|
@@ -169,10 +169,11 @@ RSpec.describe Machina::Middleware::Authentication do
|
|
|
169
169
|
status, = middleware.call(env)
|
|
170
170
|
|
|
171
171
|
expect(status).to eq(200)
|
|
172
|
-
|
|
172
|
+
# The stale session is replaced by the short-lived negative sentinel, not deleted.
|
|
173
|
+
expect(Machina.cache.read(cache_key)).to eq('__machina_invalid__' => true)
|
|
173
174
|
end
|
|
174
175
|
|
|
175
|
-
it '
|
|
176
|
+
it 'negative-caches the rejection when Console returns non-200 after cache expires' do
|
|
176
177
|
token = 'ps_expired_cache'
|
|
177
178
|
cache_key = "machina:session:#{token}"
|
|
178
179
|
|
|
@@ -197,7 +198,24 @@ RSpec.describe Machina::Middleware::Authentication do
|
|
|
197
198
|
status, = middleware.call(env)
|
|
198
199
|
|
|
199
200
|
expect(status).to eq(200)
|
|
200
|
-
expect(Machina.cache.read(cache_key)).to
|
|
201
|
+
expect(Machina.cache.read(cache_key)).to eq('__machina_invalid__' => true)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'does not re-hit Console for a rejected token while the negative cache is warm' do
|
|
205
|
+
token = 'ps_dead_token'
|
|
206
|
+
|
|
207
|
+
allow(identity_client).to receive(:resolve_session).with(token).and_return(
|
|
208
|
+
Machina::IdentityClient::Response.new(status: 404, body: '{}'),
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
3.times do
|
|
212
|
+
env = Rack::MockRequest.env_for('/resource', 'HTTP_AUTHORIZATION' => "Bearer #{token}")
|
|
213
|
+
status, = middleware.call(env)
|
|
214
|
+
expect(status).to eq(200)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Without negative caching this would be 3 calls; the sentinel absorbs the retries.
|
|
218
|
+
expect(identity_client).to have_received(:resolve_session).with(token).once
|
|
201
219
|
end
|
|
202
220
|
|
|
203
221
|
context 'when a stale cookie coexists with a fresh callback token' do
|