diff --git a/config/vufind/Alma.ini b/config/vufind/Alma.ini
index 100c029c7c704959681ea439b584ead8ba2713de..3b2017ad18ab6a19d28d83b165b428ac8f6d0966 100644
--- a/config/vufind/Alma.ini
+++ b/config/vufind/Alma.ini
@@ -3,7 +3,11 @@
 apiBaseUrl = "https://api-eu.hosted.exlibrisgroup.com/almaws/v1"
 ; An API key configured to allow access to Alma:
 apiKey = "your-key-here"
-
+; Patron login method to use. The following options are available:
+; vufind    Use VuFind's user database for authentication -- patrons are retrieved
+;           from Alma without a password (default)
+; password  Use password authentication with Alma internal users
+;loginMethod = vufind
 
 [Holds]
 ; HMACKeys - A list of hold form element names that will be analyzed for consistency
@@ -40,7 +44,7 @@ itemLimit = "10"
 ; Mandatory. The Alma user record type. Usually "PUBLIC".
 recordType = PUBLIC
 
-; Mandatory. The Alma user account type. Usually this is "INTERNAL" if you use the AlmaDatabase 
+; Mandatory. The Alma user account type. Usually this is "INTERNAL" if you use the AlmaDatabase
 ; authentication method.
 accountType = INTERNAL
 
@@ -49,27 +53,27 @@ status = ACTIVE
 
 ; Mandatory. The user group to which the new Alma account should belong. Use the code of one of
 ; the user groups that are defined in Alma (see "Alma Configuration -> User Management -> User Groups").
-userGroup = 
+userGroup =
 
 ; Mandatory. The type of ID under which the username should be saved to Alma. Log in to the ExLibris developer
 ; network and check the Alma API documentation for possible values on this site:
 ; https://developers.exlibrisgroup.com/alma/apis/xsd/rest_user.xsd?tags=POST#user_identifier
-idType = 
+idType =
 
 ; Mandatory. The preferred language of the new Alma account. This should normally be the Alma language
 ; code of your local language (see "Alma Configuration -> General -> Institution Languages").
-preferredLanguage = 
+preferredLanguage =
 
 ; Mandatory. The type of eMail of the users eMail address. Log in to the ExLibris developer network and
 ; check the Alma API documentation for possible values on this site:
 ; https://developers.exlibrisgroup.com/alma/apis/xsd/rest_user.xsd?tags=POST#email_types
-emailType = 
+emailType =
 
 ; Optional. Set the time period when the Alma account should expire. The given period will be added to the
 ; point in time of the Alma account creation. Use the DateInterval notation of PHP to express the period. See:
 ; https://secure.php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
 ; If not set, 1 year (P1Y) will be used as default value.
-expiryDate = 
+expiryDate =
 
 ; Optional. Set the time period that should be used for the Alma user account purge date. The given period
 ; will be added to the point in time of the Alma account creation. Use the DateInterval notation of PHP to
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Alma.php b/module/VuFind/src/VuFind/ILS/Driver/Alma.php
index 7974debf4b9cb0cf353a64bad66908497a82ef9a..b8c5f82938383f80e4561b0f0187fd919d033108 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Alma.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Alma.php
@@ -110,13 +110,17 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
     /**
      * Make an HTTP request against Alma
      *
-     * @param string        $path       Path to retrieve from API (excluding base
-     *                                  URL/API key)
-     * @param array         $paramsGet  Additional GET params
-     * @param array         $paramsPost Additional POST params
-     * @param string        $method     GET or POST. Default is GET.
-     * @param string        $rawBody    Request body.
-     * @param Headers|array $headers    Add headers to the call.
+     * @param string        $path          Path to retrieve from API (excluding base
+     *                                     URL/API key)
+     * @param array         $paramsGet     Additional GET params
+     * @param array         $paramsPost    Additional POST params
+     * @param string        $method        GET or POST. Default is GET.
+     * @param string        $rawBody       Request body.
+     * @param Headers|array $headers       Add headers to the call.
+     * @param array         $allowedErrors HTTP status codes that are not treated as
+     *                                     API errors.
+     * @param bool          $returnStatus  Whether to return HTTP status in addition
+     *                                     to the response.
      *
      * @throws ILSException
      * @return NULL|SimpleXMLElement
@@ -127,7 +131,9 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
         $paramsPost = [],
         $method = 'GET',
         $rawBody = null,
-        $headers = null
+        $headers = null,
+        $allowedErrors = [],
+        $returnStatus = false
     ) {
         // Set some variables
         $result = null;
@@ -150,17 +156,12 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
             // Set method
             $client->setMethod($method);
 
-            // Set other GET parameters
-            if ($method == 'GET') {
-                $client->setParameterGet($paramsGet);
-            } else {
-                // Always set API key as GET parameter
-                $client->setParameterGet(['apiKey' => $paramsGet['apiKey']]);
-
-                // Set POST parameters
-                if ($method == 'POST') {
-                    $client->setParameterPost($paramsPost);
-                }
+            // Set other GET parameters (apikey and other URL parameters are used
+            // also with e.g. POST requests)
+            $client->setParameterGet($paramsGet);
+            // Set POST parameters
+            if ($method == 'POST') {
+                $client->setParameterPost($paramsPost);
             }
 
             // Set body if applicable
@@ -212,7 +213,7 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
             );
             throw new ILSException($e->getMessage());
         }
-        if ($result->isSuccess()) {
+        if ($result->isSuccess() || in_array($statusCode, $allowedErrors)) {
             if (!$xml && $result->isServerError()) {
                 $error = 'XML is not valid or HTTP error, URL: ' . $url .
                     ', HTTP status code: ' . $statusCode;
@@ -236,7 +237,7 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
             );
         }
 
-        return $returnValue;
+        return $returnStatus ? [$returnValue, $statusCode] : $returnValue;
     }
 
     /**
@@ -489,7 +490,6 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
      */
     public function createAlmaUser($formParams)
     {
-
         // Get config for creating new Alma users from Alma.ini
         $newUserConfig = $this->config['NewUser'];
 
@@ -615,22 +615,52 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
      */
     public function patronLogin($barcode, $password)
     {
-        // Create array of get parameters for API call
-        $getParams = [
-            'user_id_type' => 'all_unique',
-            'view' => 'brief',
-            'expand' => 'none'
-        ];
+        $loginMethod = $this->config['Catalog']['loginMethod'] ?? 'vufind';
+        if ('password' === $loginMethod) {
+            // Create parameters for API call
+            $getParams = [
+                'user_id_type' => 'all_unique',
+                'op' => 'auth',
+                'password' => $password
+            ];
 
-        // Check for patron in Alma
-        $response = $this->makeRequest('/users/' . urlencode($barcode), $getParams);
+            // Try to authenticate the user with Alma
+            list($response, $status) = $this->makeRequest(
+                '/users/' . urlencode($barcode),
+                $getParams,
+                [],
+                'POST',
+                null,
+                null,
+                [400],
+                true
+            );
+            if (400 === $status) {
+                return null;
+            }
+        }
 
-        // Test once we have access
-        if ($response != null) {
-            return [
-                'cat_username' => trim($barcode),
-                'cat_password' => trim($password)
+        if ('password' === $loginMethod || 'vufind' === $loginMethod) {
+            // Create parameters for API call
+            $getParams = [
+                'user_id_type' => 'all_unique',
+                'view' => 'brief',
+                'expand' => 'none'
             ];
+
+            // Check for patron in Alma
+            $response = $this->makeRequest(
+                '/users/' . urlencode($barcode),
+                $getParams
+            );
+
+            if ($response !== null) {
+                return [
+                    'id' => (string)$response->primary_id,
+                    'cat_username' => trim($barcode),
+                    'cat_password' => trim($password)
+                ];
+            }
         }
 
         return null;