From 8c6b709ee02fbcaf280dc80cd0ae36100c629487 Mon Sep 17 00:00:00 2001
From: Ere Maijala <ere.maijala@helsinki.fi>
Date: Mon, 9 Sep 2019 15:58:30 -0400
Subject: [PATCH] Add support for method delegation and CSRF bypassing in Auth.

---
 .../VuFind/src/VuFind/Auth/AbstractBase.php   | 30 +++++++++++++++++++
 module/VuFind/src/VuFind/Auth/Manager.php     | 21 +++++++++++--
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/module/VuFind/src/VuFind/Auth/AbstractBase.php b/module/VuFind/src/VuFind/Auth/AbstractBase.php
index b4eb40ab255..e01ecb93d2e 100644
--- a/module/VuFind/src/VuFind/Auth/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Auth/AbstractBase.php
@@ -121,6 +121,36 @@ abstract class AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface,
         $this->configValidated = false;
     }
 
+    /**
+     * Whether this authentication method needs CSRF checking for the request.
+     *
+     * @param \Zend\Http\PhpEnvironment\Request $request Request object.
+     *
+     * @return bool
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function needsCsrfCheck($request)
+    {
+        // Enabled by default
+        return true;
+    }
+
+    /**
+     * Returns any authentication method this request should be delegated to.
+     *
+     * @param \Zend\Http\PhpEnvironment\Request $request Request object.
+     *
+     * @return string|bool
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getDelegateAuthMethod(\Zend\Http\PhpEnvironment\Request $request)
+    {
+        // No delegate by default
+        return false;
+    }
+
     /**
      * Validate configuration parameters.  This is a support method for getConfig(),
      * so the configuration MUST be accessed using $this->config; do not call
diff --git a/module/VuFind/src/VuFind/Auth/Manager.php b/module/VuFind/src/VuFind/Auth/Manager.php
index 611aef87ece..ae0119c9c4c 100644
--- a/module/VuFind/src/VuFind/Auth/Manager.php
+++ b/module/VuFind/src/VuFind/Auth/Manager.php
@@ -604,8 +604,16 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
         // for example):
         $this->getAuth()->preLoginCheck($request);
 
+        // Check if the current auth method wants to delegate the request to another
+        // method:
+        if ($delegate = $this->getAuth()->getDelegateAuthMethod($request)) {
+            $this->setAuthMethod($delegate, true);
+        }
+
         // Validate CSRF for form-based authentication methods:
-        if (!$this->getAuth()->getSessionInitiator(null)) {
+        if (!$this->getAuth()->getSessionInitiator(null)
+            && $this->getAuth()->needsCsrfCheck($request)
+        ) {
             if (!$this->csrf->isValid($request->getPost()->get('csrf'))) {
                 $this->getAuth()->resetState();
                 throw new AuthException('authentication_error_technical');
@@ -645,15 +653,22 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
     /**
      * Setter
      *
-     * @param string $method The auth class to proxy
+     * @param string $method     The auth class to proxy
+     * @param bool   $forceLegal Whether to force the new method legal
      *
      * @return void
      */
-    public function setAuthMethod($method)
+    public function setAuthMethod($method, $forceLegal = false)
     {
         // Change the setting:
         $this->activeAuth = $method;
 
+        if ($forceLegal) {
+            if (!in_array($method, $this->legalAuthOptions)) {
+                $this->legalAuthOptions[] = $method;
+            }
+        }
+
         // If this method supports switching to a different method and we haven't
         // already initialized it, add those options to the whitelist. If the object
         // is already initialized, that means we've already gone through this step
-- 
GitLab