From 9a813210b9a8a31ebd4c95bb59411930eadc8159 Mon Sep 17 00:00:00 2001
From: David Taylor <david@taylorhq.com>
Date: Mon, 9 Jul 2018 05:25:58 +0100
Subject: [PATCH] =?UTF-8?q?SECURITY:=20Do=20not=20allow=20authentication?=
 =?UTF-8?q?=20with=20disabled=20plugin-supplied=20a=E2=80=A6=20(#6071)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

 Do not allow authentication with disabled plugin-supplied auth providers
---
 .../users/omniauth_callbacks_controller.rb    |  7 ++--
 config/locales/server.en.yml                  |  2 ++
 .../omniauth_callbacks_controller_spec.rb     | 36 +++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb
index 9f708bd0cf7..f168403caaf 100644
--- a/app/controllers/users/omniauth_callbacks_controller.rb
+++ b/app/controllers/users/omniauth_callbacks_controller.rb
@@ -93,16 +93,19 @@ class Users::OmniauthCallbacksController < ApplicationController
   def self.find_authenticator(name)
     BUILTIN_AUTH.each do |authenticator|
       if authenticator.name == name
-        raise Discourse::InvalidAccess.new("provider is not enabled") unless SiteSetting.send("enable_#{name}_logins?")
+        raise Discourse::InvalidAccess.new(I18n.t("provider_not_enabled")) unless SiteSetting.send("enable_#{name}_logins?")
         return authenticator
       end
     end
 
     Discourse.auth_providers.each do |provider|
+      unless provider.enabled_setting.nil? || SiteSetting.send(provider.enabled_setting)
+        raise Discourse::InvalidAccess.new(I18n.t("provider_not_enabled"))
+      end
       return provider.authenticator if provider.name == name
     end
 
-    raise Discourse::InvalidAccess.new("provider is not found")
+    raise Discourse::InvalidAccess.new(I18n.t("provider_not_found"))
   end
 
   protected
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 9b5f0e82074..2d0602e7672 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -198,6 +198,8 @@ en:
   not_found: "The requested URL or resource could not be found."
   invalid_access: "You are not permitted to view the requested resource."
   invalid_api_credentials: "You are not permitted to view the requested resource. The API username or key is invalid."
+  provider_not_enabled: "You are not permitted to view the requested resource. The authentication provider is not enabled."
+  provider_not_found: "You are not permitted to view the requested resource. The authentication provider does not exist."
   read_only_mode_enabled: "The site is in read only mode. Interactions are disabled."
 
   reading_time: "Reading time"
diff --git a/spec/requests/omniauth_callbacks_controller_spec.rb b/spec/requests/omniauth_callbacks_controller_spec.rb
index c4deba0b83e..4ff4c58a977 100644
--- a/spec/requests/omniauth_callbacks_controller_spec.rb
+++ b/spec/requests/omniauth_callbacks_controller_spec.rb
@@ -33,6 +33,42 @@ RSpec.describe Users::OmniauthCallbacksController do
       expect(Users::OmniauthCallbacksController.find_authenticator("twitter"))
         .not_to eq(nil)
     end
+
+    context "with a plugin-contributed auth provider" do
+
+      let :provider do
+        provider = Plugin::AuthProvider.new
+        provider.authenticator = Auth::OpenIdAuthenticator.new('ubuntu', 'https://login.ubuntu.com', trusted: true)
+        provider.enabled_setting = "ubuntu_login_enabled"
+        provider
+      end
+
+      before do
+        Discourse.stubs(:auth_providers).returns [provider]
+      end
+
+      it "finds an authenticator when enabled" do
+        SiteSetting.stubs(:ubuntu_login_enabled).returns(true)
+
+        expect(Users::OmniauthCallbacksController.find_authenticator("ubuntu"))
+          .to be(provider.authenticator)
+      end
+
+      it "fails if an authenticator is disabled" do
+        SiteSetting.stubs(:ubuntu_login_enabled).returns(false)
+
+        expect { Users::OmniauthCallbacksController.find_authenticator("ubuntu") }
+          .to raise_error(Discourse::InvalidAccess)
+      end
+
+      it "succeeds if an authenticator does not have a site setting" do
+        provider.enabled_setting = nil
+        SiteSetting.stubs(:ubuntu_login_enabled).returns(false)
+
+        expect(Users::OmniauthCallbacksController.find_authenticator("ubuntu"))
+          .to be(provider.authenticator)
+      end
+    end
   end
 
   context 'Google Oauth2' do