Patch for auth-remote

Simple plugin to allow custom headers. Don’t judge my php, I’ve been drinking.

I left the author alone cuz its a copy of auth_remote. Works great in docker (k8s) with TTRSS_AUTH_HEADER_USERNAME=HTTP_X_WHATEVER_HEADER_USER. The fullname is untested but email worked.

<?php
class Auth_Header extends Auth_Base {

  /** redirect user to this URL after logout; .env:
  * TTRSS_AUTH_HEADER_POST_LOGOUT_URL=http://127.0.0.1/logout-redirect
  */
  const AUTH_HEADER_POST_LOGOUT_URL = "AUTH_HEADER_POST_LOGOUT_URL";
  const AUTH_HEADER_EXTERNAL_USERNAME = "AUTH_HEADER_EXTERNAL_USERNAME";
  const AUTH_HEADER_EXTERNAL_FULLNAME = "AUTH_HEADER_EXTERNAL_FULLNAME";
  const AUTH_HEADER_EXTERNAL_EMAIL = "AUTH_HEADER_EXTERNAL_EMAIL";

  function about() {
    return array(null,
      "Authenticates against external passwords (HTTP Authentication) via header",
      "fox?",
      true);
  }

  function init($host) {
    $host->add_hook($host::HOOK_AUTH_USER, $this);

    Config::add(self::AUTH_HEADER_POST_LOGOUT_URL, "", Config::T_STRING);
    Config::add(self::AUTH_HEADER_EXTERNAL_USERNAME, "REMOTE_USER", Config::T_STRING);
    Config::add(self::AUTH_HEADER_EXTERNAL_FULLNAME, "HTTP_USER", Config::T_STRING);
    Config::add(self::AUTH_HEADER_EXTERNAL_EMAIL, "HTTP_USER_MAIL", Config::T_STRING);

    if (Config::get(self::AUTH_HEADER_POST_LOGOUT_URL) != "") {
      $host->add_hook($host::HOOK_POST_LOGOUT, $this);
    }
  }

  function authenticate($login, $password, $service = '') {
    $try_login = "";

    if (!empty($_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_USERNAME)])) {
      $try_login = $_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_USERNAME)];
    }

    if ($try_login) {
      $user_id = $this->auto_create_user($try_login, $password);

      if ($user_id) {
        $_SESSION["fake_login"] = $try_login;
        $_SESSION["fake_password"] = "******";
        $_SESSION["hide_hello"] = true;
        $_SESSION["hide_logout"] = true;
        $_SESSION["bw_limit"] = false;

        // LemonLDAP can send user informations via HTTP HEADER
        if (Config::get(Config::AUTH_AUTO_CREATE)) {
          // update user name
          $fullname = isset($_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_FULLNAME)]) ? $_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_FULLNAME)] : "";
          if ($fullname){
            $sth = $this->pdo->prepare("UPDATE ttrss_users SET full_name = ? WHERE id = ?");
            $sth->execute([$fullname, $user_id]);
          }
          // update user mail
          $email = isset($_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_EMAIL)]) ? $_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_EMAIL)] : "";
          if ($email){
            $sth = $this->pdo->prepare("UPDATE ttrss_users SET email = ? WHERE id = ?");
            $sth->execute([$email, $user_id]);
          }
        }

        return $user_id;
      }
    }

    return false;
  }

  function hook_post_logout($login, $user_id) {
    return [
      Config::get(self::AUTH_HEADER_POST_LOGOUT_URL)
      ];
  }

  function api_version() {
    return 2;
  }

}

Bringing this back from the dead because it has a bug. (So does auth_remote I suspect.)

If the username isn’t submitted in lower case, auto_create_account creates the account in lower case anyway, but then cannot log in because DisGuy != disguy. Since it attempts to create it again, it violates the unique key:

[EEE] 4 E_USER_WARNING (512) (classes/pluginhost.php:354) PDOException: SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint "ttrss_users_login_key"
DETAIL:  Key (login)=(disguy) already exists. in /app/vendor/j4mie/idiorm/idiorm.php:505
Stack trace:
#0 /app/vendor/j4mie/idiorm/idiorm.php(505): PDOStatement->execute()
#1 /app/vendor/j4mie/idiorm/idiorm.php(2090): ORM::_execute()
#2 /app/classes/auth/base.php(38): ORM->save()
#3 /app/plugins.local/auth_header/..2022_07_07_15_03_21.255316644/init.php(40): Auth_Base->auto_create_user()
#4 /app/classes/auth/base.php(12): Auth_Header->authenticate()
#5 /app/classes/pluginhost.php(351): Auth_Base->hook_auth_user()
#6 /app/classes/userhelper.php(40): PluginHost->chain_hooks_callback()
#7 /app/classes/userhelper.php(138): UserHelper::authenticate()
#8 /app/index.php(21): UserHelper::login_sequence()
#9 {main}

Wrapping line 36 in strtolower fixes it:

$try_login = strtolower($_SERVER[Config::get(self::AUTH_HEADER_EXTERNAL_USERNAME)]);

can you file a PR? otherwise i’ll try to fit this in on the weekend.

I would, but…

POST https://dev.tt-rss.org/user/login
Status 500 Internal Server Error

Same username. Trying to register says it exists.

that’s strange. i’ve just tried logging out and in and it worked fine. :thinking:

maybe it’s cloudflare being wonky again?

This time I got ‘bad password’ so I went through recovery. Email worked, but guess what happens when I submit a new pw: :face_with_diagonal_mouth:

POST https://dev.tt-rss.org/user/recover_account
Status 500 Internal Server Error

This isn’t a critical patch or anything so I’m happy to mess with git some other time.

is this a cloudflare error or a gitea error? post a screenshot. people do file PRs from time to time, so gitea shouldn’t be completely broken. :slight_smile:

p.s. maybe your user account got borked somehow. gitea is not exactly bug-free. if nothing else helps, i can delete it. PM me if you want me to.

https://dev.tt-rss.org/fox/tt-rss/pulls/75