mirror of
https://github.com/meineerde/redmine.git
synced 2026-02-06 09:03:25 +00:00
Adds a setting to disable/enable/require 2fa auth (#1237).
Patch by Felix Schäfer. git-svn-id: http://svn.redmine.org/redmine/trunk@19989 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
560bca344a
commit
be7f5e21fa
@ -56,7 +56,7 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change
|
||||
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change, :check_twofa_activation
|
||||
after_action :record_project_usage
|
||||
|
||||
rescue_from ::Unauthorized, :with => :deny_access
|
||||
@ -89,6 +89,9 @@ class ApplicationController < ActionController::Base
|
||||
if user.must_change_password?
|
||||
session[:pwd] = '1'
|
||||
end
|
||||
if user.must_activate_twofa?
|
||||
session[:must_activate_twofa] = '1'
|
||||
end
|
||||
end
|
||||
|
||||
def user_setup
|
||||
@ -205,6 +208,31 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
def init_twofa_pairing_and_send_code_for(twofa)
|
||||
twofa.init_pairing!
|
||||
if twofa.send_code(controller: 'twofa', action: 'activate')
|
||||
flash[:notice] = l('twofa_code_sent')
|
||||
end
|
||||
redirect_to controller: 'twofa', action: 'activate_confirm', scheme: twofa.scheme_name
|
||||
end
|
||||
|
||||
def check_twofa_activation
|
||||
if session[:must_activate_twofa]
|
||||
if User.current.must_activate_twofa?
|
||||
flash[:warning] = l('twofa_warning_require')
|
||||
if Redmine::Twofa.available_schemes.length == 1
|
||||
twofa_scheme = Redmine::Twofa.for_twofa_scheme(Redmine::Twofa.available_schemes.first)
|
||||
twofa = twofa_scheme.new(User.current)
|
||||
init_twofa_pairing_and_send_code_for(twofa)
|
||||
else
|
||||
redirect_to controller: 'twofa', action: 'select_scheme'
|
||||
end
|
||||
else
|
||||
session.delete(:must_activate_twofa)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def set_localization(user=User.current)
|
||||
lang = nil
|
||||
if user && user.logged?
|
||||
|
||||
@ -23,16 +23,20 @@ class TwofaController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :require_admin, only: :admin_deactivate
|
||||
|
||||
before_action :require_active_twofa
|
||||
|
||||
require_sudo_mode :activate_init, :deactivate_init
|
||||
|
||||
skip_before_action :check_twofa_activation, only: [:select_scheme, :activate_init, :activate_confirm, :activate]
|
||||
|
||||
def select_scheme
|
||||
@user = User.current
|
||||
end
|
||||
|
||||
before_action :activate_setup, only: [:activate_init, :activate_confirm, :activate]
|
||||
|
||||
def activate_init
|
||||
@twofa.init_pairing!
|
||||
if @twofa.send_code(controller: 'twofa', action: 'activate')
|
||||
flash[:notice] = l('twofa_code_sent')
|
||||
end
|
||||
redirect_to action: :activate_confirm, scheme: @twofa.scheme_name
|
||||
init_twofa_pairing_and_send_code_for(@twofa)
|
||||
end
|
||||
|
||||
def activate_confirm
|
||||
@ -106,4 +110,8 @@ class TwofaController < ApplicationController
|
||||
redirect_to my_account_path
|
||||
end
|
||||
end
|
||||
|
||||
def require_active_twofa
|
||||
Setting.twofa? ? true : deny_access
|
||||
end
|
||||
end
|
||||
|
||||
@ -223,6 +223,12 @@ class Setting < ActiveRecord::Base
|
||||
s
|
||||
end
|
||||
|
||||
def self.twofa_from_params(params)
|
||||
# unpair all current 2FA pairings when switching off 2FA
|
||||
Redmine::Twofa.unpair_all! if params == '0' && self.twofa?
|
||||
params
|
||||
end
|
||||
|
||||
# Helper that returns an array based on per_page_options setting
|
||||
def self.per_page_options_array
|
||||
per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort
|
||||
|
||||
@ -396,6 +396,10 @@ class User < Principal
|
||||
twofa_scheme.present?
|
||||
end
|
||||
|
||||
def must_activate_twofa?
|
||||
Setting.twofa == '2' && !twofa_active?
|
||||
end
|
||||
|
||||
def pref
|
||||
self.preference ||= UserPreference.new(:user => self)
|
||||
end
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
<% if Setting.openid? %>
|
||||
<p><%= f.text_field :identity_url %></p>
|
||||
<% end %>
|
||||
<% if Setting.twofa? -%>
|
||||
<p>
|
||||
<label><%=l :setting_twofa -%></label>
|
||||
<% if @user.twofa_active? %>
|
||||
@ -39,6 +40,7 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end -%>
|
||||
|
||||
<% @user.custom_field_values.select(&:editable?).each do |value| %>
|
||||
<p><%= custom_field_tag_with_label :user, value %></p>
|
||||
|
||||
@ -28,6 +28,17 @@
|
||||
|
||||
<p><%= setting_check_box :lost_password %></p>
|
||||
|
||||
<p>
|
||||
<%= setting_select :twofa, [[l(:label_disabled), "0"],
|
||||
[l(:label_optional), "1"],
|
||||
[l(:label_required_lower), "2"]] -%>
|
||||
<em class="info">
|
||||
<%= t 'twofa_hint_disabled_html', label: t(:label_disabled) -%><br/>
|
||||
<%= t 'twofa_hint_required_html', label: t(:label_required_lower) -%>
|
||||
</em>
|
||||
</p>
|
||||
|
||||
|
||||
<p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p>
|
||||
</div>
|
||||
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% unless @user.must_activate_twofa? %>
|
||||
<% content_for :sidebar do %>
|
||||
<%= render :partial => 'my/sidebar' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
19
app/views/twofa/select_scheme.html.erb
Normal file
19
app/views/twofa/select_scheme.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<%= title l('twofa_label_setup') %>
|
||||
|
||||
<%= form_tag({ controller: 'twofa', action: 'activate_init' }, method: :post) do %>
|
||||
<div class="box">
|
||||
<p><%=l 'twofa_notice_select' -%></p>
|
||||
<p>
|
||||
<% Redmine::Twofa.available_schemes.each_with_index do |s, idx| %>
|
||||
<label style="display:block;"><%= radio_button_tag 'scheme', s, idx == 0 -%> <%=l "twofa__#{s}__name" -%></label>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<p><%= submit_tag l(:label_next).html_safe + " »".html_safe -%></p>
|
||||
<% end %>
|
||||
|
||||
<% unless @user.must_activate_twofa? %>
|
||||
<% content_for :sidebar do %>
|
||||
<%= render partial: 'my/sidebar' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@ -42,6 +42,7 @@
|
||||
<p><%= f.check_box :generate_password %></p>
|
||||
<p><%= f.check_box :must_change_passwd %></p>
|
||||
</div>
|
||||
<% if Setting.twofa? -%>
|
||||
<p>
|
||||
<label><%=l :setting_twofa -%></label>
|
||||
<% if @user.twofa_active? %>
|
||||
@ -55,6 +56,7 @@
|
||||
<%=l 'twofa_not_active' %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end -%>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
|
||||
@ -719,6 +719,7 @@ de:
|
||||
label_repository_new: Neues Repository
|
||||
label_repository_plural: Repositories
|
||||
label_required: Erforderlich
|
||||
label_required_lower: erforderlich
|
||||
label_result_plural: Resultate
|
||||
label_reverse_chronological_order: in umgekehrter zeitlicher Reihenfolge
|
||||
label_revision: Revision
|
||||
@ -1330,8 +1331,12 @@ de:
|
||||
twofa_currently_active: "Aktiv: %{twofa_scheme_name}"
|
||||
twofa_not_active: "Nicht aktiv"
|
||||
twofa_label_code: Code
|
||||
twofa_hint_disabled_html: Die Einstellung <strong>%{label}</strong> deaktiviert Zwei-Faktor-Authentifizierung für alle Nutzer und löscht verbundene Apps.
|
||||
twofa_hint_required_html: Die Einstellung <strong>%{label}</strong> fordert alle Nutzer bei ihrem nächsten Login dazu auf Zwei-Faktor-Authentifizierung einzurichten.
|
||||
twofa_label_setup: Zwei-Faktor-Authentifizierung einrichten
|
||||
twofa_label_deactivation_confirmation: Zwei-Faktor-Authentifizierung abschalten
|
||||
twofa_notice_select: "Bitte wählen Sie Ihr gewünschtes Schema für die Zwei-Faktor-Authentifizierung:"
|
||||
twofa_warning_require: Der Administrator fordert Sie dazu auf Zwei-Faktor-Authentifizierung einzurichten.
|
||||
twofa_activated: Zwei-Faktor-Authentifizierung erfolgreich eingerichtet.
|
||||
twofa_deactivated: Zwei-Faktor-Authentifizierung abgeschaltet.
|
||||
twofa_mail_body_security_notification_paired: "Zwei-Faktor-Authentifizierung per %{field} eingerichtet."
|
||||
|
||||
@ -870,6 +870,7 @@ en:
|
||||
label_copied_from: Copied from
|
||||
label_stay_logged_in: Stay logged in
|
||||
label_disabled: disabled
|
||||
label_optional: optional
|
||||
label_show_completed_versions: Show completed versions
|
||||
label_me: me
|
||||
label_board: Forum
|
||||
@ -993,6 +994,7 @@ en:
|
||||
label_fields_permissions: Fields permissions
|
||||
label_readonly: Read-only
|
||||
label_required: Required
|
||||
label_required_lower: required
|
||||
label_hidden: Hidden
|
||||
label_attribute_of_project: "Project's %{name}"
|
||||
label_attribute_of_issue: "Issue's %{name}"
|
||||
@ -1307,8 +1309,12 @@ en:
|
||||
twofa_currently_active: "Currently active: %{twofa_scheme_name}"
|
||||
twofa_not_active: "Not activated"
|
||||
twofa_label_code: Code
|
||||
twofa_hint_disabled_html: Setting <strong>%{label}</strong> will deactivate and unpair two-factor authentication devices for all users.
|
||||
twofa_hint_required_html: Setting <strong>%{label}</strong> will require all users to set up two-factor authentication at their next login.
|
||||
twofa_label_setup: Enable two-factor authentication
|
||||
twofa_label_deactivation_confirmation: Disable two-factor authentication
|
||||
twofa_notice_select: "Please select the two-factor scheme you would like to use:"
|
||||
twofa_warning_require: The administrator requires you to enable two-factor authentication.
|
||||
twofa_activated: Two-factor authentication successfully enabled.
|
||||
twofa_deactivated: Two-factor authentication disabled.
|
||||
twofa_mail_body_security_notification_paired: "Two-factor authentication successfully enabled using %{field}."
|
||||
|
||||
@ -88,12 +88,14 @@ Rails.application.routes.draw do
|
||||
match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
|
||||
match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
|
||||
match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
|
||||
match 'my/twofa/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post
|
||||
match 'my/twofa/:scheme/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post
|
||||
match 'my/twofa/:scheme/activate/confirm', :controller => 'twofa', :action => 'activate_confirm', :via => :get
|
||||
match 'my/twofa/:scheme/activate', :controller => 'twofa', :action => 'activate', :via => [:get, :post]
|
||||
match 'my/twofa/:scheme/deactivate/init', :controller => 'twofa', :action => 'deactivate_init', :via => :post
|
||||
match 'my/twofa/:scheme/deactivate/confirm', :controller => 'twofa', :action => 'deactivate_confirm', :via => :get
|
||||
match 'my/twofa/:scheme/deactivate', :controller => 'twofa', :action => 'deactivate', :via => [:get, :post]
|
||||
match 'my/twofa/select_scheme', :controller => 'twofa', :action => 'select_scheme', :via => :get
|
||||
match 'users/:user_id/twofa/deactivate', :controller => 'twofa', :action => 'admin_deactivate', :via => :post
|
||||
|
||||
resources :users do
|
||||
|
||||
@ -34,6 +34,9 @@ show_custom_fields_on_registration:
|
||||
lost_password:
|
||||
default: 1
|
||||
security_notifications: 1
|
||||
twofa:
|
||||
default: 1
|
||||
security_notifications: 1
|
||||
unsubscribe:
|
||||
default: 1
|
||||
password_required_char_classes:
|
||||
|
||||
@ -36,6 +36,11 @@ module Redmine
|
||||
for_twofa_scheme(user.twofa_scheme).try(:new, user)
|
||||
end
|
||||
|
||||
def self.unpair_all!
|
||||
users = User.where.not(twofa_scheme: nil)
|
||||
users.each { |u| self.for_user(u).destroy_pairing_without_verify! }
|
||||
end
|
||||
|
||||
def self.schemes
|
||||
initialize_schemes
|
||||
@@schemes
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user