OpenEMR 7.0.3 OAuth2 JWT – Getting 400 invalid_client Even After Proper Setup

oauth2, jwt, api, authentication, openemr-7.0.3

We’re trying to integrate OpenEMR (v7.0.3 on Google Cloud) using OAuth2 client_credentials flow with private_key_jwt authentication. All steps were followed exactly, but we still receive a 400 Bad Request with "invalid_client" error when exchanging the JWT for a token.

1. Created JWKS and Hosted It Publicly

  • Generated RSA key pair
  • Hosted JWKS (https: //mkjwk. org/) with kid, n, e, and alg=RS256

2. Configured Public Key in OpenEMR (Google Cloud VM)

  • Added the PEM public key to the trusted keys

3. Registered a Client in OpenEMR Admin Interface

  • Confidential client with private_key_jwt
  • Set JWKS URL and public key
  • Enabled client

4. Generated JWT Assertion (Programmatically)

  • Header included correct kid and alg
  • Payload had iss, sub, aud, iat, exp
  • Signed with matching RSA private key
  • JWT validated correctly on jwt.io and compiled in https://token.dev/

5. Made Token Request via Postman & Self-Hosted Hoppscotch

  • POST to /oauth2/default/token
  • Body:
grant_type=client_credentials  
client_id=<our-client-id>  
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer  
client_assertion=<generated JWT>  

6. Result:
Always getting:

{
  "error": "invalid_client",
  "error_description": "Client authentication failed"
}


(Postman)

:white_check_mark: Checked:

  • kid matches
  • JWT signed correctly
  • iat/exp fresh and accurate
  • JWKS URL is accessible
  • aud is the token endpoint
  • Public key same across JWKS and OpenEMR trusted keys

:question: Need Help With:

  • Is there a known bug in v7.0.3 with private_key_jwt?
  • Does OpenEMR require anything non-standard in JWTs?
  • Any logs we can check or extra debug steps?
  • Are there specific aud or formatting issues that could trigger this?

We’re stuck at this final step and would greatly appreciate any guidance.

Thanks in advance!

Check out this helpful topic
Use FHIR in open EMR V7 - OpenEMR Development - OpenEMR Community

We’ve carefully followed those steps multiple times, but the issue persists. Previously, we encountered a 500 error, but after applying your suggestions, it has changed to 400/401 errors. We’d greatly appreciate it if you could kindly share the steps once again for our reference.

Allow me to give you a brief overview — we’ve deployed both versions 7.0.3 and 0.2 of OpenEMR on Google Cloud, along with Hoppscotch, to enable API integration entirely within the cloud environment. We’ve followed your steps closely to reach this stage, but we still need your support to move forward. Your assistance would be greatly appreciated

Did you actually enable the client from the OpenEMR gui page?

Turn on the API debug logs and you’ll get more information. Most likely your registration URL doesn’t match your token if you’ve enabled the client from the admin GUI interface.

What does your registration request look like?