MDM Web UI Admin Setup Tutorial - Smile CDR Documentation

Setting Up the MDM Web UI for Data Stewards

This tutorial walks a system administrator through every step needed before a data steward can open the MDM Web UI dashboard and start reviewing patient identity decisions. The MDM Web UI supports the Probabilistic MDM strategy, in which borderline matches are resolved by a human reviewer. For a shorter reference-style overview of the same setup, see the MDM UI Tutorial; this tutorial is a detailed step-by-step walkthrough. By the end, the following will be in place:

MDM is a Premium Solution and requires a separately purchased license. Contact sales@smiledigitalhealth.com if you need to enable it.

Prerequisites


Step 1: Configure the FHIR Storage Module

The MDM engine runs asynchronously on top of Smile CDR's subscription infrastructure. Two settings on the FHIR Storage module must be enabled before the MDM module can operate.

Open the FHIR Storage module

In the Web Admin Console, go to Configuration → Module Config and open the persistence module.

Enable MDM and message subscriptions

Use the On this page sidebar to navigate to each section below, then set the values shown:

Section in sidebar Setting Value
FHIR MDM Server MDM Mode Enabled Enabled
FHIR Subscription Persistence Message Subscription Enabled Enabled
FHIR Configuration Seed Base Validation Resources Enabled

The Seed Base Validation Resources setting loads StructureDefinition and related FHIR conformance resources on startup. The MDM UI frontend requires these to be present.

Save and restart the persistence module.


Step 2: Configure the MDM Module with Match Rules

The MDM module processes incoming resources and produces the links that data stewards review. If the match rules produce only MATCH and no POSSIBLE_MATCH outcomes, the data steward queue will always be empty. This step configures rules that route borderline cases to the dashboard.

Create the MDM module (if it does not already exist)

Go to Configuration → Module Config → Add Module and select MDM.

Set the consumer thread count

Set Consumer Thread Count to 2 (or 1 for a low-volume environment).

Set the Subscription dependency

Under Module Dependencies, select the Subscription Matching module.

Enter the MDM Rule Definition Script

Paste the following JSON into the MDM Rule Definition Script field. It matches automatically when both name and birth date agree, and routes cases where only the family name and birth date agree to the data steward queue as Possible Matches.

{
  "version": "v1",
  "mdmTypes": ["Patient"],
  "candidateSearchParams": [\
    {\
      "resourceType": "Patient",\
      "searchParams": ["birthdate"]\
    },\
    {\
      "resourceType": "Patient",\
      "searchParams": ["identifier"]\
    }\
  ],
  "candidateFilterSearchParams": [],
  "matchFields": [\
    {\
      "name": "family-name",\
      "resourceType": "Patient",\
      "resourcePath": "name.family",\
      "similarity": {\
        "algorithm": "JARO_WINKLER",\
        "matchThreshold": 0.88\
      }\
    },\
    {\
      "name": "given-name",\
      "resourceType": "Patient",\
      "resourcePath": "name.given",\
      "matcher": {\
        "algorithm": "DOUBLE_METAPHONE"\
      }\
    },\
    {\
      "name": "birthdate",\
      "resourceType": "Patient",\
      "resourcePath": "birthDate",\
      "matcher": {\
        "algorithm": "DATE"\
      }\
    }\
  ],
  "matchResultMap": {
    "family-name,given-name,birthdate": "MATCH",
    "family-name,birthdate": "POSSIBLE_MATCH"
  }
}

Copy

The matchResultMap is what creates work for data stewards. The MATCH entry handles the confident cases automatically. The POSSIBLE_MATCH entry catches cases where the family name and birth date agree but the given name comparison fails — for example, when the given name is absent on one record or differs significantly. Each POSSIBLE_MATCH link becomes a task in the dashboard.

Enter a survivorship script

Survivorship rules control which field values are promoted to the Golden Record when multiple source records are linked, and which values are used when two Golden Records are merged. Without a survivorship script, the Golden Record is left empty after a merge.

Paste the following into the MDM Survivorship Script field:

function mdmApplySurvivorshipRules(targetRec, goldenRec, transactionContext) {
    var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext);
    helper.replaceAll();
}

function mdmApplySurvivorshipRulesOnMergeGoldenResources(fromGoldenRec, toGoldenRec, transactionContext) {
    var helper = new MdmHelper(Fhir.getContext(), fromGoldenRec, toGoldenRec, transactionContext);
    helper.mergeAll();
}

Copy

The first function runs whenever a source record is linked to a Golden Record: it copies all demographic fields from the source record to the Golden Record. The second function runs when two Golden Records are merged by a data steward: it combines all fields from both records into the surviving one.

Save the MDM module and start it.

Verify that the module status icon turns green. If it stays red or yellow, check Logs → Module Logs for errors. The most common cause is a missing Subscription Matching dependency.


Step 3: Configure the SMART Outbound Security Module

The MDM UI authenticates users through SMART/OIDC. A SMART Outbound Security module issues tokens, and a callback script within it assigns each user the appropriate MDM UI role at login time.

Create the module (if it does not already exist)

Go to Configuration → Module Config → Add Module and select SMART Outbound Security. Use the module ID smart_auth.

Set the listener and issuer

Setting Value
OpenID Connect (OIDC) → Issuer URL http://localhost:9200/smartauth
HTTP Listener → Listener Port 9200
HTTP Listener → Context Path /smartauth
HTTP Listener → Respect Forward Headers Disabled
HTTP Listener → HTTPS Forwarding Assumed Disabled

Reverse proxy deployments only: If the MDM UI is exposed through an HTTPS-terminating reverse proxy (nginx, Apache, a load balancer, etc.), enable both Respect Forward Headers and HTTPS Forwarding Assumed on this module. With those flags off, the server generates http:// URLs for all OIDC endpoints, which is correct for a direct connection. With them on, the server treats every connection as HTTPS and generates https:// URLs regardless of the actual listener protocol — connecting directly to the server without a proxy in front will then produce an ERR_SSL_PROTOCOL_ERROR in the browser.

Disable enforced scope restrictions

Under SMART Authorization, disable Enforce Approved Scopes. This lets the MDM UI receive all the permissions it needs without requiring each scope to be pre-approved on the client.

Enable CORS

Under Cross-Origin Resource Sharing, enable CORS and set the allowed origin to the URL where the MDM UI will be served (for example, http://localhost:8080). Do not use * here because the OIDC logout flow requires an exact origin match.

Add the Post-Authorization Script

In the SMART Callback Script section, paste the following into the Post Authorization Script Text field. This script assigns the Data Steward or Admin role to a user based on their username at the time a token is issued.

function onTokenGenerating(theUserSession, theAuthorizationRequestDetails) {
    var userName = theUserSession.username;

if (userName === 'DATA_STEWARD' || userName === 'ADMIN') {
        theUserSession.addAuthority('FHIR_WRITE_ALL_OF_TYPE', 'AuditEvent');
        theUserSession.addAuthority('FHIR_WRITE_ALL_OF_TYPE', 'Task');
        theUserSession.addAuthority('ACCESS_ADMIN_JSON');
        theUserSession.addAuthority('UPDATE_USER');
        theUserSession.addAuthority('VIEW_USERS');
    }

if (userName === 'DATA_STEWARD') {
        theUserSession.addAuthority('ROLE_MDMUI_DATASTEWARD_FHIR');
        theUserSession.addAuthority('VIEW_MODULE_CONFIG_FOR_MODULE', 'Master/mdm');
        theAuthorizationRequestDetails.addAccessTokenClaim('user_role', 'data_steward');

} else if (userName === 'ADMIN') {
        theUserSession.addAuthority('FHIR_EXTENDED_OPERATION_ON_SERVER', '$mdm-evaluate');
        theUserSession.addAuthority('ROLE_MDMUI_ADMIN_FHIR');
        theUserSession.addAuthority('MODULE_ADMIN_FOR_MODULE', 'Master/mdm');
        theUserSession.addAuthority('VIEW_BATCH_JOBS');
        theAuthorizationRequestDetails.addAccessTokenClaim('user_role', 'admin');
    }
}

Copy

This script uses hard-coded usernames for simplicity. In a production environment, replace the username checks with lookups against your organization's directory service (LDAP or an external OIDC provider) so that role assignment is managed centrally rather than in this script. See the Roles & Permissions reference for the full list of MDM UI authorities.

The ROLE_MDMUI_DATASTEWARD_FHIR permission bundle includes the individual MDM operation authorities needed to query links, update links, merge Golden Records, and mark pairs as not-duplicate. The ROLE_MDMUI_ADMIN_FHIR bundle includes all of those plus the ability to run $mdm-clear and $mdm-submit.

Save and restart the smart_auth module.


Step 4: Configure the JSON Admin API Endpoint

The MDM UI uses the JSON Admin API to fetch module configuration and metadata.

Create the module (if it does not already exist)

Go to Configuration → Module Config → Add Module and select JSON Admin API.

Configure it

Setting Value
HTTP Listener → Listener Port 9000
HTTP Listener → Context Path /json-admin
Auth: OpenID Connect → OpenIdConnect Security Enabled
Cross-Origin Resource Sharing → CORS Enabled Enabled
Cross-Origin Resource Sharing → CORS Allowed Origins http://localhost:8080 (or * for testing only)

Set module dependencies

In the Module Dependencies section, set the OpenID Connect Authentication dropdown to smart_auth.

Save and restart the JSON Admin API module.


Step 5: Configure the FHIR REST Endpoint

The MDM UI reads and writes FHIR resources — Patient records, AuditEvents, Tasks — through a dedicated FHIR REST endpoint that is protected by OIDC.

Create the module

Go to Configuration → Module Config → Add Module and select FHIR REST Endpoint (All FHIR Versions). Use the module ID fhir_endpoint.

Configure it

Setting Value
HTTP Listener → Listener Port 8000
HTTP Listener → Context Path /fhir-request
FHIR REST Endpoint → Fixed Value for Endpoint Base URL http://localhost:8000/fhir-request
Auth: OpenID Connect → OpenID Connect Security Yes
Cross-Origin Resource Sharing → CORS Enabled Enabled
CORS Allowed Origins http://localhost:8080 (or * for testing only)

Set module dependencies

Under Module Dependencies, add:

Dependency type Select
FHIR Storage Module persistence (FHIR Storage R4 RDBMS)
OpenID Connect Authentication smart_auth (SMART Outbound Security)

Save and start the fhir_endpoint module.


Step 6: Create the OIDC Client

The MDM UI is a browser application. An OIDC client record authorizes it to request tokens from the SMART auth module.

Open the OIDC client manager

In the Web Admin Console, go to Users & Authorization → OpenID Connect Clients and click Add Client.

Fill in the client details

Field Value
Client ID MDM_UI
Client Name MDM UI
Authorized Grant Types Authorization Code, Refresh Token, JWT Bearer Token
Authorized Redirect URLs http://localhost:8080/mdm-ui/
Scopes cdr_all_user_authorities``launch/patient``launch/practitioner``offline_access``openid``profile

The Authorized Redirect URL must match the URL of the MDM UI module exactly, including the trailing slash and any context path. If you change the MDM UI's port or context path in the next step, update this URL to match.

Click Create Client.


Step 7: Add the MDM UI Module

Create the module

Go to Configuration → Module Config → Add Module and select MDM UI.

Configure it

Setting Value
HTTP Listener → Listener Port 8080
HTTP Listener → Context Path /mdm-ui/
Organization Identifier A system and value identifying your organization (for example, http://example.org/org-id|my-org). A new Organization resource is created automatically if one does not exist with this identifier.
JSON Admin URL http://localhost:9000/json-admin
OIDC Client ID MDM_UI
Issuer URL http://localhost:9200/smartauth
Redirect URL http://localhost:8080/mdm-ui/
Logout URL http://localhost:9200/smartauth/logout?cb=none&revoke=token&revoke=token_refresh

Set module dependencies

Under Module Dependencies, select all available dependencies. This typically includes the FHIR REST endpoint, the JSON Admin API, and the SMART Outbound Security module.

Save and start the MDM UI module.

The MDM UI is now accessible at http://localhost:8080/mdm-ui/.


Step 8: Create Data Steward User Accounts

Users logging into the MDM UI must have accounts in the local user store. The post-authorization script from Step 3 grants the correct MDM UI permissions at login time based on the username — so the account names must match the values checked in that script.

Open the User Manager

Go to Users & Authorization → User Management and click Add User.

Create the Data Steward account

Field Value
Username DATA_STEWARD
Password Choose a strong password and share it securely with the user.
Permissions No explicit permissions are required here — the post-authorization script adds them when the user logs into the MDM UI.

Click Save.

Create the Admin account (optional)

Repeat the above with username ADMIN if you also want an MDM UI administrator account that can run match evaluations and batch jobs from within the UI.

The hard-coded usernames DATA_STEWARD and ADMIN match the values in the post-authorization script written in Step 3. If you use different usernames, update the script accordingly. For production deployments with many stewards, replace the per-username checks with group membership lookups so you do not need to modify the script each time you add or remove a user.


Step 9: Verify the Setup

Check module status

In the Web Admin Console, go to Configuration → Module Config and confirm that all seven modules show a green status icon:

Log in as a data steward

Open http://localhost:8080/mdm-ui/ in a browser. You should be redirected to the SMART auth login page. Log in with the DATA_STEWARD credentials created in Step 8.

After login you should see the MDM dashboard with Possible Matches and Possible Duplicates sections. Both counts will be zero on a fresh installation because no patient data has been loaded yet.

Confirm the data steward's view

Verify that the user can see the review queues but does not see the configuration or administration panels — those are visible only to users with the ADMIN role.

Send a test patient pair

To verify the full pipeline end to end, create two Patient records whose names and birth dates trigger a POSSIBLE_MATCH under the rules in Step 2.

Patient 1:

{
  "resourceType": "Patient",
  "name": [{ "family": "Smith", "given": ["Jonathan"] }],
  "birthDate": "1985-03-15"
}

Copy

Patient 2 (given name absent — should produce a Possible Match, not an automatic Match):

{
  "resourceType": "Patient",
  "name": [{ "family": "Smith" }],
  "birthDate": "1985-03-15"
}

Copy

Wait a few seconds for asynchronous MDM processing, then reload the MDM UI dashboard. The Possible Matches count should increment to 1. The data steward can now open that task and review it.


What You've Accomplished

In this tutorial you:

  1. Enabled MDM mode and message subscriptions on the FHIR Storage module.
  2. Configured the MDM module with match rules that produce both automatic MATCH links and POSSIBLE_MATCH tasks for data steward review, and a survivorship script for Golden Record merges.
  3. Set up a SMART Outbound Security module with a post-authorization script that assigns the ROLE_MDMUI_DATASTEWARD_FHIR and ROLE_MDMUI_ADMIN_FHIR permission bundles at login.
  4. Configured a JSON Admin API endpoint and a FHIR REST endpoint as backend services for the MDM UI.
  5. Created an OIDC client that authorizes the MDM UI application.
  6. Launched the MDM UI module and confirmed it is reachable in a browser.
  7. Created local user accounts for data stewards.

Next Steps

MDM Advanced Rule Authoring Tutorial

MDM Web UI Admin Setup Tutorial

Tutorials

Introduction Integration Testing Tutorial Custom Operations Tutorial HL7 v2.x Ingestion Tutorial Federated OAuth2/OIDC Tutorial MDM Tutorial MDM UI Tutorial MDM First Golden Resource Tutorial MDM Advanced Rule Authoring Tutorial MDM Web UI Admin Setup Tutorial CDA Import Tutorial CDA Export Tutorial CDA Export - Custom Narrative Generation Tutorial CDA Import JSON example CDA Export Template JSON example Consent Tutorial CMS-0057-F IG Setup Tutorial

CDA Import Tutorial