fhir_auth 0.13.0 copy "fhir_auth: ^0.13.0" to clipboard
fhir_auth: ^0.13.0 copied to clipboard

discontinuedreplaced by: fhir_r4_auth

Secure authentication and authorization for FHIR applications implementing SMART on FHIR (OAuth 2.0, PKCE, JWT, backend services), for every FHIR version.

fhir_auth #

pub package License: BSD-3-Clause

Production-ready SMART on FHIR authentication and authorization for Flutter applications. Implements the complete SMART App Launch specification with enterprise-grade security.

Features #

✅ Complete SMART on FHIR Implementation

  • Standalone launch (patient-facing apps)
  • EHR launch (embedded within EHR systems)
  • Backend services (server-to-server)

✅ Security Best Practices

  • PKCE (Proof Key for Code Exchange) required by default
  • Secure token storage with encryption
  • JWT validation and verification
  • Token introspection and revocation
  • Audit logging

✅ Enterprise Features

  • Session management with timeout controls
  • Token refresh handling
  • Multi-platform support (iOS, Android, Web, Desktop)
  • Comprehensive error handling

✅ Developer Experience

  • Type-safe API
  • Extensive documentation
  • Working examples for all launch types
  • 386+ unit and integration tests

Quick Start #

Installation #

Add to your pubspec.yaml:

dependencies:
  fhir_auth: ^0.6.0
  fhir_r4: ^0.6.0

Basic Standalone Launch #

import 'package:fhir_auth/fhir_auth.dart';

// 1. Configure your client
final client = SmartFhirClient(
  config: SmartConfig(
    clientId: 'your-client-id',
    fhirBaseUrl: 'https://fhir.example.com/r4'.toFhirUri,
    redirectUri: Uri.parse('com.yourapp://callback'),
    scopes: ['patient/*.read', 'launch/patient'],
  ),
);

// 2. Authenticate (launches the SMART authorization flow)
await client.login();

// 3. SmartFhirClient is an authenticated http.Client. Use it directly,
//    or hand it to fhir_r4_at_rest to build typed FHIR requests:
//    FhirReadRequest(..., client: client).sendRequest();

EHR Launch #

// Parse launch parameters from your URL
final params = Uri.base.queryParameters;

final client = SmartFhirClient(
  config: SmartConfig(
    clientId: params['clientId']!,
    fhirBaseUrl: params['iss']!.toFhirUri,
    redirectUri: Uri.parse('https://your-app.com/callback'),
    launchType: LaunchType.ehr,
    launchToken: params['launch'],
    scopes: ['patient/*.read', 'launch'],
  ),
);

await client.login();

Common Use Cases #

Token Refresh #

Tokens are automatically refreshed before expiry:

// Manual refresh if needed
await client.refreshToken();

Token Revocation #

// Logout and revoke tokens
await client.logout();

// Or revoke specific tokens
await client.revokeAccessToken();

Session Management #

final client = SmartFhirClient(
  config: config,
  sessionManager: SessionManager(
    config: SessionConfig(
      idleTimeout: Duration(minutes: 15),
      absoluteTimeout: Duration(hours: 8),
    ),
  ),
);

// Listen for timeout warnings
client.onSessionTimeoutWarning?.listen((remaining) {
  print('Session expires in ${remaining.inMinutes} minutes');
});

// Listen for session expiry
client.onSessionTimeout?.listen((reason) {
  print('Session ended: $reason');
});

// Record user activity to prevent idle timeout
await client.recordActivity();

Audit Logging #

// Events are recorded to an in-memory store by default
final auditLogger = AuditLogger();

final client = SmartFhirClient(
  config: config,
  auditLogger: auditLogger,
);

// Inspect recorded events at any time
final events = await auditLogger.queryEvents();
for (final event in events) {
  print('Audit: ${event.eventType.name}');
}

Secure Token Storage #

// Tokens are automatically stored securely
// On mobile: Keychain (iOS) / KeyStore (Android)
// On web: Encrypted localStorage

// Custom storage
final client = SmartFhirClient(
  config: config,
  tokenStorage: CustomTokenStorage(),
);

Platform-Specific Setup #

iOS #

Add to ios/Runner/Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>com.yourapp</string>
    </array>
  </dict>
</array>

Android #

Add to android/app/src/main/AndroidManifest.xml:

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

Web #

Create web/redirect.html:

<!DOCTYPE html>
<html>
<head><title>Authentication Redirect</title></head>
<body>
<script>
  window.opener.postMessage(window.location.href, '*');
</script>
</body>
</html>

Supported FHIR Servers #

Tested and working with:

  • ✅ Epic (Sandbox & Production)
  • ✅ Cerner (Sandbox & Production)
  • ✅ SMART Health IT Sandbox
  • ✅ HAPI FHIR Server
  • ✅ Google Cloud Healthcare API
  • ✅ Microsoft Azure API for FHIR
  • ✅ AWS HealthLake

Documentation #

Examples #

Check out the example directory for complete working applications:

  • example/standalone_launch.dart - Patient-facing app
  • example/ehr_launch.dart - Embedded in EHR
  • example/backend_services.dart - Server-to-server
  • example/advanced_features.dart - Session management, audit logging

Troubleshooting #

Common Issues #

"No OAuth configuration found"

  • Ensure your FHIR server's CapabilityStatement includes SMART extensions
  • Check that /metadata endpoint is accessible

"PKCE verification failed"

  • Some servers don't support PKCE yet - disable with enablePkce: false
  • This is NOT recommended for production

Token refresh fails

  • Ensure you requested offline_access scope
  • Check that your server supports refresh tokens

Web redirect doesn't work

  • Verify redirect.html exists in web/ directory
  • Check redirect URI is registered with FHIR server
  • Ensure redirect URI matches exactly (including trailing slash)

See the full troubleshooting guide for more help.

Contributing #

Contributions welcome! Please read CONTRIBUTING.md first.

Testing #

# Run all tests
flutter test

# Run specific test suite
flutter test test/unit/
flutter test test/integration/

# Run with coverage
flutter test --coverage

License #

BSD-3-Clause License - see LICENSE file for details.

Support #

Acknowledgments #

Built with ❤️ by the FHIRfli team.

Implements SMART App Launch specification from HL7.

8
likes
140
points
427
downloads

Documentation

API reference

Publisher

verified publisherfhirfli.dev

Weekly Downloads

Secure authentication and authorization for FHIR applications implementing SMART on FHIR (OAuth 2.0, PKCE, JWT, backend services), for every FHIR version.

Homepage
Repository (GitHub)
View/report issues

Topics

#fhir #smart-on-fhir #healthcare #authentication #oauth2

License

MIT (license)

Dependencies

crypto, flutter, flutter_appauth, flutter_secure_storage, flutter_web_auth_2, flutter_web_auth_2_platform_interface, http, jose, logging, url_launcher, uuid

More

Packages that depend on fhir_auth