chore: ci mariadb stuff - added 11.1 and removed 10.9 (#6834)
[openemr.git] / library / auth.inc.php
blobb80721c3a665b7e53f7a31b238a70ccccb323fdd
1 <?php
3 /**
4 * Authorization functions.
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Kevin Yeh <kevin.y@integralemr.com>
11 * @author ViCarePlus <visolve_emr@visolve.com>
12 * @author Ken Chapple <ken@mi-squared.com>
13 * @author cfapress
14 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
15 * @copyright Copyright (c) 2021 Ken Chapple <ken@mi-squared.com>
16 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19 use OpenEMR\Common\Auth\AuthUtils;
20 use OpenEMR\Common\Logging\EventAuditLogger;
21 use OpenEMR\Common\Session\SessionTracker;
22 use OpenEMR\Services\UserService;
24 $incoming_site_id = '';
25 // This is the conditional that ensures that the submission has the required parameters to attempt a login
26 if (
27 isset($_GET['auth'])
28 && ($_GET['auth'] == "login")
29 && isset($_POST['new_login_session_management'])
30 && (
31 // Either normal login or google sign-in
32 (isset($_POST['authUser']) && isset($_POST['clearPass']))
33 || (!empty($GLOBALS['google_signin_enabled']) && !empty($GLOBALS['google_signin_client_id']) && !empty($_POST['used_google_signin']) && !empty($_POST['google_signin_token']))
35 ) {
36 // Attempt login
38 // set the language
39 if (!empty($_POST['languageChoice'])) {
40 $_SESSION['language_choice'] = $_POST['languageChoice'];
41 } else {
42 $_SESSION['language_choice'] = 1;
45 // set language direction according to language choice. Later in globals.php we'll override main theme name if needed.
46 $_SESSION['language_direction'] = getLanguageDir($_SESSION['language_choice']);
48 // Note we are purposefully keeping $_POST['clearPass'], which is needed for MFA to work. It is cleared from memory after a
49 // unsuccessful or successful login
50 $passTemp = $_POST['clearPass'];
52 $login_success = false;
53 if (
54 !empty($GLOBALS['google_signin_enabled']) &&
55 !empty($GLOBALS['google_signin_client_id']) &&
56 !empty($_POST['used_google_signin']) &&
57 !empty($_POST['google_signin_token'])
58 ) {
59 // google sign-in
60 $login_success = AuthUtils::verifyGoogleSignIn($_POST['google_signin_token']);
61 } else {
62 // normal login
63 $login_success = (new AuthUtils('login'))->confirmPassword($_POST['authUser'], $passTemp);
66 if ($login_success !== true) {
67 // login attempt failed
68 $_SESSION['loginfailure'] = 1;
69 if (function_exists('sodium_memzero')) {
70 sodium_memzero($_POST["clearPass"]);
71 } else {
72 $_POST["clearPass"] = '';
74 authLoginScreen();
77 // login attempt success
78 $_SESSION['loginfailure'] = null;
79 unset($_SESSION['loginfailure']);
81 // skip the session expiration check below since the entry in session_tracker is not ready yet
82 $skipSessionExpirationCheck = true;
83 } elseif ((isset($_GET['auth'])) && ($_GET['auth'] == "logout")) {
84 // Logout
85 // If session has timed out / been destroyed, logout record for null user/provider will be invalid.
86 if (!empty($_SESSION['authUser']) && !empty($_SESSION['authProvider'])) {
87 if ((isset($_GET['timeout'])) && ($_GET['timeout'] == "1")) {
88 EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "timeout, so force logout");
89 } else {
90 EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "success");
93 authCloseSession();
94 authLoginScreen(true);
95 } else {
96 // Check if session is valid (already logged in user)
97 if (!AuthUtils::authCheckSession()) {
98 // Session is not valid (this should only happen if a user's password is changed via another session while the user is logged in)
99 EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'] ?? '', $_SESSION['authProvider'] ?? '', 0, "authCheckSession() check failed, so force logout");
100 authCloseSession();
101 authLoginScreen(true);
105 // Ensure user has not timed out, if applicable
106 // Have a mechanism to skip the timeout and timeout reset mechanisms if a skip_timeout_reset parameter exists. This
107 // can be used by scripts that continually request information from the server; for example the Messages
108 // and Reminders automated intermittent requests.
109 // Also skipping this all on login since entry in session_tracker is not ready yet
110 if (empty($skipSessionExpirationCheck) && empty($_REQUEST['skip_timeout_reset'])) {
111 if (!SessionTracker::isSessionExpired()) {
112 SessionTracker::updateSessionExpiration();
113 } else {
114 // User has timed out.
115 EventAuditLogger::instance()->newEvent("logout", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "timeout, so force logout");
116 authCloseSession();
117 authLoginScreen(true);
121 require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php");
122 function authCloseSession()
124 // Before destroying the session, save its site_id so that the next
125 // login will default to that same site.
126 global $incoming_site_id;
127 $incoming_site_id = $_SESSION['site_id'];
128 OpenEMR\Common\Session\SessionUtil::coreSessionDestroy();
131 function authLoginScreen($timed_out = false)
133 // See comment in authCloseSession().
134 global $incoming_site_id;
136 <script>
137 // Find the top level window for this instance of OpenEMR, set a flag indicating
138 // session timeout has occurred, and reload the login page into it. This is so
139 // that beforeunload event handlers will not obstruct the process in this case.
140 var w = window;
141 while (w.opener) { // in case we are in a dialog window
142 var wtmp = w;
143 w = w.opener;
144 wtmp.close();
146 <?php if ($timed_out) { ?>
147 w.top.timed_out = true;
148 <?php } ?>
149 w.top.location.href = '<?php echo "{$GLOBALS['login_screen']}?error=1&site=$incoming_site_id"; ?>';
150 </script>
151 <?php
152 exit;