azakaw_kyc_flutter 1.0.0 copy "azakaw_kyc_flutter: ^1.0.0" to clipboard
azakaw_kyc_flutter: ^1.0.0 copied to clipboard

Azakaw KYC onboarding for Flutter — runs the Azakaw compliance onboarding flow in a WebView, with region and environment selection matching the Azakaw web SDK.

azakaw_kyc_flutter #

Runs the Azakaw KYC / compliance onboarding flow inside your Flutter app.

The flow itself is the Azakaw onboarding portal, hosted in a WebView. The configuration surface mirrors the Azakaw web SDK (@azakawcompliance/azakaw-web-sdk) — the same regions, the same environments, and the same URL derivation — so a session behaves the same way on web and on mobile.

Features #

  • Region selection: UAE, KSA, Qatar, Kuwait
  • Environment selection: Sandbox, Production
  • A real completion signal — the portal's OnboardingCompleted event reaches your Dart code
  • Camera permission handling for document and liveness capture, on both Android and iOS
  • hideSidebar / hideOnboardingSections, delivered over the same handshake the web SDK uses
  • Arabic / RTL preselection

Install #

dependencies:
  azakaw_kyc_flutter: ^1.0.0

Requires Flutter 3.24+, iOS 14.3+, Android API 21+.

The bundled example/ app needs Flutter 3.35+ to build for iOS, because iOS 26+ requires the UIScene lifecycle. That applies to running the example only, not to integrating the SDK.

iOS 14.3 is the floor because WKWebView gained getUserMedia there — document and liveness capture cannot work below it. On iOS 15+ the SDK handles the camera prompt itself; on 14.3–14.x WKWebView prompts using your NSCameraUsageDescription.

Usage #

import 'package:azakaw_kyc_flutter/azakaw_kyc_flutter.dart';

final result = await AzakawKyc.start(
  context: context,
  config: AzakawKycConfig(
    sessionId: sessionId,                        // from your backend
    region: AzakawRegion.uae,
    environment: AzakawEnvironment.sandbox,
  ),
);

switch (result.status) {
  case AzakawKycStatus.completed:
    // Confirm the outcome server-side against the session id before
    // treating the user as verified.
    break;
  case AzakawKycStatus.cancelled:
    break;
  case AzakawKycStatus.failed:
    debugPrint('${result.error}');
    break;
}

AzakawKyc.start also accepts onComplete, onCancel and onError callbacks if you prefer them to the returned future.

To embed the flow in your own layout instead of a full-screen route, use AzakawKycView directly.

Configuration #

Field Type Default Description
sessionId String — Required. Session id from the Azakaw backend. Must be non-empty.
region AzakawRegion uae Selects the portal domain.
environment AzakawEnvironment sandbox Selects the portal subdomain.
hideSidebar bool false Hides the portal's sidebar.
hideOnboardingSections bool false Starts on the first form page and hides the sections page until onboarding completes.
language AzakawLanguage? null en or ar. ar also switches the portal to RTL. null leaves the portal's own default.
isFullscreen bool true Full-screen route, or an inset dialog.
resolveTenantHost bool true Opens the flow directly on the tenant's own domain. See below.
enableLogging bool false Logs protocol traffic via debugPrint. Never enable in release — payloads include the session id.

hideSidebar and hideOnboardingSections reach the portal over the postMessage handshake rather than the URL, so they apply once the portal has booted, not at load time. This matches the web SDK.

Regions and environments #

Region Domain Sandbox Production
uae (default) azakaw.com sandbox.azakaw.com app.azakaw.com
ksa azakawksa.com — not available app.azakawksa.com
qatar azakawqatar.com — not available app.azakawqatar.com
kuwait azakaw.com kuwait-stg.azakaw.com kuwait.azakaw.com

Sandbox is provisioned for UAE and Kuwait. Pair ksa and qatar with AzakawEnvironment.production; those combinations compose a URL — as they do in the web SDK — but the host does not resolve. AzakawKycConfig.isUnavailableCombination reports this, and the SDK logs a warning in debug builds.

Kuwait does not follow the app/sandbox pattern. It shares the azakaw.com domain with UAE and is separated by subdomain instead, so its API and auth hosts are kuwait-api / kuwait-auth and kuwait-stg-api / kuwait-stg-auth. AzakawRegion.subdomainFor is the authority; do not assume the convention.

Tenant domains #

Tenants can run the portal on their own domain, often with their own theming. The portal reports that domain only after it has booted and decoded the session token (the TenantBaseUrl event), so the generic host renders first and the user sees a flash of the wrong brand.

With resolveTenantHost (the default), the SDK reads the same baseUrl claim from the session token up front — one anonymous GET {authUrl}AppSessionManager/GetToken/{sessionId}, which is a pure read and does not consume the session — and opens the WebView on the tenant domain directly.

It is only an optimisation. If the lookup fails, times out, or the token names no domain, the region host loads and the portal's TenantBaseUrl redirect still corrects it, exactly as in the web SDK. Set resolveTenantHost: false to skip the extra request and rely on the redirect alone.

Permissions #

The plugin declares INTERNET and CAMERA in its own manifest, so Android host apps inherit them through manifest merging — you do not need to add them yourself. It also declares android.hardware.camera as not required, so your Play Store device filtering is unaffected.

On iOS you must do two things.

  1. Add a camera usage description to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for identity verification</string>
  1. Enable the camera permission in your ios/Podfile. permission_handler compiles every permission out by default (#ifndef PERMISSION_CAMERA → #define PERMISSION_CAMERA 0), so without this the camera request always reports denied no matter how correct your Info.plist is:
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CAMERA=1'
    end
  end
end

Enable the camera only. The flow never needs anything else, and shipping unused permission code invites App Store review questions.

The microphone is never requested: the portal captures with getUserMedia({ video: ..., audio: false }).

At runtime the SDK requests the OS camera permission and then grants it to the WebView. If the user denies it, the portal shows its own "camera unavailable" message.

How it talks to the portal #

The web SDK is a parent page holding an iframe, so the portal's window.parent.postMessage(...) crosses a frame boundary. A Flutter WebView has no parent frame — window.parent === window — so this SDK reports the portal's own origin as hostOrigin. The portal's messages are then delivered back to its own window, where a script injected at document start forwards them to Dart.

That matters because the portal treats a non-empty hostOrigin as "SDK mode" (isSdkEnabled = !!thirdPartyOrigin); without it, it never emits OnboardingCompleted at all.

The script intercepts window.postMessage rather than merely listening. The portal's handshake stream completes on the first message whose origin matches hostOrigin, so its own outbound request — echoed back because window.parent is the page itself — would end that stream before any reply arrived, and the portal would abandon the session-token exchange and show its login screen. Portal → host events therefore go to Dart instead of being re-delivered into the page; only the reply is delivered.

Supported events: OnboardingCompleted, IframeParametersRequest / IframeParametersResponse, and TenantBaseUrl (vanity-domain redirect). ResizeIframe is received and ignored — a WebView fills its own box and the portal scrolls inside it, so there is no outer frame to resize.

Example #

example/ is a harness with a session-id field, region and environment pickers, the layout and language toggles, and a live view of the resolved hosts. Run it on a physical device — camera capture does not work in a simulator.

cd example
flutter pub get
flutter run

Integration tests #

example/integration_test/ drives the real app against the live portal — the only way to cover what unit tests cannot, namely that the portal's postMessage actually reaches Dart inside a WebView.

cd example
flutter test integration_test/bridge_test.dart -d <device>   # handshake round-trip
flutter test integration_test/tls_test.dart    -d <device>   # bad cert is rejected

Both pass on an Android emulator and an iOS simulator. bridge_test needs network access and hits app.azakaw.com.

Upgrading from 0.0.x #

See CHANGELOG.md. 1.0.0 is a breaking release: the Environment enum is replaced by AzakawRegion + AzakawEnvironment, and the sandbox host has changed.

Support #

software@azakaw.com · docs.azakaw.com

Licensed under a commercial agreement — see LICENSE.

0
likes
130
points
107
downloads

Documentation

Documentation
API reference

Publisher

verified publisherazakaw.com

Weekly Downloads

Azakaw KYC onboarding for Flutter — runs the Azakaw compliance onboarding flow in a WebView, with region and environment selection matching the Azakaw web SDK.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_inappwebview, http, permission_handler

More

Packages that depend on azakaw_kyc_flutter

Packages that implement azakaw_kyc_flutter