Skip to content

Commit

Permalink
Check redirect url; only redirect to urls with local host
Browse files Browse the repository at this point in the history
  • Loading branch information
collectiveaccess committed Sep 24, 2021
1 parent 613988b commit 8034eb1
Showing 1 changed file with 175 additions and 162 deletions.
337 changes: 175 additions & 162 deletions app/controllers/system/AuthController.php
Expand Up @@ -7,7 +7,7 @@
* ----------------------------------------------------------------------
*
* Software by Whirl-i-Gig (http://www.whirl-i-gig.com)
* Copyright 2007-2018 Whirl-i-Gig
* Copyright 2007-2021 Whirl-i-Gig
*
* For more information visit http://www.CollectiveAccess.org
*
Expand All @@ -25,190 +25,203 @@
*
* ----------------------------------------------------------------------
*/
require_once(__CA_LIB_DIR__.'/WidgetManager.php');
require_once(__CA_LIB_DIR__.'/Auth/AuthenticationManager.php');

class AuthController extends ActionController {
# -------------------------------------------------------
require_once(__CA_LIB_DIR__.'/WidgetManager.php');
require_once(__CA_LIB_DIR__.'/Auth/AuthenticationManager.php');

class AuthController extends ActionController {
# -------------------------------------------------------

# -------------------------------------------------------
public function __construct(&$po_request, &$po_response, $pa_view_paths=null) {
parent::__construct($po_request, $po_response, $pa_view_paths);
if (AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_USE_ADAPTER_LOGIN_FORM__) && !in_array($this->request->getAction(), ['logout', 'callback'])) {
$po_response->setRedirect($po_request->getBaseUrlPath().'/'.$po_request->getScriptName().'/'.$po_request->config->get("auth_login_welcome_path"));
$po_response->sendResponse();
exit;
}
}
# -------------------------------------------------------
public function Login() {
global $g_ui_locale;
if (isset($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) {
if(!initializeLocale($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) die("Error loading locale ".$g_ui_locale);
}
// Redirect to the default action
$vs_redirect = $this->_getRedirectUrl();

$this->getView()->setVar('redirect', $vs_redirect);
$this->render('login_html.php');
}
# -------------------------------------------------------
public function DoLogin() {
if (!caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('login_html.php');
return;
}
global $g_ui_locale;

# -------------------------------------------------------
public function __construct(&$po_request, &$po_response, $pa_view_paths=null) {
parent::__construct($po_request, $po_response, $pa_view_paths);
if (AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_USE_ADAPTER_LOGIN_FORM__) && !in_array($this->request->getAction(), ['logout', 'callback'])) {
$po_response->setRedirect($po_request->getBaseUrlPath().'/'.$po_request->getScriptName().'/'.$po_request->config->get("auth_login_welcome_path"));
$po_response->sendResponse();
exit;
}
}
# -------------------------------------------------------

public function Login() {
global $g_ui_locale;
$vs_redirect_url = $this->_getRedirectUrl();
if (!$this->request->doAuthentication(array('dont_redirect_to_login' => true, 'redirect' => $vs_redirect_url, 'noPublicUsers' => true, 'user_name' => $this->request->getParameter('username', pString), 'password' => $this->request->getParameter('password', pString)))) {
$this->notification->addNotification(_t("Login was invalid"), __NOTIFICATION_TYPE_ERROR__);

$this->view->setVar('notifications', $this->notification->getNotifications());
if (isset($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) {
if(!initializeLocale($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) die("Error loading locale ".$g_ui_locale);
}
// Redirect to the default action
$vs_redirect = $this->request->getParameter('redirect', pString);
$this->getView()->setVar('redirect', $vs_redirect);
$this->render('login_html.php');
}
# -------------------------------------------------------
public function DoLogin() {
if (!caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('login_html.php');
return;
}
global $g_ui_locale;

$vs_redirect_url = $this->request->getParameter('redirect', pString) ?: caNavUrl($this->request, null, null, null);
if (!$this->request->doAuthentication(array('dont_redirect_to_login' => true, 'redirect' => $vs_redirect_url, 'noPublicUsers' => true, 'user_name' => $this->request->getParameter('username', pString), 'password' => $this->request->getParameter('password', pString)))) {
$this->notification->addNotification(_t("Login was invalid"), __NOTIFICATION_TYPE_ERROR__);

$this->view->setVar('notifications', $this->notification->getNotifications());
if (isset($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) {
if(!initializeLocale($_COOKIE['CA_'.__CA_APP_NAME__.'_ui_locale'])) die("Error loading locale ".$g_ui_locale);
}
$this->render('login_html.php');
} else {
//
// Reset locale globals
//
global $g_ui_locale_id, $g_ui_locale, $g_ui_units_pref, $_, $_locale;
$g_ui_locale_id = $this->request->user->getPreferredUILocaleID(); // get current UI locale as locale_id (available as global)
$g_ui_locale = $this->request->user->getPreferredUILocale(); // get current UI locale as locale string (available as global)
$g_ui_units_pref = $this->request->user->getPreference('units'); // user's selected display units for measurements (available as global)

if(!initializeLocale($g_ui_locale)) die("Error loading locale ".$g_ui_locale);
MemoryCache::flush('translation');
AppNavigation::clearMenuBarCache($this->request); // want to clear menu bar on login

// Notify the user of the good news
$this->notification->addNotification(_t("You are now logged in"), __NOTIFICATION_TYPE_INFO__);

// Jump to redirect if set
if ($vs_redirect_url) $this->redirect($vs_redirect_url);
$this->render('welcome_html.php');
}
}
# -------------------------------------------------------
public function Welcome() {
AppNavigation::clearMenuBarCache($this->request); // clear menu bar cache on welcome (stealth debugging tool)

$this->render('welcome_html.php');
}
# -------------------------------------------------------
public function Logout() {
$this->request->deauthenticate();

AppNavigation::clearMenuBarCache($this->request); // clear menu bar cache on logout just in case
$this->notification->addNotification(_t("You are now logged out"), __NOTIFICATION_TYPE_INFO__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('logged_out_html.php');
}
# -------------------------------------------------------
public function Forgot() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }

$this->render('forgot_password_html.php');
}
# -------------------------------------------------------
public function RequestPassword() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }
if (caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$vs_username = $this->getRequest()->getParameter('username',pString);
$t_user = new ca_users();

if($t_user->load($vs_username)) {
$t_user->requestPasswordReset();
} else {
sleep(2);
}
}
// render the same static view no matter if something was actually done.
// otherwise you could figure out which user names exist and which don't
$this->render('password_reset_instructions_html.php');
$this->render('login_html.php');
} else {
//
// Reset locale globals
//
global $g_ui_locale_id, $g_ui_locale, $g_ui_units_pref, $_, $_locale;
$g_ui_locale_id = $this->request->user->getPreferredUILocaleID(); // get current UI locale as locale_id (available as global)
$g_ui_locale = $this->request->user->getPreferredUILocale(); // get current UI locale as locale string (available as global)
$g_ui_units_pref = $this->request->user->getPreference('units'); // user's selected display units for measurements (available as global)

if(!initializeLocale($g_ui_locale)) die("Error loading locale ".$g_ui_locale);
MemoryCache::flush('translation');
AppNavigation::clearMenuBarCache($this->request); // want to clear menu bar on login

// Notify the user of the good news
$this->notification->addNotification(_t("You are now logged in"), __NOTIFICATION_TYPE_INFO__);

// Jump to redirect if set
if ($vs_redirect_url) $this->redirect($vs_redirect_url);
$this->render('welcome_html.php');
}
# -------------------------------------------------------
public function InitReset() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }
}
# -------------------------------------------------------
public function Welcome() {
AppNavigation::clearMenuBarCache($this->request); // clear menu bar cache on welcome (stealth debugging tool)

$this->render('welcome_html.php');
}
# -------------------------------------------------------
public function Logout() {
$this->request->deauthenticate();

AppNavigation::clearMenuBarCache($this->request); // clear menu bar cache on logout just in case
$this->notification->addNotification(_t("You are now logged out"), __NOTIFICATION_TYPE_INFO__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('logged_out_html.php');
}
# -------------------------------------------------------
public function Forgot() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }

$vs_token = $this->getRequest()->getParameter('token',pString);
$this->render('forgot_password_html.php');
}
# -------------------------------------------------------
public function RequestPassword() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }
if (caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$vs_username = $this->getRequest()->getParameter('username',pString);
$t_user = new ca_users();

$vb_render_form = false;
if($t_user->load($vs_username)) {
if($t_user->isValidToken($vs_token)) {
$vb_render_form = true;
}
$t_user->requestPasswordReset();
} else {
sleep(2);
}
}
// render the same static view no matter if something was actually done.
// otherwise you could figure out which user names exist and which don't
$this->render('password_reset_instructions_html.php');
}
# -------------------------------------------------------
public function InitReset() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }

$this->view->setVar('renderForm', $vb_render_form);
$this->view->setVar('token', $vs_token);
$this->view->setVar('username', $vs_username);
$vs_token = $this->getRequest()->getParameter('token',pString);
$vs_username = $this->getRequest()->getParameter('username',pString);
$t_user = new ca_users();

$this->render('password_reset_form_html.php');
$vb_render_form = false;
if($t_user->load($vs_username)) {
if($t_user->isValidToken($vs_token)) {
$vb_render_form = true;
}
}
# -------------------------------------------------------
public function DoReset() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }
if (!caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$this->Login();
return;
}

$vs_token = $this->getRequest()->getParameter('token',pString);
$vs_username = $this->getRequest()->getParameter('username',pString);
$t_user = new ca_users();

$vs_pw = $this->getRequest()->getParameter('password',pString);
$vs_pw_check = $this->getRequest()->getParameter('password2',pString);
$this->view->setVar('renderForm', $vb_render_form);
$this->view->setVar('token', $vs_token);
$this->view->setVar('username', $vs_username);

if($t_user->load($vs_username)) {
if($t_user->isValidToken($vs_token)) {
// no password match
if($vs_pw !== $vs_pw_check) {
$this->render('password_reset_form_html.php');
}
# -------------------------------------------------------
public function DoReset() {
if(!AuthenticationManager::supports(__CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__)) { $this->Login(); return; }
if (!caValidateCSRFToken($this->request, null, ['notifications' => $this->notification])) {
$this->Login();
return;
}

$this->notification->addNotification(_t("Passwords did not match. Please try again."), __NOTIFICATION_TYPE_ERROR__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$vs_token = $this->getRequest()->getParameter('token',pString);
$vs_username = $this->getRequest()->getParameter('username',pString);
$t_user = new ca_users();

$this->view->setVar('renderForm', true);
$this->view->setVar('token', $vs_token);
$this->view->setVar('username', $vs_username);
$vs_pw = $this->getRequest()->getParameter('password',pString);
$vs_pw_check = $this->getRequest()->getParameter('password2',pString);

$this->render('password_reset_form_html.php');
} else {
$t_user->set('password', $vs_pw);
$t_user->setMode(ACCESS_WRITE);
$t_user->update();
if($t_user->load($vs_username)) {
if($t_user->isValidToken($vs_token)) {
// no password match
if($vs_pw !== $vs_pw_check) {

$this->notification->addNotification(_t("Password was successfully changed. You can now log in with your new password."), __NOTIFICATION_TYPE_INFO__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->notification->addNotification(_t("Passwords did not match. Please try again."), __NOTIFICATION_TYPE_ERROR__);
$this->view->setVar('notifications', $this->notification->getNotifications());

$this->Login();
}
$this->view->setVar('renderForm', true);
$this->view->setVar('token', $vs_token);
$this->view->setVar('username', $vs_username);

$this->render('password_reset_form_html.php');
} else {
$t_user->set('password', $vs_pw);
$t_user->setMode(ACCESS_WRITE);
$t_user->update();

$this->notification->addNotification(_t("Password was successfully changed. You can now log in with your new password."), __NOTIFICATION_TYPE_INFO__);
$this->view->setVar('notifications', $this->notification->getNotifications());

$this->Login();
}
}
}

}
# -------------------------------------------------------
# Authentication callback handler
# Passes control to authentication manager callback handler
# Authentication adapters for schemes like Okta can use this to
# implement required control flow elements
# -------------------------------------------------------
/**
*
*/
public function callback() {
try {
AuthenticationManager::callback();
} catch (Exception $e) {
$this->notification->addNotification($e->getMessage(), __NOTIFICATION_TYPE_ERROR__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('auth_error_html.php');
}
# -------------------------------------------------------
# Authentication callback handler
# Passes control to authentication manager callback handler
# Authentication adapters for schemes like Okta can use this to
# implement required control flow elements
# -------------------------------------------------------
/**
*
*/
public function callback() {
try {
AuthenticationManager::callback();
} catch (Exception $e) {
$this->notification->addNotification($e->getMessage(), __NOTIFICATION_TYPE_ERROR__);
$this->view->setVar('notifications', $this->notification->getNotifications());
$this->render('auth_error_html.php');
}
}
# -------------------------------------------------------
/**
*
*/
private function _getRedirectUrl() {
$host = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'];
$redirect_url = $this->request->getParameter('redirect', pString, null, ['forcePurify' => true]) ?: caNavUrl($this->request, null, null, null);

if(!preg_match('!^'.preg_quote($host, '!').'!', $redirect_url)) {
$redirect_url = null;
}
# -------------------------------------------------------
}
return $redirect_url;
}
# -------------------------------------------------------
}

0 comments on commit 8034eb1

Please sign in to comment.