Hello Team, I’m using latest OpenEMR 6.1.0 Docker version. I’m trying to register a client for bulk export. It breaks when I’m requesting access (bearer) token using client assertion I generated with command-runner. The response json is nothing special:
“error”: “invalid_client”,
“error_description”: “Client authentication failed”,
“message”: “Client authentication failed”
But the logs (full logs attached) are more interesting, especially this part:
Definitely looks like a timestamp issue. I’d check to make sure your server / client time are set up correctly. I believe we give a ±300 second jitter allowance for date differences. Also when you generated the client did you use the correct issuer? That would be the other thing I would check.
@adunsulag Thanks for your answer.
As for client creation - I created it using public key generated here https://bulk-data.smarthealthit.org/ (purely for testing, following Lecture 2 - FHIR Bulk Data in OpenEMR). May it also be the case?
Hi @adunsulag , so I haven’t moved forward on this question. It is 3-4s between client and server so I guess it’s ok?
Maybe me using key generator here https://bulk-data.smarthealthit.org/ can be the case?
This is the code that is used for the client credentials JWT validation
$configuration->setValidationConstraints(
// we only allow 1 minute drift (note the 'T' specifier here, super important as we want to do time
// we had a bug here where P1M was a 1 month drift which is BAD.
new ValidAt(new SystemClock(new \DateTimeZone(\date_default_timezone_get())), new \DateInterval('PT1M')),
new SignedWith(new RsaSha384Signer(), $jsonWebKeySet),
new IssuedBy($client->getIdentifier()),
new PermittedFor($this->authTokenUrl), // allowed audience
new UniqueID($jwtRepository)
);
You are failing the SignedWith constraint which code is here:
public function assert(Token $token): void
{
if (! $token instanceof UnencryptedToken) {
throw new ConstraintViolation('You should pass a plain token');
}
if ($token->headers()->get('alg') !== $this->signer->algorithmId()) {
throw new ConstraintViolation('Token signer mismatch');
}
if (! $this->signer->verify($token->signature()->hash(), $token->payload(), $this->key)) {
throw new ConstraintViolation('Token signature mismatch');
}
}
When you use the command line runner are you replacing the openemr-rsa-384-private.key and the openemr-rsa384-public.pem key? You can see that those are the keys that are used to generate the assertion in the command line runner. If you are not replacing those key/pem files then the assertion you are generating as a client will not match the JWKS stored when you generate your assertion through the command line runner.
There are no instructions whatsoever on changing default certs.
So looks like I have two options here:
Use default public openemr-rsa384-public.pem cert in JWKS to register a client and therefore when I’ll be generating assertion by command-runner they will match?
Hi @VBregman in the video demonstration I did uses the default certs that are inside OpenEMR. If you don’t want to mess with converting your JWKS to pems and are ok with just going with the test pem files in the system you can register a bulk client using the JWKS that is in OpenEMR. To print out the test JWKS just pass the -k parameter to the command runner like so:
Your Option #2 is what you need to do when you are ready to use this in a production environment. If you use the default JWKS then your data can be stolen as the private key is publicly accessible in the OpenEMR codebase.
I probably will need to do a follow up video on how to convert JWKs to pem format. There are plenty of tools to do that for you. I would recommend only using a command line tool or something that runs on your public computer. You don’t want to paste your key information into another online tool as you can’t be sure for data security reasons that someone didn’t keep a copy of that key in their http logs or database.
@adunsulag Thanks, for now I’ll just try the first option.
But if you can add any info to that topic (videos, manuals, github pages) that would be awesome as I’m practically learning FHIR integrations with that stuff.
Again, thanks for your support!
@adunsulag Now it’s getting more interesting I believe it’s a first step for possible sql injection.
Here is the response I’m getting when trying to perform a root or patient bulk export
I’ll attach full log as well.
Actually the response has a little bit more info then logs
<h2>
<font color='red'>Query Error</font>
</h2>
<p>
<font color='red'>ERROR:</font> query failed: SELECT id,
uuid,
users.title as title,
fname,
lname,
mname,
federaltaxid,
federaldrugid,
upin,
facility_id,
facility,
npi,
email,
active,
specialty,
billname,
url,
assistant,
organization,
valedictory,
street,
streetb,
city,
state,
zip,
phone,
fax,
phonew1,
phonecell,
users.notes,
state_license_number,
abook.title as abook_title,
FROM users
LEFT JOIN list_options as abook ON abook.option_id = users.abook_type
</p>
<p>Error: <font color='red'>You have an error in your SQL syntax; check the manual that corresponds to your MariaDB
server version for the right syntax to use near 'FROM users
LEFT JOIN list_options as abook ON abook.option_i...' at line 33</font>
</p>
<br />/var/www/localhost/htdocs/openemr/src/Services/UserService.php at 196:sqlStatement<br />/var/www/localhost/htdocs/openemr/src/Services/FHIR/FhirPersonService.php at 263:getAll(Array,)<br />/var/www/localhost/htdocs/openemr/src/Services/FHIR/FhirServiceBase.php at 208:searchForOpenEMRRecords(Array)<br />/var/www/localhost/htdocs/openemr/src/Services/FHIR/Traits/FhirBulkExportDomainResourceTrait.php at 69:getAll(Array)<br />/var/www/localhost/htdocs/openemr/src/RestControllers/FHIR/FhirExportRestController.php at 359:export
It has yet to be merged into the 6.1 release. It will go in automatically into our upcoming 7.0 release or you can cherry-pick the commit if you want. Another option is to run your tests against master until we release the next 6.1 patch.