Commit 1cce0b2b authored by o@immerda.ch's avatar o@immerda.ch
Browse files

refactor auth

parent 124a67f7
......@@ -2,7 +2,7 @@ class AdminController < ApplicationController
def authorize
if !admin?
flash[:notice] = :login_failed
destroy_session
reset_user_session
redirect_to '/login'
else
super
......
......@@ -97,19 +97,15 @@ class ApplicationController < ActionController::Base
true
end
def reset_user_session
reset_session
session[:locale] = I18n.locale
end
def update_session_expiry
session[:expires_at] = 15.minutes.from_now.to_i
end
helper_method :update_session_expiry
private
def destroy_session
def reset_user_session
session[:user_id] = nil
session[:mail_crypt_recovery_token] = nil
reset_user_session
reset_session
session[:locale] = I18n.locale
end
end
......@@ -63,8 +63,8 @@ module ApiBackend
false
end
def self.auth_failures(email)
get(['users', 'auth_failures'], {'email' => email})
def self.pre_auth(email)
get(['auth', 'pre_auth'], {'email' => email})
end
def self.app_passwords(email)
......
......@@ -4,7 +4,7 @@ class DeleteAccountController < ApplicationController
begin
ApiBackend::delete_account(current_user, p)
flash[:notice] = :delete_success
destroy_session
reset_user_session
redirect_to '/' and return
rescue ApiBackend::ApiError => e
if e.api_msg == 'auth_fail'
......
......@@ -16,21 +16,16 @@ class SessionsController < ApplicationController
end
helper_method :horde_handoff_auth
def pre_auth
u = params[:user_id]
return nil unless EmailValidation.immerda_email_conform(u)
session[:pre_auth] ||= ApiBackend::pre_auth(u)
rescue
nil
end
def security_level
user = current_user || params[:user_id]
u = if user
begin
@current_user_auth_fails ||= ApiBackend::auth_failures(user)
rescue ApiBackend::ApiError => e
if e.api_msg == 'does_not_exist'
{'auth_failures' => 1, 'locked' => true}
else
{'auth_failures' => 0, 'locked' => false}
end
end
else
{'auth_failures' => 0, 'locked' => false}
end
u = pre_auth || {'auth_failures' => 0, 'locked' => false}
client_fails =
if CountIpFails
Rails.cache.read(client_auth_key) || 0
......@@ -42,9 +37,11 @@ class SessionsController < ApplicationController
captcha = u['locked'] || total_fails > 5
wait = [4, total_fails/4.0].min
wait += rand()*3 if wait > 0.5
redirects = [2, total_fails/2].min
redirects += [0,1].sample if redirects > 0
{
# how many pow do we want from the client
redirects: [2, total_fails/2].min + [0,1].sample,
redirects: redirects,
# how many seconds to throttle between pow
wait: wait,
# how hard are the pow
......@@ -67,7 +64,7 @@ class SessionsController < ApplicationController
return login_failed
end
unless session[:pre_auth_passed]
unless session[:tfa_query]
if !params[:pow].present?
return login_failed
end
......@@ -102,24 +99,32 @@ class SessionsController < ApplicationController
@handoff = h
end
session[:tfa_query] = pre_auth && pre_auth['need_2fa']
if session[:tfa_query] && params[:totp].present? && params[:totp].length == 6
session[:tfa_query] = false
end
if session[:tfa_query]
if pre_auth['need_2fa'] == 'totp'
flash[:notice] = nil
session[:tfa_query] = true
load_params
return render '2fa'
end
end
begin
res = if !@handoff && params[:unlock]
ApiBackend::auth(params[:user_id], params[:password], @handoff, unlock: params[:unlock])
ApiBackend::auth(
params[:user_id], params[:password], @handoff,
unlock: params[:unlock],
totp: params[:totp])
else
ApiBackend::auth(params[:user_id], params[:password], @handoff)
ApiBackend::auth(
params[:user_id], params[:password], @handoff,
totp: params[:totp])
end
if res
session[:pre_auth_passed] = true
if res['totp'] == true
if params[:totp]
ApiBackend::verify_totp(res['email'], params[:totp])
else
flash[:notice] = nil
load_params
return render '2fa'
end
end
# Login ok, start user session
reset_user_session
......@@ -169,7 +174,8 @@ class SessionsController < ApplicationController
def new_login_session
f = flash[:notice]
fails = session[:auth_failures] || 0
destroy_session
reset_user_session
params.delete(:user_id)
session[:auth_failures] = fails
flash[:notice] = f
load_params
......@@ -189,7 +195,7 @@ class SessionsController < ApplicationController
end
def destroy
destroy_session
reset_user_session
redirect_to '/login'
end
......@@ -266,6 +272,9 @@ class SessionsController < ApplicationController
def load_pow(initial_page)
@pow_factor = session[:pow_factor] = security_level[:pow_factor]
if !initial_page && session[:ping_pong] == 1 && security_level[:enable_captcha]
RuCaptcha.config.strikethrough = false
RuCaptcha.config.cache_store = nil
RuCaptcha.config.outline = [true, false].sample
res = RuCaptcha.generate()
@captcha = Base64.encode64(res[1])
session[:pow_nonce] = res[0]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment