Commit 31fb2b77 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Grace period support for TFA

parent 33964469
...@@ -225,9 +225,13 @@ class ApplicationController < ActionController::Base ...@@ -225,9 +225,13 @@ class ApplicationController < ActionController::Base
end end
def check_tfa_requirement def check_tfa_requirement
if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled && !skip_two_factor?
grace_period_started = current_user.otp_grace_period_started_at
grace_period_deadline = grace_period_started + two_factor_grace_period.hours
deadline_text = "until #{l(grace_period_deadline)}" unless two_factor_grace_period_expired?(grace_period_started)
redirect_to new_profile_two_factor_auth_path, redirect_to new_profile_two_factor_auth_path,
alert: 'You must configure Two-Factor Authentication in your account' alert: "You must configure Two-Factor Authentication in your account #{deadline_text}"
end end
end end
...@@ -369,6 +373,18 @@ class ApplicationController < ActionController::Base ...@@ -369,6 +373,18 @@ class ApplicationController < ActionController::Base
current_application_settings.require_two_factor_authentication current_application_settings.require_two_factor_authentication
end end
def two_factor_grace_period
current_application_settings.two_factor_grace_period
end
def two_factor_grace_period_expired?(date)
date && (date + two_factor_grace_period.hours) < Time.current
end
def skip_two_factor?
session[:skip_tfa] && session[:skip_tfa] > Time.current
end
def redirect_to_home_page_url? def redirect_to_home_page_url?
# If user is not signed-in and tries to access root_path - redirect him to landing page # If user is not signed-in and tries to access root_path - redirect him to landing page
# Don't redirect to the default URL to prevent endless redirections # Don't redirect to the default URL to prevent endless redirections
......
...@@ -4,8 +4,11 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController ...@@ -4,8 +4,11 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
def new def new
unless current_user.otp_secret unless current_user.otp_secret
current_user.otp_secret = User.generate_otp_secret(32) current_user.otp_secret = User.generate_otp_secret(32)
current_user.save!
end end
unless current_user.otp_grace_period_started_at && two_factor_grace_period
current_user.otp_grace_period_started_at = Time.current
end
current_user.save! if current_user.changed?
@qr_code = build_qr_code @qr_code = build_qr_code
end end
...@@ -36,6 +39,15 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController ...@@ -36,6 +39,15 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
redirect_to profile_account_path redirect_to profile_account_path
end end
def skip
if two_factor_grace_period_expired?(current_user.otp_grace_period_started_at)
redirect_to new_profile_two_factor_auth_path, alert: 'Cannot skip two factor authentication setup'
else
session[:skip_tfa] = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
redirect_to root_path
end
end
private private
def build_qr_code def build_qr_code
......
...@@ -50,5 +50,17 @@ module AuthHelper ...@@ -50,5 +50,17 @@ module AuthHelper
current_user.identities.exists?(provider: provider.to_s) current_user.identities.exists?(provider: provider.to_s)
end end
def two_factor_skippable?
current_application_settings.require_two_factor_authentication &&
!current_user.two_factor_enabled &&
current_application_settings.two_factor_grace_period &&
!two_factor_grace_period_expired?
end
def two_factor_grace_period_expired?
current_user.otp_grace_period_started_at &&
(current_user.otp_grace_period_started_at + current_application_settings.two_factor_grace_period.hours) < Time.current
end
extend self extend self
end end
...@@ -38,3 +38,4 @@ ...@@ -38,3 +38,4 @@
= text_field_tag :pin_code, nil, class: "form-control", required: true, autofocus: true = text_field_tag :pin_code, nil, class: "form-control", required: true, autofocus: true
.form-actions .form-actions
= submit_tag 'Submit', class: 'btn btn-success' = submit_tag 'Submit', class: 'btn btn-success'
= link_to 'Configure it later', skip_profile_two_factor_auth_path, :method => :patch, class: 'btn btn-cancel' if two_factor_skippable?
...@@ -297,6 +297,7 @@ Rails.application.routes.draw do ...@@ -297,6 +297,7 @@ Rails.application.routes.draw do
resource :two_factor_auth, only: [:new, :create, :destroy] do resource :two_factor_auth, only: [:new, :create, :destroy] do
member do member do
post :codes post :codes
patch :skip
end end
end end
end end
......
class AddTfaAdditionalFields < ActiveRecord::Migration
def change
change_table :users do |t|
t.datetime :otp_grace_period_started_at, null: true
end
end
end
...@@ -840,6 +840,7 @@ ActiveRecord::Schema.define(version: 20151224123230) do ...@@ -840,6 +840,7 @@ ActiveRecord::Schema.define(version: 20151224123230) do
t.integer "layout", default: 0 t.integer "layout", default: 0
t.boolean "hide_project_limit", default: false t.boolean "hide_project_limit", default: false
t.string "unlock_token" t.string "unlock_token"
t.datetime "otp_grace_period_started_at"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
Markdown is supported
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