External Account Connections

Participants can securely establish connections to providers from within your app, using MyDataHelpsKit to facilitate the connection process for providers selected by the participant or identified by your app’s configuration. The MyDataHelps platform and SDK handle all of the authentication, authorization, and data transfer details, allowing your app to focus on the user experience.

Overview

External account connection is a multi-step process that requires your project to be configured correctly in MyDataHelps Designer, and your participant-facing app to be correctly configured to handle the web-based authorization flow.

Your app presents the authorization flow in a modal Safari view. As the participant completes the authorization process, the SDK handles finalizing the account connection within the MyDataHelps backend.

There are four steps to the provider connection process:

  1. Select an ExternalAccountProvider for the participant to connect to. Depending on your use case, your app may present a search interface or configure a specific known provider.
  2. Prepare an external account authorization session using ParticipantSession.connectExternalAccount.
  3. Present the participant-mediated authorization flow to the user in a Safari view.
  4. Handle incoming redirect URLs from the authorization flow to dismiss and complete the connection.

Project Configuration

In MyDataHelps Designer, your project must have EHR data collection enabled in order to use this feature.

Presenting an External Account Authorization Flow

Begin by determining which external account provider the participant should connect to. Use the SDK to build a provider search interface, or configure a specific known provider ID.

Once an ExternalAccountProvider is selected or a provider ID is configured, prepare for the authorization process by calling ParticipantSession.connectExternalAccount. This grants access to a secure OAuth connection for the specified external account provider, where the participant can enter their provider credentials and authorize MyDataHelps to retrieve data from the account.

The call to connectExternalAccount returns an ExternalAccountAuthorization, which includes an authorizationURL value. Your app presents an SFSafariViewController to the user using the authorizationURL to present and complete the provider authorization flow.

Redirect URL Configuration

The connectExternalAccount function requires a redirect URL that your app must be configured to handle. This finalRedirectURL is used at the end of the authorization flow to complete the connection and notify your app that the connection is completed and the Safari view can be dismissed.

There are two options for configuring finalRedirectURL:

  • Universal Link, e.g. https://my.app/linkprovidercompletion. The Universal Link domain and path must be configured in your app’s entitlements file and the apple-app-site-association file hosted at the my.app domain.
  • Custom scheme, e.g. myapp://linkprovidercompletion. Your app’s Info.plist file must register the scheme myapp in the URL Types list.

Your app can use a specific path in this URL in order to differentiate it from other URLs your app may support.

Completing the Connection

When the participant completes the web-based authorization flow, the MyDataHelps platform will handle establishing the connection and initiating data transfer. Your app’s only responsibility is dismissing the Safari view at the appropriate time.

At the end of the connection flow in the Safari view, the participant is sent to the finalRedirectURL configured above to indicate that the browser can be dismissed. Your app should intercept this URL via the AppDelegate’s application(_:open:options:) or application(_:continue:restorationHandler:) or the SwiftUI onOpenURL modifier, and programmatically dismiss the SFSafariViewController when the URL is opened.

The user should also be allowed to manually dismiss the Safari view at any time to cancel the authorization or escape if there is an error. In these cases the finalRedirectURL will not be invoked, but you can use SFSafariViewControllerDelegate to be notified of manual dismissal if needed.

Managing External Accounts

Once an external account is connected, your app can use the SDK to allow participants to monitor and manage their account. See External Accounts for available features.

Examples

This code listing outlines the general process for provider connections:

External Provider Connection Process
// 1. Select an ExternalAccountProvider for the participant to connect to.
let searchText: String = ... // user-driven keyword search
let providers = try await session.queryExternalAccountProviders(ExternalAccountProvidersQuery(search: searchText, category: .provider))
...
let selectedIndex: Int = ... // user selects a provider to connect to
let providerToConnect = providers[selectedIndex]

// 2. Prepare an external account authorization session.
func prepareAuthorization(providerToConnect: ExternalAccountProvider) async throws -> ExternalAccountAuthorization {
    let redirectURL = URL(string: "https://my.app/linkprovidercompletion")!
    let authorization = try await session.connectExternalAccount(providerID: providerToConnect.id, finalRedirectURL: redirectURL)
    return authorization
}

// 3. Present the participant-mediated authorization flow.
func presentAuthorizationFlow(authorization: ExternalAccountAuthorization) {
    let safariView = SFSafariViewController(url: authorization.authorizationURL)
    safariView.dismissButtonStyle = .cancel
    present(safariView, animated: true)
}

// 4. Handle incoming redirect URLs from the authorization flow.
// This is triggered by AppDelegate, SceneDelegate,
// or SwiftUI's onOpenURL depending your selected UI framework.
func onOpenURL(redirectURL: URL) {
    if redirectURL.scheme == authorization.finalRedirectURL.scheme,
        redirectURL.path() == authorization.finalRedirectURL.path() {
        // Incoming URL indicates a provider authorization completion.
        // Dismiss the Safari view and update your app's UI as needed.
        dismiss(animated: true)
    }
}
// 1. Select an ExternalAccountProvider for the participant to connect to. let searchText: String = ... // user-driven keyword search let providers = try await session.queryExternalAccountProviders(ExternalAccountProvidersQuery(search: searchText, category: .provider)) ... let selectedIndex: Int = ... // user selects a provider to connect to let providerToConnect = providers[selectedIndex] // 2. Prepare an external account authorization session. func prepareAuthorization(providerToConnect: ExternalAccountProvider) async throws -> ExternalAccountAuthorization { let redirectURL = URL(string: "https://my.app/linkprovidercompletion")! let authorization = try await session.connectExternalAccount(providerID: providerToConnect.id, finalRedirectURL: redirectURL) return authorization } // 3. Present the participant-mediated authorization flow. func presentAuthorizationFlow(authorization: ExternalAccountAuthorization) { let safariView = SFSafariViewController(url: authorization.authorizationURL) safariView.dismissButtonStyle = .cancel present(safariView, animated: true) } // 4. Handle incoming redirect URLs from the authorization flow. // This is triggered by AppDelegate, SceneDelegate, // or SwiftUI's onOpenURL depending your selected UI framework. func onOpenURL(redirectURL: URL) { if redirectURL.scheme == authorization.finalRedirectURL.scheme, redirectURL.path() == authorization.finalRedirectURL.path() { // Incoming URL indicates a provider authorization completion. // Dismiss the Safari view and update your app's UI as needed. dismiss(animated: true) } }

If your app is configured to connect to a single specific provider, you can skip step 1 above and use the configured provider ID when calling connectExternalAccount:

Connecting to a Known Provider
let knownProviderID = ExternalAccountProvider.ID(someKnownID)
let authorization = try await model.source.session.connectExternalAccount(providerID: knownProviderID, finalRedirectURL: finalRedirectURL)
let knownProviderID = ExternalAccountProvider.ID(someKnownID) let authorization = try await model.source.session.connectExternalAccount(providerID: knownProviderID, finalRedirectURL: finalRedirectURL)

Additional Sample Code

In the MyDataHelpsKit example app, see:

SDK Reference