DEV: If only one auth provider is enabled allow GET request

DEV: If only one auth provider is enabled allow GET request

In this case, the auth provider is acting as a SSO provider, and can be trusted to maintain its own CSRF protections.

diff --git a/config/initializers/009-omniauth.rb b/config/initializers/009-omniauth.rb
index 415e3b3..6acc285 100644
--- a/config/initializers/009-omniauth.rb
+++ b/config/initializers/009-omniauth.rb
@@ -7,4 +7,3 @@ require "middleware/omniauth_bypass_middleware"
 Rails.application.config.middleware.use Middleware::OmniauthBypassMiddleware
 
 OmniAuth.config.logger = Rails.logger
-OmniAuth.config.allowed_request_methods = [:post]
diff --git a/lib/middleware/omniauth_bypass_middleware.rb b/lib/middleware/omniauth_bypass_middleware.rb
index c40c892..92f3c97 100644
--- a/lib/middleware/omniauth_bypass_middleware.rb
+++ b/lib/middleware/omniauth_bypass_middleware.rb
@@ -22,8 +22,10 @@ class Middleware::OmniauthBypassMiddleware
     end
 
     @omniauth.before_request_phase do |env|
-      # Check for CSRF token
-      CSRFTokenVerifier.new.call(env)
+      request = ActionDispatch::Request.new(env)
+
+      # Check for CSRF token in POST requests
+      CSRFTokenVerifier.new.call(env) if request.request_method.downcase.to_sym != :get
 
       # Check whether the authenticator is enabled
       if !Discourse.enabled_authenticators.any? { |a| a.name == env['omniauth.strategy'].name }
@@ -31,7 +33,6 @@ class Middleware::OmniauthBypassMiddleware
       end
 
       # If the user is trying to reconnect to an existing account, store in session
-      request = ActionDispatch::Request.new(env)
       request.session[:auth_reconnect] = !!request.params["reconnect"]
     end
   end
@@ -39,6 +40,10 @@ class Middleware::OmniauthBypassMiddleware
   def call(env)
     if env["PATH_INFO"].start_with?("/auth")
       begin
+        # When only one provider is enabled, assume it can be completely trusted, and allow GET requests
+        only_one_provider = !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1
+        OmniAuth.config.allowed_request_methods = only_one_provider ? [:get, :post] : [:post]
+
         @omniauth.call(env)
       rescue AuthenticatorDisabled => e
         #  Authenticator is disabled, pretend it doesn't exist and pass request to app
diff --git a/spec/requests/omniauth_callbacks_controller_spec.rb b/spec/requests/omniauth_callbacks_controller_spec.rb
index 63850f6..25d9238 100644
--- a/spec/requests/omniauth_callbacks_controller_spec.rb
+++ b/spec/requests/omniauth_callbacks_controller_spec.rb
@@ -146,6 +146,14 @@ RSpec.describe Users::OmniauthCallbacksController do
           post "/auth/google_oauth2", params: { authenticity_token: token }
           expect(response.status).to eq(302)
         end
+
+        it "should not be CSRF protected if it is the only auth method" do
+          get "/auth/google_oauth2"
+          expect(response.status).to eq(200)
+          SiteSetting.enable_local_logins = false
+          get "/auth/google_oauth2"
+          expect(response.status).to eq(302)
+        end
       end
     end

GitHub sha: 1a8fee11

1 Like