Healthcare Demo Application
Galactic Health Corporation
Galactic Health Corporation (GHC) is a sample application set in the universe of "Rick and Morty," that demonstrates all the common application permission models, in a single healthcare application:
A highly detailed explanation and walkthrough of this application is available in this blog. The Git repository for this demo application is available here.
GHC App Key Features:
User Roles: GHC accommodates various user types, each assigned with a corresponding role. These include doctors, patients, caretakers, and administrators. Each user type has distinct responsibilities and access levels tailored to their role.
Patient Management: Patients can access their own health records, medical history, and treatment plans. They can also grant limited access to caregivers or family members as needed.
Doctor-Patient Relationships: Doctors can view and manage the medical records of patients under their care. Patient data is only accessible to authorized medical professionals.
Attribute-Based Access: Access to certain resources within the application is restricted by using attributes like geographic location, patient age, date scoping, or treatment status - making sure they are only accessible under the right conditions.
Feature testing pilot Group: GHC allows the management of user feature testing pilot groups, which allows them to test new application features based on users fitting specific criteria.
Delegated Permissions: Users can delegate limited access to their health information to others, such as caregivers, with specific limitations.
Getting Started
Prerequisites
Node.js Environment - You'll need a working Node.js environment installed on your local machine.
Docker Environment - GHC relies on Docker for running the decision point container locally. Make sure you have Docker installed and configured.
Clerk Account - GHC uses Clerk to authenticate users, allowing them to log into the app.
Permit.io Account - GHC leverages Permit.io for managing user permissions. You'll need a Permit.io account to configure and manage access control.
Setting up the application
- Clone the repository to your local machine.
git clone https://github.com/permitio/Galactic-Health-Corporation.git
- In the root folder, create a file named
.env.local
and copy the content of.env.example
to it.
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="<your clerk publishable key>"
CLERK_SECRET_KEY="<your clerk secret key>"
PERMIT_SDK_KEY="<your permit sdk key>"
PERMIT_PDP_URL=http://localhost:7766
From the Clerk dashboard, go to
API Keys
, choose Next.js example, and copy theNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
andCLERK_SECRET_KEY
values to the.env.local
file.In the Permit dashboard, go to
Connect
, and copy the token variable to thePERMIT_SDK_KEY
value into the.env.local
file.Run
npm install
to install the application dependencies.At this point, we have all the required setup to run the application locally. We have configured the runtime and the keys we need to authenticate and authorize the users.
Configuration Setup
We’ll have to configure the relevant data in Clerk.com and Permit to experiment with authorization and permissions. To do that -
Open the terminal in the repository's root folder and run
npm run config
. This will seed the permissions data into Permit.At this step, have all the relevant resources, actions, and roles configured in Permit.io.
Running the Application
To authorize our users to use the data we configured in Permit, we should run the policy decision point (PDP) locally and run the following docker command to spin up the decision point container:
docker run -it \
-e PDP_API_KEY=<YOUR_PERMIT_API_KEY> \
-p 7766:7000 \
-p 8081:8081 \
permitio/pdp-v2:latest
As the decision point is up and running, open a new terminal window in the repository's root folder and run npm run dev
. This will start the application locally, and you can access it at http://localhost:3000.
Permission Models - RBAC and ReBAC
With the application running, let’s take a look at the entities defined within our app:
Entities
Resources - A resource is the object we want to manage access to. Each resource can have multiple instances.
Actions - The various actions that users can perform on a resource. Each action can be either allowed or denied for each user as defined in the permission model.
Role Derevations - ReBAC allows us to derive authorization policies based on existing application-level relationships. Put in the simplest way, permissions can be derived from the Member Profile to the Medical Record.
Relationships - These define the link between different resources, allowing us to derive permissions from one resource to another.
Resource Roles - Roles that can be assigned to specific resource instances.
The combination of roles, resources, actions, and relationships allows us to define our application’s policy. Let’s go over all of the permissions we want to set up:
Requirements
Users can view their own profile details, health plans, and medical records.
Users can view the profiles of other users they have a relationship with (for example, family members).
Users can delegate permissions to other users to view their health plan and medical records; this delegation is limited to a specific date range.
Users can view particular features in the application based on their pilot groups.
Here’s a list of all of the Resources, Actions, Relationships, etc. we set up in this model:
Resource | Actions | Relationships | Resource Roles | Derived Roles | Description |
---|---|---|---|---|---|
Member | Write, Read | Parent of: Medical Records, Health Plan, Profile | - Owner (read, write) resources. | - Caregiver (read) | A root entity for all member-related |
Profile | Write, Read | Child of Member, | - Owner (read, write) | Member:Caregiver, Member Group:Org Member | A member profile. |
Health Plan | Write, Read | Child of Member | - Owner (read, write) | Member:Caregiver | A member’s health plan. |
Medical Records | Write, Read | Child of Member | - Owner (read, write) | Member:Caregiver | A member’s medical records. |
Member Group | List, Assign | - Admin (list, assign), - Org member (list) | A member group. | ||
New feature pilot group | View | Pilot group member (general role) | A member group that has access to beta features. |
API Endpoints
To demonstrate the permissions in the application, we implemented the following API endpoints:
Endpoint | Description | Roles | Derived Roles |
---|---|---|---|
GET /account/dashboard/profile/{user} | Get the (current) user's details. | Profile:Caregiver | Member:Owner#Profile Member Group:Org Member#Profile |
GET /account/dashboard/health-plan/{user} | Get the (current) user's health plan. | Health Plan:Caregiver | Member:Owner#Health Plan Member:Caregiver#Health Plan |
GET /account/dashboard/medical-records/{user} | Get the (current) user's medical records. | Medical Records:Caregiver | Member:Owner#Medical Records Member:Caregiver#Medical Records |
GET /account/member | Get all the members from all the member groups | Member Group:Org Member | |
GET /account/caregiver | Get all the user's caregivers | Member:Owner | |
POST /account/caregiver | Add a new caregiver to the user | Member:Owner | |
DELETE /account/caregiver | Remove a caregiver from the user | Member:Owner |
Testing the application flow
If you want to run a cloud version of this application, feel free to open Rick and Morty accounts and play with permissions at https://ghc.up.railway.app/ To test the simplest application flow, let's perform the following steps:
- Rick and Morty both need to sign up for GHC accounts using their respective email addresses:
rick@sanchez.app
, andmorty@smith.app
. We’ll also add another account forbird@person.app
.
You can use any email you’d like. To do that, edit the user keys in Permit.io’s dashboard.
Log in to the app as
rick@sanchez.app
, you will notice that Rick’s dashboard only allows him to see his own data. This is because, in GHC, users are granted access to their own information by default.GHC offers a "Delegate Permissions Wizard," a tool that allows users like Rick to share specific healthcare data with others. Use the wizard to share all the data, and assign Morty as a caregiver.
As you can see, Rick can give access only to their member groups members Morty and Bird Person.
Rick can give Morty access limited to a specific date range, ensuring that Morty can view Rick's data only within that timeframe.
With Morty assigned as a caregiver to Rick, let’s log in to Morty’s account. In the "Shared Access" section, you can see that Morty can now access Rick's health plan and medical records as permitted by Rick. This access is derived from the
Member:Caregiver
role. Log into Bird Person's account. You will see that he can only access his own healthcare data and doesn't have any caregiving relationships with other users.
Using this simple usage flow, we demonstrate the following ReBAC permissions:
Rick's Access: Rick, as a member of GHC, can view all of his own healthcare data, as the
Owner
role is assigned to him.Morty's Access: Morty, as Rick's caregiver, can see Rick's health plan and medical records, thanks to the
Member:Caregiver
role assigned to him by Rick.Bird Person's Access: Bird Person can only view his own healthcare data, as he doesn't have any specific relationships with other users.
Feature testing pilot group: In Rick's dashboard, there's a special box only visible to the "Feature testing pilot group". This is an example of Role-Based Access Control (RBAC), where Rick, as a member of the
Feature testing pilot group
role, can access this specific feature. Other users can't see this box.
Now that we have covered the RBAC and ReBAC sections of this GHC’s authorization layer, let’s see how ABAC works in this context.
Permission Models - ABAC
Requirements
The ABAC requirement for our app is to limit the delegation of permissions to a specific date range. For example, Rick can give access to his health plan and medical records to Morty, but only for the next 30 days.
Model
Rick and Morty's relationship determines Morty's instance-level role, so we can't limit the delegation based on the relationship itself. This means we need to add attributes.
To implement the ABAC, we will use a date attribute that can define the boundaries to each role assignment.
For example, if we assign the Member:Caregiver
role to Morty with start_date
set to 2024-01-01
and end_date
set to 2024-01-31
, Morty will be able to view Rick's health plan and medical records only between 2024-01-01
and 2024-01-31
.
The result will be an object that looks like this:
{
"{user}": {
"Member:Caregiver:${instance}": {
"start_date": "2024-01-01",
"end_date": "2024-01-31"
}
}
}
The query will be something similar to this:
if (user[permission].start_date <= today && user[permission].end_date >= today) {
return true;
}
Implementation
To implement the ABAC permissions using Permit:
Configure a Resource Set based on the condition we defined, and configure it within the Permit UI.
Write a custom Rego code that will be combined together with the permissions we already configured in Permit, and will be analyzed by Permit in the PDP.
For the sake of this demo, we will use the second option, as we want to demonstrate the flexibility of the Permit as a solution.
You can find the the generated and custom policy code in the following repository - https://github.com/permitio/ghc-demo-policy
Configure GitOps
The way that Permit.io lets you write your own custom policy code is by using the GitOps feature. This feature allows you to use Git-based features such as pull requests, branches, and merge requests to manage your policy configuration. To configure GitOps, follow this guide.
Configure the Policy
In the relevant branch, replace the content of custom/root.rego
with the content of the scripts/custom.rego
file in the repository.
In the relevant branch, edit the root.rego
file so all the conditions will sit on the same allow rule, like this (remember to remove the second allow rule):
allow {
policies.allow
custom.allow
}
Application Flow
To test the ABAC permissions, run the same caregiver delegation flow we did in the ReBAC and RBAC Permissions section, but this time, limit the delegation to a specific date range.
The permissions should be now limited to the defined date range.
Hosted App
If you'd only like to view the application running, login with one of the following users here and customize the permissions any way you see fit.
User | Password | Groups |
---|---|---|
rick@sanchez.app | Aa123456! | ricks_org, smith_family |
morty@smith.app | Aa123456! | smith_family |
bird@person.app | Aa123456! | ricks_org |
homer@simpson.app | Aa123456! |