machina-auth 0.1.6 → 0.1.7
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: 376d280c6510f8afa38049e22a0c73df81355c57571b83ef571d547e340ee7c3
|
|
4
|
+
data.tar.gz: 13ce052358975310f67e3b3a65daee423fb48ddc9e2490632b548c66aa0f32d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 271245b4d9c4e3a28d4feafe688d9c3e1985d28566f5f86037ab68ef76fa246f266c67b5dad94ad0d23b111844f9c9e9224e656f97bdeaf9ef76efaf4f18311b
|
|
7
|
+
data.tar.gz: f719e7340acaab6a85ea6b96408c639e0608c797dcbd64f57fa9f5fa76921c5a6ccaac3d0c2751932d77de0ca1019fd4f127479f9b461686b6b0b36c99206c95
|
|
@@ -23,10 +23,7 @@ module Machina
|
|
|
23
23
|
# Token present but invalid/expired: clear the stale cache entry and
|
|
24
24
|
# fall through with nil authorized. API callers get 401 from the
|
|
25
25
|
# controller; browser users get redirected to login by authenticate!.
|
|
26
|
-
unless session_data
|
|
27
|
-
Machina.cache.delete(cache_key(token))
|
|
28
|
-
return @app.call(env)
|
|
29
|
-
end
|
|
26
|
+
return handle_expired_token(env, request, token) unless session_data
|
|
30
27
|
|
|
31
28
|
Machina::Current.authorized = Machina::Authorized.new(session_data)
|
|
32
29
|
|
|
@@ -56,11 +53,23 @@ module Machina
|
|
|
56
53
|
end
|
|
57
54
|
end
|
|
58
55
|
|
|
56
|
+
# Clears the cache entry for the expired token and, when the token
|
|
57
|
+
# originated from the session cookie, deletes that cookie so the
|
|
58
|
+
# browser stops sending it on subsequent requests. This prevents a
|
|
59
|
+
# redirect loop where an expired cookie shadows fresh callback tokens.
|
|
60
|
+
def handle_expired_token(env, request, token)
|
|
61
|
+
Machina.cache.delete(cache_key(token))
|
|
62
|
+
|
|
63
|
+
status, headers, body = @app.call(env)
|
|
64
|
+
Rack::Utils.delete_cookie_header!(headers, 'machina_session') if request.cookies['machina_session'] == token
|
|
65
|
+
[status, headers, body]
|
|
66
|
+
end
|
|
67
|
+
|
|
59
68
|
def extract_token(request)
|
|
60
|
-
request.
|
|
69
|
+
request.params['token']
|
|
70
|
+
|| request.cookies['machina_session']
|
|
61
71
|
|| extract_bearer(request)
|
|
62
72
|
|| request.headers['X-Api-Key']
|
|
63
|
-
|| request.params['token']
|
|
64
73
|
end
|
|
65
74
|
|
|
66
75
|
def extract_bearer(request)
|
data/lib/machina/version.rb
CHANGED
|
@@ -100,6 +100,66 @@ RSpec.describe Machina::Middleware::Authentication do
|
|
|
100
100
|
expect(Machina.cache.read(cache_key)).to be_nil
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
+
context 'when a stale cookie coexists with a fresh callback token' do
|
|
104
|
+
let(:stale_token) { 'ps_expired_cookie' }
|
|
105
|
+
let(:fresh_token) { 'ps_fresh_callback' }
|
|
106
|
+
|
|
107
|
+
before do
|
|
108
|
+
allow(identity_client).to receive(:resolve_session).with(stale_token).and_return(
|
|
109
|
+
Machina::IdentityClient::Response.new(status: 404, body: '{}'),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
allow(identity_client).to receive(:resolve_session).with(fresh_token).and_return(
|
|
113
|
+
Machina::IdentityClient::Response.new(status: 200, body: MockResponses.session_resolution),
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'prefers the query param token over the stale cookie' do
|
|
118
|
+
env = Rack::MockRequest.env_for(
|
|
119
|
+
'/auth/machina/callback?token=ps_fresh_callback',
|
|
120
|
+
'HTTP_COOKIE' => 'machina_session=ps_expired_cookie',
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
status, _headers, body = middleware.call(env)
|
|
124
|
+
|
|
125
|
+
expect(status).to eq(200)
|
|
126
|
+
parsed = JSON.parse(body.first)
|
|
127
|
+
expect(parsed['user_id']).to eq(MockResponses.session_resolution['data']['user']['id'])
|
|
128
|
+
expect(identity_client).not_to have_received(:resolve_session).with(stale_token)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'deletes the session cookie when a cookie-sourced token is expired' do
|
|
133
|
+
allow(identity_client).to receive(:resolve_session).with('ps_expired_cookie').and_return(
|
|
134
|
+
Machina::IdentityClient::Response.new(status: 404, body: '{}'),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
env = Rack::MockRequest.env_for(
|
|
138
|
+
'/resource',
|
|
139
|
+
'HTTP_COOKIE' => 'machina_session=ps_expired_cookie',
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
_status, headers, _body = middleware.call(env)
|
|
143
|
+
|
|
144
|
+
expect(headers['set-cookie']).to include('machina_session=')
|
|
145
|
+
expect(headers['set-cookie']).to include('max-age=0')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'does not delete the cookie when a bearer token fails resolution' do
|
|
149
|
+
allow(identity_client).to receive(:resolve_session).with('ps_expired_bearer').and_return(
|
|
150
|
+
Machina::IdentityClient::Response.new(status: 404, body: '{}'),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
env = Rack::MockRequest.env_for(
|
|
154
|
+
'/resource',
|
|
155
|
+
'HTTP_AUTHORIZATION' => 'Bearer ps_expired_bearer',
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
_status, headers, _body = middleware.call(env)
|
|
159
|
+
|
|
160
|
+
expect(headers['set-cookie']).to be_nil
|
|
161
|
+
end
|
|
162
|
+
|
|
103
163
|
it 'uses the cache on subsequent requests' do
|
|
104
164
|
response = Machina::IdentityClient::Response.new(
|
|
105
165
|
status: 200,
|