diff --git a/application/config/config.sample.php b/application/config/config.sample.php index 15c3cb3c7..db8660972 100644 --- a/application/config/config.sample.php +++ b/application/config/config.sample.php @@ -100,6 +100,11 @@ $config['qrzru_password'] = ''; | 'auth_mode' Minimum user level required 0 = anonymous, 1 = viewer, | 2 = editor, 3 = api user, 99 = owner | 'auth_level[]' Defines level titles +| +| 'auth_header_enable' False disables header based authentication +| 'auth_header_create' False disables user creation if user doesn't exist +| 'auth_header_value' Which header provides authenticated username +| 'auth_header_text' Display text on login screen */ $config['use_auth'] = true; @@ -109,6 +114,11 @@ $config['auth_mode'] = '3'; $config['auth_level'][3] = 'Operator'; $config['auth_level'][99] = 'Administrator'; +$config['auth_header_enable'] = false; +$config['auth_header_create'] = false; +$config['auth_header_value'] = "HTTP_X-Username"; +$config['auth_header_text'] = "Login with SSO"; + /* |-------------------------------------------------------------------------- | Base Site URL diff --git a/application/controllers/Header_auth.php b/application/controllers/Header_auth.php new file mode 100644 index 000000000..8037cc16f --- /dev/null +++ b/application/controllers/Header_auth.php @@ -0,0 +1,81 @@ +load->model('user_model'); + $this->load->library('session'); + $this->load->helper('url'); + } + + /** + * Authenticate using a trusted request header. + * Expected to be called from a login-screen button. + */ + public function login() + { + // Guard: feature must be enabled + if (!$this->config->item('auth_header_enable')) { + $this->session->set_flashdata('error', __('Header authentication is disabled.')); + redirect('user/login'); + } + + $headerName = $this->config->item('auth_header_value') ?: ''; + if (empty($headerName)) { + $this->session->set_flashdata('error', __('Missing header setting.')); + redirect('user/login'); + } + $username = $this->input->server($headerName, true); + + if (empty($username)) { + $this->session->set_flashdata('error', __('Missing username header.')); + redirect('user/login'); + } + + // Look up user by the header value + $query = $this->user_model->get($username); + if (!$query || $query->num_rows() !== 1) { + $this->session->set_flashdata('error', __('User not found.')); + redirect('user/login'); + } + + + $user = $query->row(); + + // Prevent clubstation direct login via header (mirrors User::login) + if (!empty($user->clubstation) && $user->clubstation == 1) { + $this->session->set_flashdata('error', __("You can't login to a clubstation directly. Use your personal account instead.")); + redirect('user/login'); + } + + // Maintenance mode check (admin only allowed) + if (ENVIRONMENT === 'maintenance' && (int)$user->user_type !== 99) { + $this->session->set_flashdata('error', __("Sorry. This instance is currently in maintenance mode. Only administrators are currently allowed to log in.")); + redirect('user/login'); + } + + // Establish session + $this->user_model->update_session($user->user_id); + $this->user_model->set_last_seen($user->user_id); + + // Set language cookie (mirrors User::login) + $cookie = [ + 'name' => $this->config->item('gettext_cookie', 'gettext'), + 'value' => $user->user_language, + 'expire' => 1000, + 'secure' => false, + ]; + $this->input->set_cookie($cookie); + + log_message('info', "User ID [{$user->user_id}] logged in via header auth."); + redirect('dashboard'); + } +} diff --git a/application/controllers/User.php b/application/controllers/User.php index 34069fe54..11e2c5c53 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -1211,6 +1211,8 @@ class User extends CI_Controller { if ($this->form_validation->run() == FALSE) { $data['page_title'] = __("Login"); $data['https_check'] = $this->https_check(); + $data['auth_header_enable'] = $this->config->item('auth_header_enable'); + $data['auth_header_text'] = $this->config->item('auth_header_text'); $this->load->view('interface_assets/mini_header', $data); $this->load->view('user/login'); $this->load->view('interface_assets/footer'); diff --git a/application/views/user/login.php b/application/views/user/login.php index c53fd56ed..102e6ff7b 100644 --- a/application/views/user/login.php +++ b/application/views/user/login.php @@ -73,6 +73,14 @@ " autocomplete="current-password"> + +
+ + + +
+
diff --git a/install/config/config.php b/install/config/config.php index 1e4ad582d..71c65a986 100644 --- a/install/config/config.php +++ b/install/config/config.php @@ -100,6 +100,11 @@ $config['qrzru_password'] = '%qrzru_password%'; | 'auth_mode' Minimum user level required 0 = anonymous, 1 = viewer, | 2 = editor, 3 = api user, 99 = owner | 'auth_level[]' Defines level titles +| +| 'auth_header_enable' False disables header based authentication +| 'auth_header_create' False disables user creation if user doesn't exist +| 'auth_header_value' Which header provides authenticated username +| 'auth_header_text' Display text on login screen */ $config['use_auth'] = true; @@ -109,6 +114,11 @@ $config['auth_mode'] = '3'; $config['auth_level'][3] = 'Operator'; $config['auth_level'][99] = 'Administrator'; +$config['auth_header_enable'] = false; +$config['auth_header_create'] = false; +$config['auth_header_value'] = "HTTP_X-Username"; +$config['auth_header_text'] = "Login with SSO"; + /* |-------------------------------------------------------------------------- | Base Site URL