Skip to content

Commit 2f67c52

Browse files
Merge pull request #41 from RadiusNetworks/eric/redis-session
Modifies cookie cache value check to also check with redis-based value
2 parents ddfcd8f + d7b4841 commit 2f67c52

File tree

5 files changed

+92
-48
lines changed

5 files changed

+92
-48
lines changed

app/controllers/kracken/sessions_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ class SessionsController < ActionController::Base
77
def create
88
@user = user_class.find_or_create_from_auth_hash(auth_hash)
99
session[:user_id] = @user.id
10-
session[:user_cache_key] = cookies[:_radius_user_cache_key]
10+
session[:user_uid] = @user.uid
11+
session[:user_cache_key] = Kracken::SessionManager.get(@user.uid)
1112
session[:token_expires_at] = Time.zone.at(auth_hash[:credentials][:expires_at])
13+
1214
redirect_to return_to_path
1315
end
1416

lib/kracken.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "kracken/authenticator"
1313
require "kracken/registration"
1414
require "kracken/railtie" if defined?(Rails)
15+
require "kracken/session_manager"
1516

1617
module Kracken
1718
mattr_accessor :config

lib/kracken/controllers/authenticatable.rb

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Authenticatable
66

77
def self.included(base)
88
base.instance_exec do
9-
before_action :handle_user_cache_cookie!
9+
before_action :handle_user_cache_key!
1010
before_action :authenticate_user!
1111
helper_method :sign_out_path, :sign_up_path, :sign_in_path,
1212
:current_user, :user_signed_in?
@@ -49,7 +49,7 @@ def authenticate_user!
4949

5050
def check_token_expiry!
5151
if session[:token_expires_at].nil? || session[:token_expires_at] < Time.zone.now
52-
session.delete :user_id
52+
delete_session_data
5353
end
5454
end
5555

@@ -64,31 +64,18 @@ def check_token_expiry!
6464
#
6565
# This method will:
6666
#
67-
# - Check for the `_radius_user_cache_key` tld cookie
68-
# - If the key is "none" log them out
67+
# - Check for the presence of a user cache key in Redis
6968
# - Compare it to the `user_cache_key` in the session
7069
# - If they don't match, redirect them to the oauth provider and
71-
# delete the cookie
70+
# delete the session
7271
#
73-
def handle_user_cache_cookie!
74-
if cookies[:_radius_user_cache_key]
75-
if cookies[:_radius_user_cache_key] == "none"
76-
# Sign out current user
77-
session.delete :user_id
78-
79-
# Clear that user's cache key
80-
session.delete :user_cache_key
81-
82-
elsif session[:user_cache_key] != cookies[:_radius_user_cache_key]
83-
# Delete the cookie to prevent redirect loops
84-
cookies.delete :_radius_user_cache_key
85-
86-
# Redirect to the account app
87-
redirect_to_sign_in
88-
end
89-
end
90-
end
72+
def handle_user_cache_key!
73+
return unless session_present?
74+
return if session_and_redis_match?
9175

76+
delete_session_data
77+
redirect_to_sign_in
78+
end
9279

9380
def current_user=(u)
9481
@current_user = u
@@ -124,6 +111,23 @@ def user_signed_in?
124111

125112
private
126113

114+
def session_present?
115+
session[:user_uid] && session[:user_cache_key]
116+
end
117+
118+
def session_and_redis_match?
119+
Kracken::SessionManager.get(session[:user_uid]) == session[:user_cache_key]
120+
end
121+
122+
def delete_session_data
123+
# Sign out current user
124+
session.delete :user_id
125+
126+
# Clear that user's cache data
127+
session.delete :user_uid
128+
session.delete :user_cache_key
129+
end
130+
127131
def user_class
128132
Kracken.config.user_class
129133
end

lib/kracken/session_manager.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
module Kracken
4+
module SessionManager
5+
def self.conn
6+
@conn ||= if ENV["REDIS_SESSION_URL"].present?
7+
Redis.new(url: ENV["REDIS_SESSION_URL"])
8+
else
9+
NullRedis.new
10+
end
11+
end
12+
13+
def self.get(user_id)
14+
conn.get(user_session_key(user_id))
15+
end
16+
17+
def self.del(user_id)
18+
conn.del(user_session_key(user_id))
19+
end
20+
21+
def self.update(user_id, value)
22+
conn.set(user_session_key(user_id), value)
23+
end
24+
25+
def self.user_session_key(user_id)
26+
"rnsession:#{user_id}"
27+
end
28+
29+
class NullRedis
30+
# rubocop:disable Style/EmptyMethod
31+
def initialize(*); end
32+
33+
def del(*); end
34+
35+
def get(*); end
36+
37+
def set(*); end
38+
# rubocop:enable Style/EmptyMethod
39+
end
40+
end
41+
end

spec/kracken/controllers/authenticatable_spec.rb

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -136,47 +136,43 @@ class ControllerDouble < BaseControllerDouble
136136
expect(controller).to_not have_received(:redirect_to)
137137
end
138138

139-
context "user cache cookie" do
140-
it "nothing if the cache cookie does not exist" do
139+
context "user cache key" do
140+
it "does nothing if the session does not exist" do
141141
allow(controller).to receive(:request).and_return(double(format: nil, fullpath: nil))
142142
allow(controller).to receive(:redirect_to)
143-
controller.session[:user_cache_key] = "123"
144143

145-
controller.handle_user_cache_cookie!
144+
controller.handle_user_cache_key!
146145

147146
expect(controller).to_not have_received(:redirect_to)
148147
end
149148

150-
it "signs the current user out when the cache cookie is 'none'" do
151-
allow(controller).to receive(:request).and_return(double(format: nil, fullpath: nil))
152-
allow(controller).to receive(:redirect_to)
153-
controller.cookies[:_radius_user_cache_key] = "123"
149+
it "ends session and redirects if stored key does not match session key" do
154150
controller.session[:user_cache_key] = "123"
151+
controller.session[:user_uid] = "123"
155152

156-
controller.handle_user_cache_cookie!
157-
158-
expect(controller).to_not have_received(:redirect_to)
159-
end
160-
161-
it "redirects when the cache cookie is different than the session" do
162153
allow(controller).to receive(:request).and_return(double(format: nil, fullpath: nil))
163-
allow(controller).to receive(:cookies).and_return({_radius_user_cache_key: "123"})
164154
allow(controller).to receive(:redirect_to)
165-
controller.handle_user_cache_cookie!
155+
allow(Kracken::SessionManager).to receive(:get).and_return("456")
156+
157+
expect(controller).to receive(:redirect_to).with("/")
158+
expect(controller.session).to receive(:delete).with(:user_id)
159+
expect(controller.session).to receive(:delete).with(:user_uid)
160+
expect(controller.session).to receive(:delete).with(:user_cache_key)
166161

167-
expect(controller).to have_received(:redirect_to).with("/")
162+
controller.handle_user_cache_key!
168163
end
169164

170-
it "does not redirect when the cache cookie matches the session" do
171-
controller.session = spy
165+
it "does nothing if session keys match" do
166+
controller.session[:user_cache_key] = "123"
167+
controller.session[:user_uid] = "123"
168+
169+
allow(controller).to receive(:request).and_return(double(format: nil, fullpath: nil))
172170
allow(controller).to receive(:redirect_to)
173-
controller.cookies[:_radius_user_cache_key] = "none"
171+
allow(Kracken::SessionManager).to receive(:get).and_return("123")
174172

175-
controller.handle_user_cache_cookie!
173+
expect(controller).to_not receive(:redirect_to).with("/")
176174

177-
expect(controller).to_not have_received(:redirect_to)
178-
expect(controller.session).to have_received(:delete).with(:user_id)
179-
expect(controller.session).to have_received(:delete).with(:user_cache_key)
175+
controller.handle_user_cache_key!
180176
end
181177
end
182178
end

0 commit comments

Comments
 (0)