summaryrefslogtreecommitdiff
path: root/app/controllers/otp_challenges_controller.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/otp_challenges_controller.rb')
-rw-r--r--app/controllers/otp_challenges_controller.rb54
1 files changed, 54 insertions, 0 deletions
diff --git a/app/controllers/otp_challenges_controller.rb b/app/controllers/otp_challenges_controller.rb
new file mode 100644
index 00000000..892503a8
--- /dev/null
+++ b/app/controllers/otp_challenges_controller.rb
@@ -0,0 +1,54 @@
1# The second half of a two-step login. A pending marker (set by
2# sessions#create after a correct password) plus deadline and attempt
3# counter live in the session; the real user_id is only written after a
4# valid code, through a fresh session.
5class OtpChallengesController < ApplicationController
6
7 layout 'admin'
8
9 MAX_ATTEMPTS = 5
10
11 def new
12 redirect_to login_path unless pending_user
13 end
14
15 def create
16 user = pending_user
17 return redirect_to login_path unless user
18
19 session[:otp_attempts] = session[:otp_attempts].to_i + 1
20 if session[:otp_attempts] > MAX_ATTEMPTS
21 clear_pending
22 flash[:error] = "Too many attempts -- log in again."
23 return redirect_to login_path
24 end
25
26 if user.verify_otp!(params[:code])
27 return_to = session[:return_to]
28 reset_session
29 self.current_user = user
30 flash[:notice] = "Logged in successfully"
31 redirect_to safe_return_to(return_to, :default => admin_path)
32 else
33 flash.now[:error] = "That code did not match."
34 render :new
35 end
36 end
37
38 private
39
40 def pending_user
41 return nil if session[:pending_otp_user_id].blank?
42 if session[:otp_deadline].to_i < Time.now.to_i
43 clear_pending
44 return nil
45 end
46 @pending_user ||= User.find_by(:id => session[:pending_otp_user_id])
47 end
48
49 def clear_pending
50 session.delete(:pending_otp_user_id)
51 session.delete(:otp_deadline)
52 session.delete(:otp_attempts)
53 end
54end