How to configure OpenEMR 6.x with Keycloak (or any OAuth2 server)

I think the docs might be missing the Authorize section example based on what was posted here: V6 Authorization and API changes afoot

  1. You do a registration request to: https://localhost/oauth2/default/registration
  2. Next step is to authorize to: https://localhost/openemrv6/oauth2/default/authorize

The API docs says to use this url: https://localhost/oauth2/default and no example.

So I registered the admin account as an API client that worked fine.
I then proceed to authorize the client via a GET/POST to: https://localhost:443/oauth2/default/authorize using these params:

{
    "client_id": "UIy5NV9K53pYus35IbXGjVuYzQOUXIDQzmF3YocU7Zs",
    "response_type": "code",
    "client_id": "LnjqojEEjFYe5j2Jp9m9UnmuxOnMg4VodEJj3yE8_OA",
    "state": "a85b870548dd8880ddb7c3192439f468fe63396f",
    "scope": "openid api:oemr api:fhir api:port api:pofh",
    "redirect_uri": "https://localhost:443"
}

And this is the result:

<br />
<b>Notice</b>:  Key file "file:///var/www/localhost/htdocs/openemr/sites/default/documents/certificates/oaprivate.key" permissions are not correct, recommend changing to 600 or 660 instead of 700 in <b>/var/www/localhost/htdocs/openemr/vendor/league/oauth2-server/src/CryptKey.php</b> on line <b>63</b><br />
{
    "error": "unsupported_grant_type",
    "error_description": "The authorization grant type is not supported by the authorization server.",
    "hint": "Check that all required parameters have been provided",
    "message": "The authorization grant type is not supported by the authorization server."
}

Changing permissions on that file does nothing, this is where I’m stuck at the moment so I’m not sure if it’s something I’m doing wrong or missing info in the API docs.

I’ve changed response_type to every response type supported based on: https://localhost/oauth2/default/.well-known/openid-configuration and get the same error.

Using the endpoint in the API docs https://localhost:443/oauth2/default doesn’t return anything but a 200 ok with an empty body.

I’m just looking to be able to use the API with the user accounts created in OEMR like it was prior to V6 since I’m just using OEMR as the backend of my app.

Thanks.

A bit of progress so far here’s what I’ve done:

  • Enabled REST API in Admin > Connectors
  • Added Site Address: https://localhost:443
  • Enabled Client SSL under Admin > Security (not sure if necessary)
  • Enabled OAuth2 Password Grant to: On for Both Roles
  • Registered my admin account as an API Client via postman on: https://localhost:443/oauth2/default/registration
    with the following:
{
    "application_type": "private",
   "redirect_uris": ["https://localhost:443"],
    "initiate_login_uri": "https://localhost:443",
   "client_name": "admin-account",
   "token_endpoint_auth_method": "client_secret_post",
   "username": "admin",
   "password": "pass",
   "scope": "openid api:oemr api:fhir api:port api:pofh"
}
  • Enabled Client under Administration > System > API Clients
  • Proceeded to refresh/authorize the client on: https://localhost:443/oauth2/default/token with the following urlencoded data:
client_id:xtk0UuP446AneUfZs5nchUn_iCQX-yV92Sh_GI8aDMQ
grant_type:password
user_role:users
scope:openid api:oemr api:fhir api:port api:pofh
username:admin
password:pass
  • Used the access token from the previous request as the Bearer token for my next request to: https://localhost:443/apis/default/api/facility which then returns:
{
    "error": "access_denied",
    "error_description": "The resource owner or authorization server denied the request.",
    "hint": "Error while decoding from JSON",
    "message": "The resource owner or authorization server denied the request."
}

That’s as far as I’ve gotten.

Hi,

Regarding the Authorization Code Grant, that is done via a oauth2 standard flow. That’s why the instructions are minimal (ie. use a oauth2 client, which I detailed an example of using one in the 4 steps several posts above) since there is a standardized process/flow for this (can learn about via google).

Regarding your password grant, just need to include the needed scopes in your scope on the client registration and password grant request. For example, the user/facility.read scope will get your call to https://localhost:443/apis/default/api/facility to work.

I was under the assumption that using api:oemr could grant access to all scopes under it the same for api:fhir etc. is that not the case?

I can register fine with all scopes but when I try to refresh the token with all scopes I get an invalid scope error.

<br />
<b>Notice</b>:  Key file "file:///var/www/localhost/htdocs/openemr/sites/default/documents/certificates/oaprivate.key" permissions are not correct, recommend changing to 600 or 660 instead of 700 in <b>/var/www/localhost/htdocs/openemr/vendor/league/oauth2-server/src/CryptKey.php</b> on line <b>63</b><br />
{
    "error": "invalid_scope",
    "error_description": "The requested scope is invalid, unknown, or malformed",
    "hint": "Check the `user/Coverage.read` scope",
    "message": "The requested scope is invalid, unknown, or malformed"
}

I’ve tried escaping / and periods but no matter what I always get this error when trying to refresh the token.

Thanks for your help and patience :pray:

Hi,

From experience, the scope of the resource must be clearly specified at the time of registering and authorize. In your example, add user/Coverage.read to your scope.

I hope this will help you,

Regards,

Yeah I removed it from the scope and it worked maybe it was no included in the register phase :thinking: thanks.

It definitely was in the registration scope, weird anyways progress now to see if I can get this working, thanks again.

Hi there,

I can surely help with what all you need.

Reach me at nicole(at)cisinlabs(com)

With regards,
Nciole

Hi @benmarte ,
The user/Coverage.read scope is only in master (ie. dev version) since it was just recently added. If you are using 6.0.0, then it will fail if try to use that scope since it does not exist there. If doing shotgun approach on scopes (ie. including them all) while getting them to work and testing them out, then would use the listing of scopes in the API_README.md file included in the instance you are running from to avoid trying to use scopes that do not yet exists there.

1 Like

Ok, so I decided to write down a blog post for any other poor soul trying to use the new Open EMR Auth flows, specifically the Password Grant flow.

Check it out here and let me know what can be improved or is wrong so I can fix it, thank you everyone for your help :pray:

https://benmarte.com/blog/openemr-api-v6/

1 Like

@benmarte ,

Very cool stuff! Only 2 things I noted:

  1. https is required for oauth/api to work (when set the Site Address in globals)
  2. The Activating your API Client is not needed in this setting (it will work without doing this; this is only pertinent for use of SMART app use)
1 Like