This script provides a simple way to perform OAuth 2.0 authentication with Epic's FHIR API. It is intended for developers who want to test or demonstrate the Epic OAuth flow, retrieve access tokens, and view user profile information.
- Demonstrates the OAuth 2.0 Authorization Code flow with Epic's FHIR endpoints.
- Fetches and displays access tokens and user profile information after successful authentication.
- Useful for development, testing, and learning how Epic's OAuth process works.
- Node (v16 or higher recommended)
- An Epic client ID and redirect URI registered with Vendor Services.
- A VPN connection
- Clone this repository.
- Install dependencies:
yarn
Set the following environment variables in .env as needed:
EPIC_BASE_URL
: The base URL for the Epic FHIR server. The default value is the sandbox URL.CLIENT_ID
: Your Epic FHIR client IDCLIENT_SECRET
: (Optional) Your Epic FHIR client secret (leave blank if not required)INITIALIZATION_PATH
: The route that initializes authorization with Epic.SCOPE
: The scope of access you are requesting (defaults toopenid profile fhirUser
).openid
is required, andfhirUser
is recommended to access the user's FHIR endpoint to retrieve their profile.profile
will provide the user'spreferred_username
(typically their t-id). You can add additional scopes as needed, separated by spaces.launch
will automatically be added to the scope if the initialization request comes as an embedded launch request from Epic.HOST
: The host the local server will run on (defaults tolocalhost
)PORT
: The port the local server will run on (defaults to4005
)CALLBACK_PATH
: The path for the callback URL (defaults to/oauth/mychart/callback
). The combinedHOST
,PORT
, andCALLBACK_PATH
will form the full callback URL.LOG_LEVEL
: Defaults toinfo
. You can set it todebug
for more detailed logging. Orerror
to only log errors.FETCH_PROFILE
: (Optional) Defaults totrue
. Set tofalse
if you do not want to fetch the user profile after authentication.SHOW_TOKEN_IN_BROWSER
: (Optional) Defaults tofalse
to avoid accidentally displaying tokens. Set totrue
to display the access token in the browser after authentication. You can set these by copying the.env.example
file and updating as needed.FETCH_ADDITIONAL_RESOURCES
: (Optional) Defaults tofalse
. Set totrue
if you want to make additional requests to Epic using the access token obtained after successful authentication with Epic. Extra requests can be defined in thetest-requests.json
file. Provide the resource name and search params for all additional requests (see below for more info). Individual responses will be timestamped and stored in the responses directory.OPEN_BROWSER
: (Optional) defaults totrue
. This opens a browser window to the script's "home" page after the server starts. It can be helpful to set this tofalse
when testing Embedded launch to avoid opening extra browser tabs.
When FETCH_ADDITIONAL_RESOURCES
is set to true
, the script will attempt to fetch all the resources defined in
test-requests.json
. This file contains a list of resource in the following format:
[
{
"resource": "Patient",
"params": {
"identifier": "<patient FHIR ID>"
}
},
{
"resource": "Appointment",
"params": {
"patient": "<patient FHIR ID>",
"status": "arrived",
"date": "YYYY-MM-DD"
}
}
]
The example above would make one request to
the patient resource endpoint to fetch the patient with the provided
identifier. The response will be stored in responses/<timestamp>-Patient.json
. Then it would fetch Appointments for
the specified patient on the specified day, where the status is "arrived." That response will be stored in
responses/<timestamp>-Appointment.json
.
- Start the script:
yarn run start
- The script will open a browser window. The default home page will have a button that can be pressed to initiate authorization.
- Clicking the 'Authenticate with Epic' button will redirect to the Epic MyChart login form.
- After successful authentication, a success message will be shown in the browser. If configured to do so, the browser
will display the access token and user profile information as well. Note that the user profile is fetched using the
fhirUser
scope, which provides a URL directly to the user's FHIR endpoint. - token.json file will be created in the current directory containing the auth response, including the access token and id token.
- If
FETCH_ADITIONAL_RESOURCES
is true and there are requests defined intest-requests.json
, those requests will be made using the access token received in earlier steps. The responses will be stored in the responses directory.
- Create a new Embedded Launch Simulation in Vendor Services. This is found under "Find Resources" > "Embedded
Simulator." Click on "SMART on FHIR" to create a new simulation. Choose the app you want to test, and set the
"Launch URL" to the combined
http://HOST:PORT/INITIALIZATION_PATH
you configured in your.env
file. Add any tokens you want to collect as part of the authentication flow. Select Launch Type "Launch Embedded in This Window" (or whichever option you wish to test). See example below: - Click the "Save" button to create the simulation.
- (Optional) You may wish to set the environment variable
OPEN_BROWSER
tofalse
to avoid opening an extra browser tab when starting the script. - Start the script:
yarn run start
- Click "Run Test" in your simulation or click the test name in the list of simulations on the left of the screen to start the simulation. You may be asked to look up a patient before running the simulation.
- Starting the simulation will force a redirect to the initialization path you configured in your
.env
file. This will start the OAuth flow. Since the user has already authenticated, they will not be asked to do so again. - After successful authentication with the launch token, a success message will be shown in the browser. If configured
to do so, the browser will display the access token and user profile information as well. Note that the user profile
is fetched using the
fhirUser
scope, which provides a URL directly to the user's FHIR endpoint. - A token.json file will be created in the current directory containing the auth response, including the access token and id token.
- If
FETCH_ADITIONAL_RESOURCES
is true and there are requests defined intest-requests.json
, those requests will be made using the access token received in earlier steps. The responses will be stored in the responses directory.
An application that wishes to authenticate with Epic needs to listen to at least 2 endpoints. The endpoints are:
- The URL that will initialize the OAuth flow, which will redirect the user to Epic's authorization server. This can be the same for both standalone and embedded launch, or can be split into two separate endpoints if there are significant differences in how the application plans to handle each auth case.
- The callback URL that Epic will redirect to after successful authentication.
In the case of standalone launch, typically, a button or link in your application will redirect the user to the OAuth initialization URL, which will start the OAuth flow. After the user logs in and authorizes the app, they will be redirected back to the callback URL with an authorization code. The application can then exchange this code for an access token and ID token by making a request to the Epic token endpoint. The access token can then be used to make authenticated requests to the FHIR API.
In the case of embedded launch, an endpoint is needed to capture the request Epic sends to launch the application in an embedded context. This endpoint will initialize the OAuth flow. The user will be directed to Epic to authorize the app, then redirected back to the callback URL with an authorization code. The application can then exchange this code for an access token and ID token by making a request to the Epic token endpoint. The access token can then be used to make authenticated requests to the FHIR API.
The main difference between standalone and embedded launch is that there are two additional parameters required
for the initial authorization request (aud
and launch
). When Epic sends a request for embedded launch, it will
also send launch
and iss
parameters. launch
will be included as launch
in the initial authorization request and
iss
will be included as aud
.
- This script is for development and demonstration purposes only. Do not use it in production environments.
- Never share your client secrets or access tokens.
- Never commit the token.json file that is generated after authentication, as it contains sensitive information.
If something isn't working as expected, check the following:
- VPN connection
EPIC_BASE_URL
points to the correct URL. If testing embedded launch, this likely needs to be the vendor services URL.- Set
LOG_LEVEL
todebug
to see more information ub the logs