feat: Fixes #6634 CORS content-encoding (#6636)
[openemr.git] / portal / get_patient_info.php
blob87d635c808c64711f0a3c09c4226782990e8a3c1
1 <?php
3 /**
4 * portal/get_patient_info.php
6 * @package OpenEMR
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');
39 exit();
42 // some validation
43 if (!isset($_POST['uname']) || empty($_POST['uname'])) {
44 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
45 header('Location: ' . $landingpage . '&w&c');
46 exit();
49 if (!isset($_POST['pass']) || empty($_POST['pass'])) {
50 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
51 header('Location: ' . $landingpage . '&w&c');
52 exit();
55 // set the language
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;
61 } else {
62 // keep the current session language token
65 // Settings that will override globals.php
66 $ignoreAuth_onsite_portal = true;
69 // Authentication
70 require_once('../interface/globals.php');
72 if (
73 $GLOBALS['enforce_signin_email']
74 && (!isset($_POST['passaddon']) || empty($_POST['passaddon']))
75 ) {
76 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
77 header('Location: ' . $landingpage . '&w&c');
78 exit();
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']]);
111 // validation
112 $validate = substr($auth[COL_POR_ONETIME], 32, 6);
113 if (!empty($validate) && !empty($_POST['token_pin'])) {
114 if ($_SESSION['pin'] !== $_POST['token_pin']) {
115 $auth = false;
116 } elseif ($validate !== $_POST['token_pin']) {
117 $auth = false;
119 } else {
120 $auth = false;
122 unset($_SESSION['forward']);
123 unset($_SESSION['pin']);
124 unset($_POST['token_pin']);
126 } else {
127 // normal login
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');
143 exit();
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');
151 exit();
153 } else {
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.");
164 privStatement(
165 "UPDATE " . TBL_PAT_ACC_ON . " SET " . COL_POR_PWD . " = ? WHERE " . COL_ID . " = ?",
167 $reHash,
168 $auth[COL_ID]
172 } else {
173 $logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid password'), '', '0');
174 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
175 header('Location: ' . $landingpage . '&w&p');
176 exit();
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');
192 exit();
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');
199 exit();
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');
207 exit();
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');
214 exit();
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)
228 privStatement(
229 "UPDATE " . TBL_PAT_ACC_ON . " SET " . COL_POR_LOGINUSER . "=?," . COL_POR_PWD . "=?," . COL_POR_PWD_STAT . "=1 WHERE id=?",
230 array(
231 $_POST['login_uname'],
232 $new_hash,
233 $auth['id']
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);
246 exit();
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
272 // the csrf tokens.
273 CsrfUtils::setupCsrfKey();
275 $logit->portalLog('login', $_SESSION['pid'], ($_SESSION['portal_username'] . ': ' . $_SESSION['ptName'] . ':success'));
276 } else {
277 $logit->portalLog('login', '', ($_POST['uname'] . ':not authorized'), '', '0');
278 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
279 header('Location: ' . $landingpage . '&w');
280 exit();
282 } else { // problem with query
283 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
284 header('Location: ' . $landingpage . '&w');
285 exit();
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]);
296 exit();
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');
303 exit();