4 * portal/get_patient_info.php
7 * @link https://www.open-emr.org
8 * @author Cassian LUP <cassi.lup@gmail.com>
9 * @author Jerry Padgett <sjpadgett@gmail.com>
10 * @author Brady Miller <brady.g.miller@gmail.com>
11 * @copyright Copyright (c) 2011 Cassian LUP <cassi.lup@gmail.com>
12 * @copyright Copyright (c) 2016-2017 Jerry Padgett <sjpadgett@gmail.com>
13 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 // starting the PHP session
18 // Will start the (patient) portal OpenEMR session/cookie.
19 require_once(dirname(__FILE__
) . "/../src/Common/Session/SessionUtil.php");
20 OpenEMR\Common\Session\SessionUtil
::portalSessionStart();
22 // regenerating the session id to avoid session fixation attacks
23 session_regenerate_id(true);
26 // landing page definition -- where to go if something goes wrong
27 $landingpage = "index.php?site=" . urlencode($_SESSION['site_id'] ??
($_GET['site'] ??
'default'));
30 if (!empty($_REQUEST['redirect'])) {
31 // let's add the redirect back in case there are any errors or other problems.
32 $landingpage .= "&redirect=" . urlencode($_REQUEST['redirect']);
35 // checking whether the request comes from index.php
36 if (!isset($_SESSION['itsme'])) {
37 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
38 header('Location: ' . $landingpage . '&w');
43 if (!isset($_POST['uname']) ||
empty($_POST['uname'])) {
44 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
45 header('Location: ' . $landingpage . '&w&c');
49 if (!isset($_POST['pass']) ||
empty($_POST['pass'])) {
50 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
51 header('Location: ' . $landingpage . '&w&c');
56 if (!empty($_POST['languageChoice'])) {
57 $_SESSION['language_choice'] = (int)$_POST['languageChoice'];
58 } elseif (empty($_SESSION['language_choice'])) {
59 // just in case both are empty, then use english
60 $_SESSION['language_choice'] = 1;
62 // keep the current session language token
65 // Settings that will override globals.php
66 $ignoreAuth_onsite_portal = true;
70 require_once('../interface/globals.php');
73 $GLOBALS['enforce_signin_email']
74 && (!isset($_POST['passaddon']) ||
empty($_POST['passaddon']))
76 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
77 header('Location: ' . $landingpage . '&w&c');
81 require_once(dirname(__FILE__
) . "/lib/appsql.class.php");
82 require_once("$srcdir/user.inc.php");
84 use OpenEMR\Common\Auth\AuthHash
;
85 use OpenEMR\Common\Csrf\CsrfUtils
;
87 $logit = new ApplicationTable();
88 $password_update = isset($_SESSION['password_update']) ?
$_SESSION['password_update'] : 0;
89 unset($_SESSION['password_update']);
91 $authorizedPortal = false; // flag
92 DEFINE("TBL_PAT_ACC_ON", "patient_access_onsite");
93 DEFINE("COL_ID", "id");
94 DEFINE("COL_PID", "pid");
95 DEFINE("COL_POR_PWD", "portal_pwd");
96 DEFINE("COL_POR_USER", "portal_username");
97 DEFINE("COL_POR_LOGINUSER", "portal_login_username");
98 DEFINE("COL_POR_PWD_STAT", "portal_pwd_status");
99 DEFINE("COL_POR_ONETIME", "portal_onetime");
101 // 2 is flag for one time credential reset else 1 = normal reset.
102 // one time reset requires a PIN where normal uses a new temp pass sent to user.
103 if ($password_update === 2 && !empty($_SESSION['pin'])) {
104 $sql = "SELECT " . implode(",", array(
105 COL_ID
, COL_PID
, COL_POR_PWD
, COL_POR_USER
, COL_POR_LOGINUSER
, COL_POR_PWD_STAT
, COL_POR_ONETIME
)) . " FROM " . TBL_PAT_ACC_ON
.
106 " WHERE BINARY " . COL_POR_ONETIME
. "= ?";
107 $auth = privQuery($sql, array($_SESSION['forward']));
108 if ($auth !== false) {
109 // remove the token from database
110 privStatement("UPDATE " . TBL_PAT_ACC_ON
. " SET " . COL_POR_ONETIME
. "=NULL WHERE BINARY " . COL_POR_ONETIME
. " = ?", [$auth['portal_onetime']]);
112 $validate = substr($auth[COL_POR_ONETIME
], 32, 6);
113 if (!empty($validate) && !empty($_POST['token_pin'])) {
114 if ($_SESSION['pin'] !== $_POST['token_pin']) {
116 } elseif ($validate !== $_POST['token_pin']) {
122 unset($_SESSION['forward']);
123 unset($_SESSION['pin']);
124 unset($_POST['token_pin']);
128 $sql = "SELECT " . implode(",", array(
129 COL_ID
, COL_PID
, COL_POR_PWD
, COL_POR_USER
, COL_POR_LOGINUSER
, COL_POR_PWD_STAT
)) . " FROM " . TBL_PAT_ACC_ON
.
130 " WHERE " . COL_POR_LOGINUSER
. "= ?";
131 if ($password_update === 1) {
132 $sql = "SELECT " . implode(",", array(
133 COL_ID
, COL_PID
, COL_POR_PWD
, COL_POR_USER
, COL_POR_LOGINUSER
, COL_POR_PWD_STAT
)) . " FROM " . TBL_PAT_ACC_ON
.
134 " WHERE " . COL_POR_USER
. "= ?";
137 $auth = privQuery($sql, array($_POST['uname']));
139 if ($auth === false) {
140 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid username'), '', '0');
141 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
142 header('Location: ' . $landingpage . '&w&u');
146 if ($password_update === 2) {
147 if ($_POST['pass'] != $auth[COL_POR_PWD
]) {
148 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid password'), '', '0');
149 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
150 header('Location: ' . $landingpage . '&w&p');
154 if (AuthHash
::passwordVerify($_POST['pass'], $auth[COL_POR_PWD
])) {
155 $authHashPortal = new AuthHash('auth');
156 if ($authHashPortal->passwordNeedsRehash($auth[COL_POR_PWD
])) {
157 // If so, create a new hash, and replace the old one (this will ensure always using most modern hashing)
158 $reHash = $authHashPortal->passwordHash($_POST['pass']);
159 if (empty($reHash)) {
160 // Something is seriously wrong
161 error_log('OpenEMR Error : OpenEMR is not working because unable to create a hash.');
162 die("OpenEMR Error : OpenEMR is not working because unable to create a hash.");
165 "UPDATE " . TBL_PAT_ACC_ON
. " SET " . COL_POR_PWD
. " = ? WHERE " . COL_ID
. " = ?",
173 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid password'), '', '0');
174 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
175 header('Location: ' . $landingpage . '&w&p');
182 $_SESSION['portal_username'] = $auth[COL_POR_USER
];
183 $_SESSION['portal_login_username'] = $auth[COL_POR_LOGINUSER
];
185 $sql = "SELECT * FROM `patient_data` WHERE `pid` = ?";
187 if ($userData = sqlQuery($sql, array($auth['pid']))) { // if query gets executed
188 if (empty($userData)) {
189 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':not active patient'), '', '0');
190 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
191 header('Location: ' . $landingpage . '&w');
195 if ($userData['email'] != ($_POST['passaddon'] ??
'') && $GLOBALS['enforce_signin_email']) {
196 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid email'), '', '0');
197 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
198 header('Location: ' . $landingpage . '&w');
202 if ($userData['allow_patient_portal'] != "YES") {
203 // Patient has not authorized portal, so escape
204 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':allow portal turned off'), '', '0');
205 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
206 header('Location: ' . $landingpage . '&w');
210 if ($auth['pid'] != $userData['pid']) {
211 // Not sure if this is even possible, but should escape if this happens
212 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
213 header('Location: ' . $landingpage . '&w');
217 if ($password_update) {
218 $code_new = $_POST['pass_new'];
219 $code_new_confirm = $_POST['pass_new_confirm'];
220 if (!(empty($_POST['pass_new'])) && !(empty($_POST['pass_new_confirm'])) && ($code_new == $code_new_confirm)) {
221 $new_hash = (new AuthHash('auth'))->passwordHash($code_new);
222 if (empty($new_hash)) {
223 // Something is seriously wrong
224 error_log('OpenEMR Error : OpenEMR is not working because unable to create a hash.');
225 die("OpenEMR Error : OpenEMR is not working because unable to create a hash.");
227 // Update the password and continue (patient is authorized)
229 "UPDATE " . TBL_PAT_ACC_ON
. " SET " . COL_POR_LOGINUSER
. "=?," . COL_POR_PWD
. "=?," . COL_POR_PWD_STAT
. "=1 WHERE id=?",
231 $_POST['login_uname'],
236 $authorizedPortal = true;
237 $logit->portalLog('password update', $auth['pid'], ($_POST['login_uname'] . ': ' . $_SESSION['ptName'] . ':success'));
241 if ($auth['portal_pwd_status'] == 0) {
242 if (!$authorizedPortal) {
243 // Need to enter a new password in the index.php script
244 $_SESSION['password_update'] = 1;
245 header('Location: ' . $landingpage);
250 if ($auth['portal_pwd_status'] == 1) {
251 // continue (patient is authorized)
252 $authorizedPortal = true;
255 if ($authorizedPortal) {
256 // patient is authorized (prepare the session variables)
257 unset($_SESSION['password_update']); // just being safe
258 unset($_SESSION['itsme']); // just being safe
259 $_SESSION['pid'] = $auth['pid'];
260 $_SESSION['patient_portal_onsite_two'] = 1;
262 $tmp = getUserIDInfo($userData['providerID']);
263 $_SESSION['providerName'] = ($tmp['fname'] ??
'') . ' ' . ($tmp['lname'] ??
'');
264 $_SESSION['providerUName'] = $tmp['username'] ??
null;
265 $_SESSION['sessionUser'] = '-patient-'; // $_POST['uname'];
266 $_SESSION['providerId'] = $userData['providerID'] ?
$userData['providerID'] : 'undefined';
267 $_SESSION['ptName'] = $userData['fname'] . ' ' . $userData['lname'];
268 // never set authUserID though authUser is used for ACL!
269 $_SESSION['authUser'] = 'portal-user';
270 // Set up the csrf private_key (for the paient portal)
271 // Note this key always remains private and never leaves server session. It is used to create
273 CsrfUtils
::setupCsrfKey();
275 $logit->portalLog('login', $_SESSION['pid'], ($_SESSION['portal_username'] . ': ' . $_SESSION['ptName'] . ':success'));
277 $logit->portalLog('login', '', ($_POST['uname'] . ':not authorized'), '', '0');
278 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
279 header('Location: ' . $landingpage . '&w');
282 } else { // problem with query
283 OpenEMR\Common\Session\SessionUtil
::portalSessionCookieDestroy();
284 header('Location: ' . $landingpage . '&w');
288 // now that we are authorized, we need to check for the redirect, sanitize it (or eliminate it if we can't), and then redirect
290 if (!empty($_REQUEST['redirect'])) {
291 // for now we are only going to allow redirects to locations in the module directories, we can open this up more
292 // in future requests once we consider the threat vectors
293 $safeRedirect = \OpenEMR\Core\ModulesApplication
::filterSafeLocalModuleFiles([$_REQUEST['redirect']]);
294 if (!empty($safeRedirect)) {
295 header('Location: ' . $safeRedirect[0]);
299 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
300 header("Cache-Control: no-cache");
301 header("Pragma: no-cache");
302 header('Location: ./home.php');