diff --git a/README.md b/README.md
index 271ab6f..deb14b2 100644
--- a/README.md
+++ b/README.md
@@ -165,6 +165,56 @@ Add the following to your `config.php`:
[BasicAuth_0]: https://en.wikipedia.org/wiki/Basic_access_authentication
+HTTP (Generic HTTP Auth Interface)
+------
+
+Authenticate users against a generic HTTP authentication interface. This backend sends HTTP POST requests with user credentials to a configured endpoint and expects specific response codes for authentication validation.
+
+### Configuration
+The HTTP backend accepts three parameters: endpoint URL, optional hash algorithm, and optional access key.
+
+**⚠⚠ Warning:** make sure to use the URL of a correctly configured HTTP authentication server. The server must validate credentials properly and return HTTP 202 for successful authentication. ⚠⚠
+
+Add the following to your `config.php`:
+
+ 'user_backends' => array(
+ array(
+ 'class' => '\OCA\UserExternal\HTTP',
+ 'arguments' => array('https://example.com/auth_endpoint'),
+ ),
+ ),
+
+For password hashing (e.g., MD5, SHA1, SHA256), add the hash algorithm as second parameter:
+
+ 'user_backends' => array(
+ array(
+ 'class' => '\OCA\UserExternal\HTTP',
+ 'arguments' => array('https://example.com/auth_endpoint', 'md5'),
+ ),
+ ),
+
+For additional security with an access key:
+
+ 'user_backends' => array(
+ array(
+ 'class' => '\OCA\UserExternal\HTTP',
+ 'arguments' => array('https://example.com/auth_endpoint', 'sha1', 'your_secret_access_key'),
+ ),
+ ),
+
+### HTTP Request Format
+The backend sends POST requests with the following parameters:
+- `user`: The username
+- `password`: The password (hashed if hash algorithm is specified)
+- `accessKey`: The access key (if provided)
+
+### Expected Response
+The HTTP server must return HTTP status code **202** for successful authentication. Any other status code is treated as authentication failure.
+
+### Dependencies
+Uses Nextcloud's built-in HTTP client service (no additional dependencies required).
+
+
SSH
---
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 34cbe12..3e333a6 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -3,7 +3,7 @@
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
user_external
External user authentication
- Use external user authentication methods like IMAP, SMB, FTP, WebDAV, HTTP BasicAuth, SSH and XMPP
+ Use external user authentication methods like IMAP, SMB, FTP, WebDAV, HTTP BasicAuth, HTTP (Generic), SSH and XMPP
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\UserExternal;
+
+use OCP\Http\Client\IClientService;
+
+/**
+ * User authentication against a generic HTTP auth interface
+ *
+ * @category Apps
+ * @package UserExternal
+ * @author Sebastian Sterk https://wiuwiu.de/Imprint
+ * @license http://www.gnu.org/licenses/agpl AGPL
+ */
+class HTTP extends Base {
+ private $hashAlgo;
+ private $accessKey;
+ private $authenticationEndpoint;
+ private $httpClientService;
+
+ /**
+ * Create new HTTP authentication provider
+ *
+ * @param string $authenticationEndpoint The HTTP endpoint URL for authentication
+ * @param string|false $hashAlgo Hash algorithm for password (false for plain text)
+ * @param string $accessKey Access key for additional security
+ */
+ public function __construct($authenticationEndpoint, $hashAlgo = false, $accessKey = '') {
+ parent::__construct($authenticationEndpoint);
+ $this->authenticationEndpoint = $authenticationEndpoint;
+ $this->hashAlgo = $hashAlgo;
+ $this->accessKey = $accessKey;
+ $this->httpClientService = \OC::$server->get(IClientService::class);
+ }
+
+ /**
+ * Send user credentials to HTTP endpoint
+ *
+ * @param string $user The username
+ * @param string $password The password
+ *
+ * @return bool True if authentication successful, false otherwise
+ */
+ public function sendUserData($user, $password) {
+ if ($this->hashAlgo !== false) {
+ $password = $this->hashPassword($password);
+ }
+
+ try {
+ $client = $this->httpClientService->newClient();
+
+ $response = $client->post($this->authenticationEndpoint, [
+ 'form_params' => [
+ 'accessKey' => $this->accessKey,
+ 'user' => $user,
+ 'password' => $password
+ ],
+ 'timeout' => 10,
+ ]);
+
+ $statusCode = $response->getStatusCode();
+
+ if ($statusCode === 202) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (\Exception $e) {
+ \OC::$server->getLogger()->error(
+ 'ERROR: Could not connect to HTTP auth endpoint: ' . $e->getMessage(),
+ ['app' => 'user_external']
+ );
+ return false;
+ }
+ }
+
+ /**
+ * Hash password using configured algorithm
+ *
+ * @param string $password The plain text password
+ *
+ * @return string The hashed password
+ */
+ private function hashPassword($password) {
+ return hash($this->hashAlgo, $password);
+ }
+
+ /**
+ * Check if the password is correct without logging in the user
+ *
+ * @param string $uid The username
+ * @param string $password The password
+ *
+ * @return string|false The username on success, false on failure
+ */
+ public function checkPassword($uid, $password) {
+ if (isset($uid) && isset($password)) {
+ $authenticationStatus = $this->sendUserData($uid, $password);
+ if ($authenticationStatus) {
+ $uid = mb_strtolower($uid);
+ $this->storeUser($uid);
+ return $uid;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ }
+}
diff --git a/tests/config.php b/tests/config.php
index 3cfadba..8bd30e8 100644
--- a/tests/config.php
+++ b/tests/config.php
@@ -32,4 +32,12 @@
'user' => 'test',//valid username/password combination
'password' => 'test',
),
+ 'http' => array(
+ 'run' => false,
+ 'endpoint' => 'http://localhost/http_auth',
+ 'hashAlgo' => false, // or 'md5', 'sha1', etc.
+ 'accessKey' => 'your_access_key',
+ 'user' => 'test',//valid username/password combination
+ 'password' => 'test',
+ ),
);
diff --git a/tests/http.php b/tests/http.php
new file mode 100644
index 0000000..885d6ef
--- /dev/null
+++ b/tests/http.php
@@ -0,0 +1,40 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class Test_User_HTTP extends \Test\TestCase {
+ /**
+ * @var OC_User_HTTP $instance
+ */
+ private $instance;
+
+ private function getConfig() {
+ return include(__DIR__.'/config.php');
+ }
+
+ public function skip() {
+ $config = $this->getConfig();
+ $this->skipUnless($config['http']['run']);
+ }
+
+ protected function setUp() {
+ parent::setUp();
+
+ $config = $this->getConfig();
+ $this->instance = new OC_User_HTTP(
+ $config['http']['endpoint'],
+ $config['http']['hashAlgo'],
+ $config['http']['accessKey']
+ );
+ }
+
+ public function testLogin() {
+ $config = $this->getConfig();
+ $this->assertEquals($config['http']['user'], $this->instance->checkPassword($config['http']['user'], $config['http']['password']));
+ $this->assertFalse($this->instance->checkPassword($config['http']['user'], $config['http']['password'].'foo'));
+ }
+}