HIE of One Authorization Server is a simple User Managed Access (UMA) Server that incorporates OAuth2 and OpenID Connect protocols to facilitate the ability of an individual to control and authorize access to his or her health information to clients such as physicians, hospitals, caregivers, and third-party applications.
Run the following commands to install:
sudo curl -o install.sh https://raw.githubusercontent.com/shihjay2/hieofone-as/master/install.sh
sudo chmod +x install.sh
sudo bash install.sh
- PHP
- MySQL
- Apache
- CURL
- OAuth2 OpenID Connect compliant server
- OAuth2 OpenID Connect relying party for Google and Twitter
- User Managed Access compliant authentication server
- Patient has registered a domain name where the HIE of One Authorization Server is installed (ie domain.xyz)
- Client software (such as an EHR with a patient portal) has the capability to make HTTPS calls (such as CURL) and is able to process JSON responses.
Patient submits his or her HIE of One email address ([email protected]) to the client (like a physician), where domain.xyz is the same domain name as where the HIE of One authorization server is installed. This can be done, for example, through a EHR patient portal that has a text input that allows processing of the patient's HIE of One email address. Alternatively, the provider would enter this email address in the EHR directly when the patient's chart is open. A negative result results in a 404 error response.
Client submits email address to the following address per Webfinger protocol to confirm validity of the account and email address. Here is an example call (line breaks below are just for display convenience):
GET /.well-known/webfinger?
resource=acct:[email protected]
&rel=http://openid.net/specs/connect/1.0/issuer
Client takes the JSON return (specifically the href subkey
under links
) and when appending .well-known/uma2-configuration
to the URL, like this: https://domain.xyz/.well-known/uma2-configuration, client will see in JSON format all the valid UMA endpoints where client makes calls to initiate a token request, start authorization, request a permission ticket, and make requesting party claims.
Client makes a call to the dynamic_client_endpoint
to register itself. Client will need to store the client_id
and client_secret
(such as in a database) going forward. It is important for the client to consider which redirect URIs to use as one of them will need to handle the claims_redirect_uri
parameter listed here. Being a client only requires that you declare a scope of uma_authorization
. Here is an example call (line breaks below are just for display convenience):
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: server.example.com
{
"redirect_uris":[
"https://client.example.org/callback",
"https://client.example.org/callback2"]
"client_name":"My Example Client",
"logo_uri":"https://client.example.org/logo.png",
"claims_redirect_uris":[
"https://client.example.org/callback3"
],
"scope": "openid email offline_access uma_authorization"
}
As a client, make a call to the authorization_endpoint
. Make sure as a client that it declares these 2 scopes - uma_authorization (which defines you as a client requesting access to resources) and offline_access (so that you can obtain a refresh token for future calls without needing the patient to repeat consent online.) Here is an example call (line breaks below are just for display convenience):
GET /authorize?
response_type=code
&scope=openid%20profile%20email%20uma_authorization%20offline_access
&client_id=some_client_id
&client_secret=some_client_secret
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: server.example.com
The patient is then directed to the login page of HIE of One Authorization Server where he/she verifies his/her identity. If successful, the patient will then see a consent screen that verifies that this client will have access to resources registered on his/her authorization server. If the patient accepts, the client is authorized and the client is now registered to the authorization server. From now on, the client is now the registered client. It is the responsibility of the client to correctly assign the registered client information (client_id, client_secret, refresh_token, authorization server URI) to the correct identity (patient, requesting party).
Becoming a resource server is exactly the same steps as above except for the following changes:
- Resource server software has resources that pertain to the patient
Resource server makes a call to the dynamic_client_endpoint
to register itself. Resource server will need to store the client_id
and client_secret
(such as in a database) going forward. It is important for the resource server to consider which redirect URIs to use as one of them will need to handle the claims_redirect_uri
parameter listed here. Being a resource server requires that you declare a scope of uma_protection
. Being a resource server also allows it to be client, so a scope declaration can include both uma_authorization
and uma_protection
. Here is an example call (line breaks below are just for display convenience):
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: server.example.com
{
"redirect_uris":[
"https://rs.example.org/callback",
"https://rs.example.org/callback2"]
"client_name":"My Example Resource Server",
"logo_uri":"https://rs.example.org/logo.png",
"claims_redirect_uri":[
"https://rs.example.org/callback3"
],
"scope": "openid email offline_access uma_authorization uma_protection"
}
As a resource server, make a call to the authorization_endpoint
. Make sure as a resource server that it declares these 2 scopes - uma_protection (which defines you as a resource server requesting access to serve resources) and offline_access (so that you can obtain a refresh token for future calls without needing the patient to repeat consent online.) Here is an example call (line breaks below are just for display convenience):
GET /authorize?
response_type=code
&scope=openid%20profile%20email%20uma_protection%20offline_access
&client_id=some_client_id
&client_secret=some_client_secret
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Frs.example.org%2Fcb HTTP/1.1
Host: server.example.com
The patient is then directed to the login page of HIE of One Authorization Server where he/she verifies his/her identity. If successful, the patient will then see a consent screen that verifies that this resource server will have access to his data and will be able to serve resources and register them on his/her authorization server. If the patient accepts, the client is authorized and the client is now registered to the authorization server. From now on, the client is now the registered resource server. It is the responsibility of the resource server to correctly assign the registered client information (client_id, client_secret, refresh_token, authorization server URI) to the correct identity (patient).
- The authorization server has a associated resource server (such as a patient centric EHR that supports the FHIR API like NOSH ChartingSystem)
- The registered client knows the FHIR resource endpoints such as medication list, problem list, allergy list, encounters, immunizations, binaries) to access/edit these resources.
- The patient has created policies via the policy API that define which requesting party (identified by his/her e-mail address) has permissions to access/edit his/her resources.
The client makes an initial call to the resource endpoint.
GET /fhir/Patient/1 HTTP/1.1
Host: rs.example.com
The resource server sends a response back with the URI of the authorization server (as_uri
parameter in the WWW-Authenticate
portion of the return header) and a permission ticket (ticket
in JSON return).
The client makes a call to the token_endpoint
of the authorizaion server as such (line breaks below are just for display convenience):
POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=some_client_id
&client_secret=some_client_secret
&scope=uma_authorization
The authorization API token is access_token
in the JSON return which will be used in the rpt_endpoint
.
Step 3a: Client makes a call to the authorization server with the permission ticket given by the resource server
The client makes a call to the requesting_party_claims_endpoint
of the authorization server and presents the permission ticket as such (line breaks below are just for display convenience):
GET /rqp_claims?client_id=some_client_id
&state=abc<br>&ticket=016f84e8-f9b9-11e0-bd6f-0021cc6004de
&claims_redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fredirect_claims HTTP/1.1
Host: as.example.com
The requesting party will then be directed following this call to the authorization server which will determine the identity of the requesting party where a login screen will be presented. 4 choices of login will exist (going in order of most likely to least)
- Login with MDNosh Gateway (a federated physician single-sign-on solution).
- Login with Google
- Login with Twitter
- Login with the authorization server (if the physician is a registered user for the authorization server, which is the least likely scenario)
After login, the authorization server checks the login identity email address to the claim associated with the resource policy. If there is a match, the requesting party is redirected by the client supplied redirect URL (claims_redirect_uri
in the above example) with the added authorization_state
parameter as such (line breaks below are just for display convenience)
GET /redirect_claims?&state=abc
&authorization_state=claims_submitted HTTP/1.1
Host: client.example.com
Client makes a call to the rpt_endpoint
of the authorization server supplying the authorization API token and the permission ticket as such (line breaks below are just for display convenience):
POST /authz_request HTTP/1.1
Host: as.example.com
Authorization: Bearer some_authorization_API_token
...
{
"ticket": "some_permission_ticket"
}
The requesting party token is rpt
in the JSON return.
The client redirects back to the resource server with the requesting party token attached to the original FHIR resource endpoint.
GET /fhir/Patient/1 HTTP/1.1
Host: rs.example.com
Authorization: Bearer some_requesting party_token
The resource server makes calls to the authorization server to validate the requesting party token through an introspection call. If validated, the resource server then presents the requested FHIR resource to the requesting party.
If you discover a security vulnerability within HIE of One Authorization Server, please send an e-mail to Michael Chen at shihjay2 at gmail.com. All security vulnerabilities will be promptly addressed.
The HIE of One Authorization Server is open-sourced software licensed under the GNU AGPLv3 license.