4 * Authorization Server Member
7 * @link http://www.open-emr.org
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @copyright Copyright (c) 2020 Jerry Padgett <sjpadgett@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 namespace OpenEMR\Common\Auth\OpenIDConnect\Entities
;
15 use League\OAuth2\Server\Entities\UserEntityInterface
;
16 use League\OAuth2\Server\Exception\OAuthServerException
;
17 use OpenEMR\Common\Auth\AuthUtils
;
18 use OpenEMR\Common\Auth\MfaUtils
;
19 use OpenEMR\Common\Auth\UuidUserAccount
;
20 use OpenEMR\Common\Logging\SystemLogger
;
21 use OpenEMR\Common\Uuid\UuidRegistry
;
22 use OpenEMR\Services\PractitionerService
;
23 use OpenIDConnectServer\Entities\ClaimSetInterface
;
25 class UserEntity
implements ClaimSetInterface
, UserEntityInterface
30 public function getClaims()
32 $claimsType = (!empty($_REQUEST['grant_type']) && ($_REQUEST['grant_type'] === 'client_credentials')) ?
'client' : 'oidc';
33 if ($claimsType === 'oidc') {
34 $uuidToUser = new UuidUserAccount($this->identifier
);
36 $userRole = $uuidToUser->getUserRole();
37 $fhirUserResource = "Person";
38 if ($userRole == UuidUserAccount
::USER_ROLE_USERS
) {
39 // need to find out if its a practitioner or not
40 $practitionerService = new PractitionerService();
41 // ONC validation does not accept Person as a valid test case so we have to differentiate practitioners
42 // from the more generic Person resource.
43 if ($practitionerService->isValidPractitionerUuid($this->identifier
)) {
44 $fhirUserResource = "Practitioner";
46 } else if ($userRole == UuidUserAccount
::USER_ROLE_PATIENT
) {
47 $fhirUserResource = "Patient";
49 (new SystemLogger())->error("user role not supported for fhirUser claim ", ['role' => $userRole]);
51 $fhirUser = $GLOBALS['site_addr_oath'] . $GLOBALS['web_root'] . '/apis/' . $_SESSION['site_id'] . "/fhir/" . $fhirUserResource . "/" . $this->identifier
;
53 (new SystemLogger())->debug("UserEntity->getClaims() fhirUser claim is ", ['role' => $userRole, 'fhirUser' => $fhirUser]);
55 $user = $uuidToUser->getUserAccount();
60 'name' => $user['fullname'],
61 'family_name' => $user['lastname'],
62 'given_name' => $user['firstname'],
63 'middle_name' => $user['middlename'],
65 'preferred_username' => $user['username'] ??
'',
74 'email' => $user['email'],
75 'email_verified' => true,
76 'phone_number' => $user['phone'],
77 'phone_number_verified' => true,
78 'address' => $user['street'] . ' ' . $user['city'] . ' ' . $user['state'],
79 'zip' => $user['zip'],
80 'fhirUser' => $fhirUser,
86 if ($claimsType === 'client') {
88 'fhirUser' => $fhirUser,
94 if (!empty($_SESSION['nonce'])) {
95 $claims['nonce'] = $_SESSION['nonce'];
97 if ($_SESSION['site_id']) {
98 $claims['site'] = $_SESSION['site_id'];
104 public function getIdentifier()
106 return $this->identifier
;
109 public function setIdentifier($id): void
111 $this->identifier
= $id;
114 protected function getAccountByPassword($userrole, $username, $password, $email = ''): bool
116 if (($userrole == UuidUserAccount
::USER_ROLE_USERS
) && (($GLOBALS['oauth_password_grant'] == 1) ||
($GLOBALS['oauth_password_grant'] == 3))) {
117 $auth = new AuthUtils('api');
118 if ($auth->confirmPassword($username, $password)) {
119 $id = $auth->getUserId();
120 UuidRegistry
::createMissingUuidsForTables(['users']);
121 $uuid = sqlQueryNoLog("SELECT `uuid` FROM `users` WHERE `id` = ?", [$id])['uuid'];
123 error_log("OpenEMR Error: unable to map uuid for user when creating oauth password grant token");
126 $this->setIdentifier(UuidRegistry
::uuidToString($uuid));
128 // If an mfa_token was provided, then will force TOTP MFA (U2F impossible to support via password grant)
129 // (note that this is only forced if mfa_token is provided)
130 $mfa = new MfaUtils($id);
131 $mfaToken = $mfa->tokenFromRequest(MfaUtils
::TOTP
);
132 if (!is_null($mfaToken)) {
133 if (!$mfa->isMfaRequired() ||
!in_array(MfaUtils
::TOTP
, $mfa->getType())) {
134 // A mfa_token was provided, however the user is not configured for totp
135 throw new OAuthServerException(
136 'MFA not supported.',
142 //Check the validity of the totp token, if applicable
143 if (!empty($mfaToken) && $mfa->check($mfaToken, MfaUtils
::TOTP
)) {
146 throw new OAuthServerException(
147 $mfa->errorMessage(),
158 } elseif (($userrole == UuidUserAccount
::USER_ROLE_PATIENT
) && (($GLOBALS['oauth_password_grant'] == 2) ||
($GLOBALS['oauth_password_grant'] == 3))) {
159 $auth = new AuthUtils('portal-api');
160 if ($auth->confirmPassword($username, $password, $email)) {
161 $id = $auth->getPatientId();
162 UuidRegistry
::createMissingUuidsForTables(['patient_data']);
163 $uuid = sqlQueryNoLog("SELECT `uuid` FROM `patient_data` WHERE `pid` = ?", [$id])['uuid'];
165 error_log("OpenEMR Error: unable to map uuid for patient when creating oauth password grant token");
168 $this->setIdentifier(UuidRegistry
::uuidToString($uuid));