diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 28c4380ca84..e77094fe2a8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,12 +8,12 @@ class ApplicationController < ActionController::Base include PageLayoutHelper include SentryHelper include WorkhorseHelper + include EnforcesTwoFactorAuthentication before_action :authenticate_user_from_private_token! before_action :authenticate_user! before_action :validate_user_service_ticket! before_action :check_password_expiration - before_action :check_2fa_requirement before_action :ldap_security_check before_action :sentry_context before_action :default_headers @@ -25,7 +25,6 @@ class ApplicationController < ActionController::Base helper_method :can?, :current_application_settings helper_method :import_sources_enabled?, :github_import_enabled?, :gitea_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? - helper_method :two_factor_grace_period_expired?, :two_factor_skippable? rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) @@ -152,12 +151,6 @@ class ApplicationController < ActionController::Base end end - def check_2fa_requirement - if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled? && !skip_two_factor? - redirect_to profile_two_factor_auth_path - end - end - def ldap_security_check if current_user && current_user.requires_ldap_check? return unless current_user.try_obtain_ldap_lease @@ -266,37 +259,6 @@ class ApplicationController < ActionController::Base current_application_settings.import_sources.include?('gitlab_project') end - def two_factor_authentication_required? - current_application_settings.require_two_factor_authentication || - current_user.try(:require_two_factor_authentication) - end - - def two_factor_grace_period - if current_user.try(:require_two_factor_authentication) - [ - current_application_settings.two_factor_grace_period, - current_user.two_factor_grace_period - ].min - else - current_application_settings.two_factor_grace_period - end - end - - def two_factor_grace_period_expired? - date = current_user.otp_grace_period_started_at - date && (date + two_factor_grace_period.hours) < Time.current - end - - def two_factor_skippable? - two_factor_authentication_required? && - !current_user.two_factor_enabled? && - !two_factor_grace_period_expired? - end - - def skip_two_factor? - session[:skip_tfa] && session[:skip_tfa] > Time.current - end - # U2F (universal 2nd factor) devices need a unique identifier for the application # to perform authentication. # https://developers.yubico.com/U2F/App_ID.html diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb new file mode 100644 index 00000000000..b490f0058c7 --- /dev/null +++ b/app/controllers/concerns/enforces_two_factor_authentication.rb @@ -0,0 +1,47 @@ +# == EnforcesTwoFactorAuthentication +# +# Controller concern to enforce two-factor authentication requirements +# +# Upon inclusion, adds `check_2fa_requirement` as a before_action, and +# makes `two_factor_grace_period_expired?` and `two_factor_skippable?` +# available as view helpers. +module EnforcesTwoFactorAuthentication + extend ActiveSupport::Concern + + included do + before_action :check_2fa_requirement + helper_method :two_factor_grace_period_expired?, :two_factor_skippable? + end + + def check_2fa_requirement + if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled? && !skip_two_factor? + redirect_to profile_two_factor_auth_path + end + end + + def two_factor_authentication_required? + current_application_settings.require_two_factor_authentication? || + current_user.try(:require_two_factor_authentication?) + end + + def two_factor_grace_period + periods = [current_application_settings.two_factor_grace_period] + periods << current_user.two_factor_grace_period if current_user.try(:require_two_factor_authentication?) + periods.min + end + + def two_factor_grace_period_expired? + date = current_user.otp_grace_period_started_at + date && (date + two_factor_grace_period.hours) < Time.current + end + + def two_factor_skippable? + two_factor_authentication_required? && + !current_user.two_factor_enabled? && + !two_factor_grace_period_expired? + end + + def skip_two_factor? + session[:skip_tfa] && session[:skip_tfa] > Time.current + end +end