fhir_auth 0.5.0-4 copy "fhir_auth: ^0.5.0-4" to clipboard
fhir_auth: ^0.5.0-4 copied to clipboard

outdated

A Dart/Flutter package for authorization & authentication, includes SMART on FHIR and Google sign-in

fhir_auth #

This package is supposed to allow easier authentication for FHIR applications (mostly using SMART on FHIR, although there's also support for general oauth2 and Google authentication). I will say, this continues to be the most frustrating package to try and develop/support. I continue to feel as though, even though each server that I work with SAYS that they support SMART on FHIR, and yet I still always struggle and fight with the process. Currently I'm successfully able to authenticate against GCP, Aidbox, Interopland, and MELD, and hopefully Azure soon. I still haven't gotten to AWS. These all work for both mobile and web. If anyone has practice authenticating against any other servers, please let me know!

FHIR® is the registered trademark of HL7 and is used with the permission of HL7. Use of the FHIR trademark does not constitute endorsement of this product by HL7.

Full SMART on FHIR #

All SMART on FHIR capabilities defined, all scopes allowed, all FHIR versions (Dstu2, Stu3, R4 and preview R5 #3) defined. Currently it only allows external to EHR launches, but soon should also support EHR launches.

Setup #

Setting up your app, because it has to go deeper in Android and iOS than most, is a pain. I'm using oauth2_client. And accordingly, I have followed their recommendations for setup (note, these are not exactly the same as my previous setup).

I've included examples in mobileauthdemo as well as webauthdemo.

Android Setup #

In your file android/app/build.gradle you should have a section entitled defaultConfig, you need to change it so that it looks similar to the following:

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "your.application.id"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        manifestPlaceholders = [
            'appAuthRedirectScheme': 'your.application.id'
        ]
    }

A few notes.

  1. Your minSdkVersion needs at least 18, and preferably something like 21 or 23.
  2. "your.application.id" is usually a reverse of a typicaly url format, so could be something like: "dev.fhirfli.application". This is also going to be your callback, although it should be something like: dev.fhirfli.application://callback (or in the case of google, sometimes they only allow a single slash, i.e. dev.fhirfli.application:/callback).
  3. While it may not be completely necessary, I add the manifestPlaceholders as formatted above.

In the AndroidManifest.xml file (android/app/src/main/AndroidManifest.xml)

<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
  <intent-filter android:label="flutter_web_auth">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="dev.fhirfli.mobileauthdemo" />
  </intent-filter>
</activity>

iOS Setup #

You must set the platform in ios/Podfile

platform :ios, '11.0'

Basic Example Setup #

SmartClient #

  final client = SmartClient.getSmartClient(
    fhirUrl: FhirUri(url),
    clientId: clientId,
    redirectUri: fhirCallback,
    Scopes(
      clinicalScopes: [
        ClinicalScope(
          Role.patient,
          R4ResourceType.Patient,
          Interaction.any,
        ),
      ],
      openid: true,
      offlineAccess: true,
    ),
    secret: secret, /// should not be used
    authUrl: authUrl == null ? null : FhirUri(authUrl),
    tokenUrl: tokenUrl == null ? null : FhirUri(tokenUrl),
  );

Workflow #

  await client.initialize();
  final request1 = FhirRequest.create(
    base: client.fhirUri!.value!,
    resource: _newPatient,
    fhirClient: client,
  );
  final response = await request1.request();

Api.dart #

In my examples, I'm using an API file for all of the credentials. In order to keep private things private, I haven't uploaded my API.dart file for public consumption. However, it looks something like the following for those playing along at home:

mixin Api {
  /// redirect url for oauth2 authentication
  static final fhirCallback = FhirUri('com.myshiny.newapp://callback');
  /// because google apparently requires/prefers one slash at times
  static final googleFhirCallback = FhirUri('com.myshiny.newapp:/callback');

  /// Aidbox
  static const aidboxUrl = 'https://demo.aidbox.app/fhir';
  static const aidboxClientId = 'e67063f5-1234-8558-9fc4-137g1mnod93b';

  /// GCS
  static const gcsUrl = 'https://healthcare.googleapis.com/v1/projects/'
      'brandnewdemo/locations/us-central1/'
      'datasets/demo/fhirStores/demo/fhir';
  static const gcsClientId =
      '411278748873-7l8946m31373be4889mnoii9w5y6a5gm.apps.googleusercontent.com';

  /// HAPI Server
  static const hapiUrl = 'https://hapi.fhir.org/baseR4';

  /// Interop
  static const interopClientId = 'e77063f5-1234-1234-9de4-137e1abcd83c';
  static const interopUrl = 'https://api.interop.community/Demo/data';

  /// MELD
  static const meldClientId = 'e77063f5-1234-1234-9de4-137e1abcd83c';
  static const meldUrl = 'https://meld.interop.community/Demo/data';
}

Mobile Auth by Provider #

Google's Healthcare API - ToDo #

I've included the ability to use Google sign-in, so if you'd like to connect to the Google Healthcare API. Follow Part 1 and Part 2 for instructions for setting up your own GCP version (this may need to be updated).

To briefly setup your app (assuming you have your GCP setup completed).

  1. Go through the APIs & Services -> OAuth consent screen (fill in everything, including support email, and your authorized domains as your GCP domain)
  2. Your sensitive scopes - Cloud Healthcare API
  3. APIs & Services -> Credentials -> Create OAuth client ID
  4. Package name should be (assuming API file above): com.myshiny.newapp
  5. You do need the SHA-1 certificate for this
  6. From the same menu, Create an OAuth client ID but select web application
  7. Identity Platform -> Add a Provider -> Select Google
  8. Web Client ID (from the above web app) and Web Client Secret (from the above web app)
  9. In this same client, input Allowed client IDs, and include the mobile app client ID

Aidbox #

I've liked Aidbox for a while. They have some nice features setup, so it's definitely worth taking a look. For us though, one of the really nice aspects is a free cloud demo.

  1. Start by going to https://aidbox.app/
  2. Create a new box called whatever you want, select your FHIR Version and Zone
  3. Create your client
PUT /Client/shinynewapp?_pretty=true
content-type: text/yaml
accept: text/yaml

secret: verysecret
grant_types:
  - code
auth:
  authorization_code:
    redirect_uri: com.myshiny.newapp://callback
first_party: true
  1. Create User (can be found more detail here)
data:
  name: Grey Faulkenberry
  roles:
    - Administrator
    - Doctor
email: user@mail.com
password: password
id: user1
resourceType: User
  1. Create AccessPolicy for user (for true production apps, you will need to consider how you actually want this to be done, what kind of access you need, etc. For now, we are giving all the permissions for the User)
engine: json-schema
schema:
  required:
    - client
    - user
    - request-method
  properties:
    user:
      required:
        - data
      properties:
        data:
          required:
            - roles
          properties:
            roles:
              not:
                items:
                  not:
                    enum:
                      - Administrator
              type: array
    client:
      required:
        - id
      properties:
        id:
          const: shinynewapp
    request-method:
      enum:
        - get
        - post
        - put
        - delete
        - option
        - patch
        - head
description: Full access for users with role Administrator from client shinynewapp
id: policy-for-shinynewapp-users-role-administrator
resourceType: AccessPolicy
  1. The mobileauthdemo should now be ready to connect to Aidbox.

Interopland and MELD #

  1. This is a relatively typical HAPI server
  2. After you have the server setup, select Apps, then create a new App.
  3. App Name and description can be what you'd like, Client Type should generally be Public Client
  4. App Launch URI for this is unimportant, because we're not launching from within their portal
  5. App redirect (given above API): com.myshiny.newapp://callback
  6. You'll need to choose your own scopes, I've gone with: launch patient/Patient.* openid profile offline_access user/Patient.*
  7. You'll also need to add some users (Settings -> USERS)

Azure API for FHIR (needs to be updated) - ToDo #

  static const azureClientId = 'myAzureClientId';
  static const azureTenantId = 'myAzureTenantId';
  static const azureSecret = 'myAzureSecret';
  static const azureUrl = 'https://myfhirserver.azurehealthcareapis.com';
  static const azureAuthUrl =
      'https://login.microsoftonline.com/$azureTenantId/oauth2/authorize?resource=$azureUrl';
  static const azureTokenUrl =
      'https://login.microsoftonline.com/$azureTenantId/oauth2/token';

Notice that capability statement will not give the proper endpoints, but it will not attach the url to the resource parameter for the authURl, this is important, and it won't work without it. This is my Azure tutorial, it's not as complete as the one above, but it should be a reasonable start.

Web Auth by Provider #

Redirect #

You'll most likely be distributing this as a PWA, so you should know what the redirect URL will be ahead of time. Just in case for test purposes, I've included a script you can use to make sure the it will run locally with the same port, and it will print out the redirect url that you can use. If you use this script, the redirect is: http://localhost:8888/redirect.html

The other piece to note is that we need a redirect file in the web folder. I use the one that was demonstrated in this article

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Connexion Succeeded</title>
    <meta name="description"
        content="Simple, quick, standalone responsive placeholder without any additional resources">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
</body>
<script>
    window.opener.postMessage(window.location.href, '*');
</script>

</html>

Google's Healthcare API #

  1. Follow the instructions above to set everything up.
  2. Ensure you put the Authorized Origins and Redirect URIs in the webauthdemo Oauth2 client
  3. For our demo, since we're running it on a localhost (don't ever do this in real life, and ESPECIALLY never in production), our origin is http://localhost:8888 and our redirect is http://localhost:8888/redirect.html

Aidbox #

  1. Same setup as above actually, just remember to change your redirect.

Interopland and MELD #

  1. Same setup as above, but remember that for this one you probably do want to make sure you have the correct launch url (although we're still launching externally) and the new redirect URL

Azure API for FHIR - ToDo #

  static const azureClientId = 'myAzureClientId';
  static const azureTenantId = 'myAzureTenantId';
  static const azureSecret = 'myAzureSecret';
  static const azureUrl = 'https://myfhirserver.azurehealthcareapis.com';
  static const azureAuthUrl =
      'https://login.microsoftonline.com/$azureTenantId/oauth2/authorize?resource=$azureUrl';
  static const azureTokenUrl =
      'https://login.microsoftonline.com/$azureTenantId/oauth2/token';

Notice that capability statement will not give the proper endpoints, but it will not attach the url to the resource parameter for the authURl, this is important, and it won't work without it. This is my Azure tutorial, it's not as complete as the one above, but it should be a reasonable start.

Suggestions and Complaints #

As I mentioned above, this is the most difficult package I've tried to publish. Mostly because authentication is a huge pain in the ass. Anyone who has suggestions or wants to open a PR is welcome. If you would like to contact me directly, my email is grey@fhirfli.dev.

FHIR® is a registered trademark of Health Level Seven International (HL7) and its use does not constitute an endorsement of products by HL7®

7
likes
0
points
145
downloads

Publisher

verified publisherfhirfli.dev

Weekly Downloads

A Dart/Flutter package for authorization & authentication, includes SMART on FHIR and Google sign-in

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

collection, fhir, flutter, freezed_annotation, google_sign_in, http, oauth2, oauth2_client, universal_html

More

Packages that depend on fhir_auth