You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
5.9 KiB
155 lines
5.9 KiB
<?php |
|
|
|
/** |
|
* Authorization functions. |
|
* |
|
* @package OpenEMR |
|
* @link https://www.open-emr.org |
|
* @author Rod Roark <rod@sunsetsystems.com> |
|
* @author Brady Miller <brady.g.miller@gmail.com> |
|
* @author Kevin Yeh <kevin.y@integralemr.com> |
|
* @author ViCarePlus <visolve_emr@visolve.com> |
|
* @author Ken Chapple <ken@mi-squared.com> |
|
* @author cfapress |
|
* @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com> |
|
* @copyright Copyright (c) 2021 Ken Chapple <ken@mi-squared.com> |
|
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 |
|
*/ |
|
|
|
use OpenEMR\Common\Auth\AuthUtils; |
|
use OpenEMR\Common\Logging\EventAuditLogger; |
|
use OpenEMR\Common\Session\SessionTracker; |
|
use OpenEMR\Services\UserService; |
|
|
|
$incoming_site_id = ''; |
|
// This is the conditional that ensures that the submission has the required parameters to attempt a login |
|
if ( |
|
isset($_GET['auth']) |
|
&& ($_GET['auth'] == "login") |
|
&& isset($_POST['new_login_session_management']) |
|
&& ( |
|
// Either normal login or google sign-in |
|
(isset($_POST['authUser']) && isset($_POST['clearPass'])) |
|
|| (!empty($GLOBALS['google_signin_enabled']) && !empty($GLOBALS['google_signin_client_id']) && !empty($_POST['used_google_signin']) && !empty($_POST['google_signin_token'])) |
|
) |
|
) { |
|
// Attempt login |
|
|
|
// set the language |
|
if (!empty($_POST['languageChoice'])) { |
|
$_SESSION['language_choice'] = $_POST['languageChoice']; |
|
} else { |
|
$_SESSION['language_choice'] = 1; |
|
} |
|
|
|
// set language direction according to language choice. Later in globals.php we'll override main theme name if needed. |
|
$_SESSION['language_direction'] = getLanguageDir($_SESSION['language_choice']); |
|
|
|
// Note we are purposefully keeping $_POST['clearPass'], which is needed for MFA to work. It is cleared from memory after a |
|
// unsuccessful or successful login |
|
$passTemp = $_POST['clearPass']; |
|
|
|
$login_success = false; |
|
if ( |
|
!empty($GLOBALS['google_signin_enabled']) && |
|
!empty($GLOBALS['google_signin_client_id']) && |
|
!empty($_POST['used_google_signin']) && |
|
!empty($_POST['google_signin_token']) |
|
) { |
|
// google sign-in |
|
$login_success = AuthUtils::verifyGoogleSignIn($_POST['google_signin_token']); |
|
} else { |
|
// normal login |
|
$login_success = (new AuthUtils('login'))->confirmPassword($_POST['authUser'], $passTemp); |
|
} |
|
|
|
if ($login_success !== true) { |
|
// login attempt failed |
|
$_SESSION['loginfailure'] = 1; |
|
if (function_exists('sodium_memzero')) { |
|
sodium_memzero($_POST["clearPass"]); |
|
} else { |
|
$_POST["clearPass"] = ''; |
|
} |
|
authLoginScreen(); |
|
} |
|
|
|
// login attempt success |
|
$_SESSION['loginfailure'] = null; |
|
unset($_SESSION['loginfailure']); |
|
|
|
// skip the session expiration check below since the entry in session_tracker is not ready yet |
|
$skipSessionExpirationCheck = true; |
|
} elseif ((isset($_GET['auth'])) && ($_GET['auth'] == "logout")) { |
|
// Logout |
|
// If session has timed out / been destroyed, logout record for null user/provider will be invalid. |
|
if (!empty($_SESSION['authUser']) && !empty($_SESSION['authProvider'])) { |
|
if ((isset($_GET['timeout'])) && ($_GET['timeout'] == "1")) { |
|
EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "timeout, so force logout"); |
|
} else { |
|
EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "success"); |
|
} |
|
} |
|
authCloseSession(); |
|
authLoginScreen(true); |
|
} else { |
|
// Check if session is valid (already logged in user) |
|
if (!AuthUtils::authCheckSession()) { |
|
// Session is not valid (this should only happen if a user's password is changed via another session while the user is logged in) |
|
EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "authCheckSession() check failed, so force logout"); |
|
authCloseSession(); |
|
authLoginScreen(true); |
|
} |
|
} |
|
|
|
// Ensure user has not timed out, if applicable |
|
// Have a mechanism to skip the timeout and timeout reset mechanisms if a skip_timeout_reset parameter exists. This |
|
// can be used by scripts that continually request information from the server; for example the Messages |
|
// and Reminders automated intermittent requests. |
|
// Also skipping this all on login since entry in session_tracker is not ready yet |
|
if (empty($skipSessionExpirationCheck) && empty($_REQUEST['skip_timeout_reset'])) { |
|
if (!SessionTracker::isSessionExpired()) { |
|
SessionTracker::updateSessionExpiration(); |
|
} else { |
|
// User has timed out. |
|
EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "timeout, so force logout"); |
|
authCloseSession(); |
|
authLoginScreen(true); |
|
} |
|
} |
|
|
|
require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php"); |
|
function authCloseSession() |
|
{ |
|
// Before destroying the session, save its site_id so that the next |
|
// login will default to that same site. |
|
global $incoming_site_id; |
|
$incoming_site_id = $_SESSION['site_id']; |
|
OpenEMR\Common\Session\SessionUtil::coreSessionDestroy(); |
|
} |
|
|
|
function authLoginScreen($timed_out = false) |
|
{ |
|
// See comment in authCloseSession(). |
|
global $incoming_site_id; |
|
?> |
|
<script> |
|
// Find the top level window for this instance of OpenEMR, set a flag indicating |
|
// session timeout has occurred, and reload the login page into it. This is so |
|
// that beforeunload event handlers will not obstruct the process in this case. |
|
var w = window; |
|
while (w.opener) { // in case we are in a dialog window |
|
var wtmp = w; |
|
w = w.opener; |
|
wtmp.close(); |
|
} |
|
<?php if ($timed_out) { ?> |
|
w.top.timed_out = true; |
|
<?php } ?> |
|
w.top.location.href = '<?php echo "{$GLOBALS['login_screen']}?error=1&site=$incoming_site_id"; ?>'; |
|
</script> |
|
<?php |
|
exit; |
|
} |
|
|
|
?>
|
|
|