External Identity Providers | Medplum

IDP Routing Strategies

When using external identity providers, you need to decide how to route users to the correct IDP. Medplum supports two primary strategies:

1. App-based Routing (Client ID)

In this model, the Identity Provider is determined by the application the user is logging into. This is configured on the ClientApplication resource.

2. Domain-based Routing (Email Domain)

In this model, the Identity Provider is determined by the user's email address. This is configured using Domain Configuration.

Auth flow

When an end user authenticates with your client-side web application, we will use the following authentication flow:

Example repo

Medplum provides a minimal example application which demonstrates using Auth0 as an external identity provider. The example is approximately 100 lines of TypeScript code, and can be used as a starting point for any standard OAuth2/OpenID identity provider.

https://github.com/medplum/medplum-client-external-idp-demo

Setup

Setup your external authentication provider (Auth0, AWS Cognito, Okta, etc). Use " https://api.medplum.com/auth/external" as the "redirect URI" (also known as the "callback URL" in some systems).

Also make sure that your provider accepts the profile OIDC scope.

Note the following details:

Setup your Medplum account:

Self-hosted server-scoped identity providers

The IdentityProvider resource is server-scoped. On self-hosted deployments, creating or editing server-scoped identity provider configuration requires super admin context. Project administrators can configure identity provider settings on project ClientApplication resources, but they cannot create server-scoped IdentityProvider resources unless they are operating as super admin.

Start the flow

The MedplumClient TypeScript class provides a signInWithExternalAuth convenience method:

// The login button handler
// The user can click this button to initiate the OAuth flow

$('login').addEventListener('click', () =>
  medplum.signInWithExternalAuth(EXTERNAL_AUTHORIZE_URL, EXTERNAL_CLIENT_ID, EXTERNAL_REDIRECT_URI, {
    projectId: MEDPLUM_PROJECT_ID,
    clientId: MEDPLUM_CLIENT_ID,
    redirectUri: WEB_APP_REDIRECT_URI,
  })
);

Handle the code

When the external identity provider flow redirects back to your web application, it will include a code query parameter. This code can be exchanged for a Medplum access token.

The MedplumClient TypeScript class provides a processCode convenience method:

// The code check
// If the current URL includes a "code" query string param, then we can exchange it for a token

const code = new URLSearchParams(window.location.search).get('code');

if (code) {
  // Process the code
  // On success, remove the query string parameters
  medplum
    .processCode(code)
    .then(() => (window.location.href = window.location.href.split('?')[0]))
    .catch(console.error);
}

After the code is processed, the Medplum access token will be stored in the browser's local storage. The MedplumClient will automatically use the access token for all subsequent API calls.

FAQ

AWS Cognito

medplum.signInWithExternalAuth(
  EXTERNAL_AUTHORIZE_URL,
  EXTERNAL_CLIENT_ID,
  EXTERNAL_REDIRECT_URI,
  {
    projectId: MEDPLUM_PROJECT_ID,
    clientId: MEDPLUM_CLIENT_ID,
    redirectUri: WEB_APP_REDIRECT_URI,
  },
  false,
);