Getting 401 Unzuthorized on /fhir/Patient API on POST request but GET request works

Situation
Describe your problem here
I followed this doc:

to register a private client API on OpenEMR using the client_credentials grant_type. I was able to get the access token by hitting POST request on oauth2/default/token with body

{
“grant_type”: “client_credentials”
“client_assertion_type”: “urn:ietf:params:oauth:client-assertion-type:jwt-bearer”
“scopes”: “openid fhirUser online_access offline_access launch launch/patient api:fhir patient/AllergyIntolerance.read patient/Appointment.read patient/Binary.read patient/CarePlan.read patient/CareTeam.read patient/Condition.read patient/Coverage.read patient/Device.read patient/DiagnosticReport.read patient/DocumentReference.read patient/DocumentReference.$docref patient/Encounter.read patient/Goal.read patient/Immunization.read patient/Location.read patient/MedicationRequest.read patient/Medication.read patient/Observation.read patient/Organization.read patient/Patient.read patient/Person.read patient/Practitioner.read patient/Procedure.read patient/Provenance.read system/AllergyIntolerance.read system/Binary.read system/CarePlan.read system/CareTeam.read system/Condition.read system/Coverage.read system/Device.read system/DiagnosticReport.read system/DocumentReference.read system/DocumentReference.$docref system/Encounter.read system/Goal.read system/Group.read system/Group.$export system/Immunization.read system/Location.read system/MedicationRequest.read system/Medication.read system/Observation.read system/Organization.read system/Patient.read system/Patient.$export system/Person.read system/Practitioner.read system/PractitionerRole.read system/Procedure.read system/Provenance.read system/.$bulkdata-status system/.$export user/AllergyIntolerance.read user/Binary.read user/CarePlan.read user/CareTeam.read user/Condition.read user/Coverage.read user/Device.read user/DiagnosticReport.read user/DocumentReference.read user/DocumentReference.$docref user/Encounter.read user/Goal.read user/Immunization.read user/Location.read user/MedicationRequest.read user/Medication.read user/Observation.read user/Organization.read user/Organization.write user/Patient.read user/Patient.write user/Person.read user/Practitioner.read user/Practitioner.write user/PractitionerRole.read user/Procedure.read user/Provenance.read api:oemr user/allergy.read user/allergy.write user/appointment.read user/appointment.write user/dental_issue.read user/dental_issue.write user/document.read user/document.write user/drug.read user/encounter.read user/encounter.write user/facility.read user/facility.write user/immunization.read user/insurance.read user/insurance.write user/insurance_company.read user/insurance_company.write user/insurance_type.read user/list.read user/medical_problem.read user/medical_problem.write user/medication.read user/medication.write user/message.write user/patient.read user/patient.write user/practitioner.read user/practitioner.write user/prescription.read user/procedure.read user/soap_note.read user/soap_note.write user/surgery.read user/surgery.write user/transaction.read user/transaction.write user/vital.read user/vital.write api:port patient/encounter.read patient/patient.read patient/appointment.read”
“client_assertion”: “jwt encoded token”
}

When I use the token as bearre auth on GET endpoint /fhir/Patient I get 200 status codes and all patients list. But when I follow the above steps (generate new bearer auth from jwt) and use the new token on same endpoint but POST request, I am getting 401 unauthorized.

I change the jti value in jwt payload every time to generate unique jwt encoded token.

OpenEMR Version
I’m using OpenEMR version 7.0.0

Browser:
I’m using: POSTMAN

Operating System
I’m using: OpenEMR from AWS lightsail

Logs
Did you check the logs? Yes
Was there anything pertinent in them? No just warning:

[Thu Mar 23 17:46:06.190919 2023] [mpm_prefork:notice] [pid 156] AH00163: Apache/2.4.55 (Unix) OpenSSL/1.1.1s configured -- resuming normal operations
[Thu Mar 23 17:46:06.191075 2023] [core:notice] [pid 156] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
[Thu Mar 23 18:03:02.926508 2023] [mpm_prefork:notice] [pid 156] AH00163: Apache/2.4.55 (Unix) OpenSSL/1.1.1s configured -- resuming normal operations
[Thu Mar 23 18:03:02.926805 2023] [core:notice] [pid 156] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
[Thu Mar 23 18:07:12.757978 2023] [mpm_prefork:notice] [pid 156] AH00163: Apache/2.4.55 (Unix) OpenSSL/1.1.1s configured -- resuming normal operations
[Thu Mar 23 18:07:12.758135 2023] [core:notice] [pid 156] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
[Thu Mar 23 18:16:00.591978 2023] [mpm_prefork:notice] [pid 156] AH00163: Apache/2.4.55 (Unix) OpenSSL/1.1.1s configured -- resuming normal operations
[Thu Mar 23 18:16:00.592155 2023] [core:notice] [pid 156] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'

Please paste them here (surround with three backticks (```) for readability.

You can also turn on User Debugging under Administration->Globals->Logging User Debugging Options=>All

1 Like

I don’t see any system/Patient.write scopes in your scopes request. Your registered client needs the scope and your client_credentials grant request needs the scope as well if you want to be able to do a write to the endpoint.

1 Like

Hi Stephen , thanks you so much for replying in such short notice. I tried registering another api client by adding the system/Patient.write scope as you suggested, but I am getting 400 Bad Request with response:

{
    "error": "invalid_scope",
    "error_description": "The requested scope is invalid, unknown, or malformed",
    "hint": "Check the `system/Patient.write` scope",
    "message": "The requested scope is invalid, unknown, or malformed"
}

Do you know, what I may have done wrong ?

1 Like

My apologies Saurav, it should be system/patient.write as only the standard api (not FHIR) has support for writing to the patient endpoint. The FHIR endpoint is the one that uses the capitalized Patient and that is currently not supported right now.

Thanks Stepthen, I decided to go with Password grant, I was able to use the user/patient.write (I think) scope for FHIR post request.

401 Unauthorized Error When Fetching FHIR Patient Data from OpenEMR

Hello everyone,

I’m working on integrating a Flutter web application with OpenEMR but am encountering a 401 Unauthorized error when trying to fetch FHIR patient data.

What I’ve Done So Far:

  1. App Registration: The application is registered.
  2. Token Retrieval: I successfully obtained the access_token and patientId by making a POST request to the /oauth2/default/token endpoint with code, redirect_uri, client_id, and grant_type.
  3. API Request: Using the retrieved access_token, I attempted to fetch patient data from:

/apis/default/fhir/Patient/${patientId}

However, this request returns a 401 Unauthorized error with no response body.

Additional Information:

  • FHIR API & System Scopes Enabled: I have enabled OpenEMR Standard FHIR REST API and System Scopes via Admin → Config → Connector .
  • Access Token Usage: The token is being sent correctly in the request as a Bearer token in the Authorization header.
  • Token Verification: I have verified the token’s claims using jwt.io to ensure it contains the expected permissions.
  • Scopes Used:

[ “openid”, “fhirUser”, “online_access”, “offline_access”, “launch”, “launch/patient”, “api:oemr”, “api:fhir”, “api:port”, “system/Patient.$export”, “system/Group.$export”, “system/.$bulkdata-status", "system/.$export”, “system/AllergyIntolerance.read”, “system/Appointment.read”, “system/Binary.read”, “system/CarePlan.read”, “system/CareTeam.read”, “system/Condition.read”, “system/Coverage.read”, “system/Device.read”, “system/DiagnosticReport.read”, “system/DocumentReference.$docref”, “system/DocumentReference.read”, “system/Encounter.read”, “system/Goal.read”, “system/Group.read”, “system/Immunization.read”, “system/Location.read”, “system/Medication.read”, “system/MedicationRequest.read”, “system/Observation.read”, “system/Organization.read”, “system/Person.read”, “system/Practitioner.read”, “system/PractitionerRole.read”, “system/Procedure.read”, “system/Provenance.read”, “system/ValueSet.read”, “system/Patient.read”, “site:default” ]

I would appreciate any insights on what might be causing this issue. Have I missed any configuration steps, or is there a specific scope required for accessing patient data?

Is this a POST or a GET request? your posting under a community forum message around POSTS not working.

Have you turned on the system debug logs in Config → Logging → System Error Logging Options? You can then look at the php error log and see much more details on why you are being denied.

Okay, I enabled the system debug logs option and navigated to Admin → System → Logs.
In the Name of Event field, I selected ‘api’.
There, I found the API success comment:
“Token successfully used for client and user .”

However, the API call is still returning a 401 Unauthorized error with no response body.

php debug error logs are not stored in the database. They are stored in the webserver error logs. For example on the standard docker apache linux install it would be in the

/var/log/apache2/error.log

What grant are you using? Client Credentials Grant?

On a flutter app I would expect you to be using either the Authorization Code grant or the Password Grant.

system/Patient.read is only allowed using Client Credentials Grant. You more likely want to use user/Patient.read or patient/Patient.read for your app. The user context is for grabbing multiple patients’ data from a clinician/provider perspective, the patient permission is for grabbing a single patient’s data (locked for the entire request of the token) whether you are a provider or a patient.