Add OMNIAUTH_ONLY environment variable to enforce externa log-in (#17288)
* Remove support for OAUTH_REDIRECT_AT_SIGN_IN Fixes #15959 Introduced in #6540, OAUTH_REDIRECT_AT_SIGN_IN allowed skipping the log-in form to instead redirect to the external OmniAuth login provider. However, it did not prevent the log-in form on /about introduced by #10232 from appearing, and completely broke with the introduction of #15228. As I restoring that previous log-in flow without introducing a security vulnerability may require extensive care and knowledge of how OmniAuth works, this commit removes support for OAUTH_REDIRECT_AT_SIGN_IN instead for the time being. * Add OMNIAUTH_ONLY environment variable to enforce external log-in only * Disable user registration when OMNIAUTH_ONLY is set to true * Replace log-in links When OMNIAUTH_ONLY is set with exactly one OmniAuth provider
This commit is contained in:
		| @@ -83,10 +83,14 @@ class Api::V1::AccountsController < Api::BaseController | ||||
|   end | ||||
|  | ||||
|   def check_enabled_registrations | ||||
|     forbidden if single_user_mode? || !allowed_registrations? | ||||
|     forbidden if single_user_mode? || omniauth_only? || !allowed_registrations? | ||||
|   end | ||||
|  | ||||
|   def allowed_registrations? | ||||
|     Setting.registrations_mode != 'none' | ||||
|   end | ||||
|  | ||||
|   def omniauth_only? | ||||
|     ENV['OMNIAUTH_ONLY'] == 'true' | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -81,13 +81,17 @@ class Auth::RegistrationsController < Devise::RegistrationsController | ||||
|   end | ||||
|  | ||||
|   def check_enabled_registrations | ||||
|     redirect_to root_path if single_user_mode? || !allowed_registrations? | ||||
|     redirect_to root_path if single_user_mode? || omniauth_only? || !allowed_registrations? | ||||
|   end | ||||
|  | ||||
|   def allowed_registrations? | ||||
|     Setting.registrations_mode != 'none' || @invite&.valid_for_use? | ||||
|   end | ||||
|  | ||||
|   def omniauth_only? | ||||
|     ENV['OMNIAUTH_ONLY'] == 'true' | ||||
|   end | ||||
|  | ||||
|   def invite_code | ||||
|     if params[:user] | ||||
|       params[:user][:invite_code] | ||||
|   | ||||
| @@ -50,13 +50,37 @@ module ApplicationHelper | ||||
|   end | ||||
|  | ||||
|   def available_sign_up_path | ||||
|     if closed_registrations? | ||||
|     if closed_registrations? || omniauth_only? | ||||
|       'https://joinmastodon.org/#getting-started' | ||||
|     else | ||||
|       new_user_registration_path | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def omniauth_only? | ||||
|     ENV['OMNIAUTH_ONLY'] == 'true' | ||||
|   end | ||||
|  | ||||
|   def link_to_login(name = nil, html_options = nil, &block) | ||||
|     target = new_user_session_path | ||||
|  | ||||
|     if omniauth_only? && Devise.mappings[:user].omniauthable? && User.omniauth_providers.size == 1 | ||||
|       target = omniauth_authorize_path(:user, User.omniauth_providers[0]) | ||||
|       html_options ||= {} | ||||
|       html_options[:method] = :post | ||||
|     end | ||||
|  | ||||
|     if block_given? | ||||
|       link_to(target, html_options, &block) | ||||
|     else | ||||
|       link_to(name, target, html_options) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def provider_sign_in_link(provider) | ||||
|     link_to I18n.t("auth.providers.#{provider}", default: provider.to_s.chomp('_oauth2').capitalize), omniauth_authorize_path(:user, provider), class: "button button-#{provider}", method: :post | ||||
|   end | ||||
|  | ||||
|   def open_deletion? | ||||
|     Setting.open_deletion | ||||
|   end | ||||
|   | ||||
| @@ -1,13 +1,22 @@ | ||||
| = simple_form_for(new_user, url: user_session_path, namespace: 'login') do |f| | ||||
|   .fields-group | ||||
|     - if use_seamless_external_login? | ||||
|       = f.input :email, placeholder: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false | ||||
|     - else | ||||
|       = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false | ||||
| - unless omniauth_only? | ||||
|   = simple_form_for(new_user, url: user_session_path, namespace: 'login') do |f| | ||||
|     .fields-group | ||||
|       - if use_seamless_external_login? | ||||
|         = f.input :email, placeholder: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false | ||||
|       - else | ||||
|         = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false | ||||
|  | ||||
|     = f.input :password, placeholder: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password') }, hint: false | ||||
|       = f.input :password, placeholder: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password') }, hint: false | ||||
|  | ||||
|   .actions | ||||
|     = f.button :button, t('auth.login'), type: :submit, class: 'button button-primary' | ||||
|     .actions | ||||
|       = f.button :button, t('auth.login'), type: :submit, class: 'button button-primary' | ||||
|  | ||||
|   %p.hint.subtle-hint= link_to t('auth.trouble_logging_in'), new_user_password_path | ||||
|     %p.hint.subtle-hint= link_to t('auth.trouble_logging_in'), new_user_password_path | ||||
|  | ||||
| - if Devise.mappings[:user].omniauthable? and User.omniauth_providers.any? | ||||
|   .simple_form.alternative-login | ||||
|     %h4= omniauth_only? ? t('auth.log_in_with') : t('auth.or_log_in_with') | ||||
|  | ||||
|     .actions | ||||
|       - User.omniauth_providers.each do |provider| | ||||
|         = provider_sign_in_link(provider) | ||||
|   | ||||
| @@ -4,24 +4,25 @@ | ||||
| - content_for :header_tags do | ||||
|   = render partial: 'shared/og' | ||||
|  | ||||
| = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| | ||||
|   .fields-group | ||||
|     - if use_seamless_external_login? | ||||
|       = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false | ||||
|     - else | ||||
|       = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false | ||||
|   .fields-group | ||||
|     = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false | ||||
| - unless omniauth_only? | ||||
|   = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| | ||||
|     .fields-group | ||||
|       - if use_seamless_external_login? | ||||
|         = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false | ||||
|       - else | ||||
|         = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false | ||||
|     .fields-group | ||||
|       = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false | ||||
|  | ||||
|   .actions | ||||
|     = f.button :button, t('auth.login'), type: :submit | ||||
|     .actions | ||||
|       = f.button :button, t('auth.login'), type: :submit | ||||
|  | ||||
| - if devise_mapping.omniauthable? and resource_class.omniauth_providers.any? | ||||
|   .simple_form.alternative-login | ||||
|     %h4= t('auth.or_log_in_with') | ||||
|     %h4= omniauth_only? ? t('auth.log_in_with') : t('auth.or_log_in_with') | ||||
|  | ||||
|     .actions | ||||
|       - resource_class.omniauth_providers.each do |provider| | ||||
|         = link_to t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize), omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}", method: :post | ||||
|         = provider_sign_in_link(provider) | ||||
|  | ||||
| .form-footer= render 'auth/shared/links' | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|     %li= link_to t('settings.account_settings'), edit_user_registration_path | ||||
|   - else | ||||
|     - if controller_name != 'sessions' | ||||
|       %li= link_to t('auth.login'), new_user_session_path | ||||
|       %li= link_to_login t('auth.login') | ||||
|  | ||||
|     - if controller_name != 'registrations' | ||||
|       %li= link_to t('auth.register'), available_sign_up_path | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
|             - if user_signed_in? | ||||
|               = link_to t('settings.back'), root_url, class: 'nav-link nav-button webapp-btn' | ||||
|             - else | ||||
|               = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn nav-link nav-button' | ||||
|               = link_to_login t('auth.login'), class: 'webapp-btn nav-link nav-button' | ||||
|               = link_to t('auth.register'), available_sign_up_path, class: 'webapp-btn nav-link nav-button' | ||||
|  | ||||
|     .container= yield | ||||
|   | ||||
| @@ -56,6 +56,6 @@ | ||||
|  | ||||
| - if include_threads && !embedded_view? && !user_signed_in? | ||||
|   .entry{ class: entry_classes } | ||||
|     = link_to new_user_session_path, class: 'load-more load-gap' do | ||||
|     = link_to_login class: 'load-more load-gap' do | ||||
|       = fa_icon 'comments' | ||||
|       = t('statuses.sign_in_to_participate') | ||||
|   | ||||
| @@ -844,6 +844,7 @@ en: | ||||
|     invalid_reset_password_token: Password reset token is invalid or expired. Please request a new one. | ||||
|     link_to_otp: Enter a two-factor code from your phone or a recovery code | ||||
|     link_to_webauth: Use your security key device | ||||
|     log_in_with: Log in with | ||||
|     login: Log in | ||||
|     logout: Logout | ||||
|     migrate_account: Move to a different account | ||||
|   | ||||
		Reference in New Issue
	
	Block a user