about summary refs log tree commit diff
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-01-23 15:52:58 +0100
committerGitHub <noreply@github.com>2022-01-23 15:52:58 +0100
commitbddd9ba36d9f4e86e2a4bbea77f967c143afa2cc (patch)
tree8614b0600d7b8f0a0186b4a0711ff49f26fdff88
parentcfa583fa7111cfc16b9ce548f9d9b58963f154bd (diff)
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
-rw-r--r--app/controllers/api/v1/accounts_controller.rb6
-rw-r--r--app/controllers/auth/registrations_controller.rb6
-rw-r--r--app/helpers/application_helper.rb26
-rw-r--r--app/views/about/_login.html.haml29
-rw-r--r--app/views/auth/sessions/new.html.haml25
-rw-r--r--app/views/auth/shared/_links.html.haml2
-rw-r--r--app/views/layouts/public.html.haml2
-rw-r--r--app/views/statuses/_status.html.haml2
-rw-r--r--config/locales/en.yml1
9 files changed, 71 insertions, 28 deletions
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index cbccd64f3..5c47158e0 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -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
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 3c1730f25..f37e906fd 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -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]
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 34fc46615..9e16de5b5 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -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
diff --git a/app/views/about/_login.html.haml b/app/views/about/_login.html.haml
index fa58f04d7..0f19e8164 100644
--- a/app/views/about/_login.html.haml
+++ b/app/views/about/_login.html.haml
@@ -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)
diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml
index 9713bdaeb..a4323d1d9 100644
--- a/app/views/auth/sessions/new.html.haml
+++ b/app/views/auth/sessions/new.html.haml
@@ -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'
diff --git a/app/views/auth/shared/_links.html.haml b/app/views/auth/shared/_links.html.haml
index 66ed5b93f..f078e2f7e 100644
--- a/app/views/auth/shared/_links.html.haml
+++ b/app/views/auth/shared/_links.html.haml
@@ -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
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index bdb8a3a8e..069931cfd 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -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
diff --git a/app/views/statuses/_status.html.haml b/app/views/statuses/_status.html.haml
index 9f3197d0d..3b7152753 100644
--- a/app/views/statuses/_status.html.haml
+++ b/app/views/statuses/_status.html.haml
@@ -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')
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 13a252a47..85aa87c7a 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -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