Skip to main content
This guide covers how to integrate Didit verification into your mobile app using a WebView. This is the recommended approach for React Native and Flutter until native SDKs are available.

Use Native SDKs when available

Native SDKs are available for iOS and Android and provide significantly better performance, camera handling, NFC support, and user experience.
PlatformNative SDKWebView
iOSiOS SDKNot recommended
AndroidAndroid SDKNot recommended
React NativeComing SoonRecommended
FlutterComing SoonRecommended

When to Use WebView

Use WebView integration when:
  • You’re building with React Native or Flutter (native SDKs coming soon)
  • You need a quick prototype or proof of concept
  • You’re migrating from web and want a faster initial integration

How It Works

1

Create a session

Your backend calls the Create Session API and receives a verification_url.
2

Open in WebView

Your app loads the verification_url in a WebView component.
3

User completes verification

The user goes through the verification flow inside the WebView.
4

Intercept callback

When done, the WebView navigates to your callback URL. Your app intercepts this navigation and extracts the result.
5

Get full results via webhook

Your backend receives the complete decision data via webhook.

Creating a Session

Before opening the verification flow, create a session from your backend:
curl -X POST https://verification.didit.me/v3/session/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "your-workflow-id",
    "vendor_data": "user-123",
    "callback": "https://yourapp.com/callback"
  }'
Response:
{
  "session_id": "abc123...",
  "url": "https://verify.didit.me/session/abc123..."
}

React Native

Install the WebView package:
npm install react-native-webview
# or with Expo
npx expo install react-native-webview

Implementation

import React from 'react';
import { WebView } from 'react-native-webview';

const VerificationScreen = ({ sessionUrl, onComplete }) => {
  return (
    <WebView
      source={{ uri: sessionUrl }}
      // Required: generic mobile user agent
      userAgent="Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
      // Required for camera/media
      mediaPlaybackRequiresUserAction={false}
      allowsInlineMediaPlayback={true}
      // Android-specific
      domStorageEnabled={true}
      // Performance
      androidHardwareAccelerationDisabled={false}
      androidLayerType="hardware"
      // Intercept callback
      onNavigationStateChange={(navState) => {
        if (navState.url.includes('yourapp.com/callback')) {
          const url = new URL(navState.url);
          const sessionId = url.searchParams.get('verificationSessionId');
          const status = url.searchParams.get('status');
          onComplete({ sessionId, status });
        }
      }}
    />
  );
};

export default VerificationScreen;

React Native Demo

Expo + WebView verification example

Flutter

Add the required packages to pubspec.yaml:
dependencies:
  webview_flutter: ^4.4.0
  webview_flutter_wkwebview: ^3.9.0
  webview_flutter_android: ^3.12.0

Implementation

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';

class VerificationScreen extends StatefulWidget {
  final String sessionUrl;
  
  const VerificationScreen({super.key, required this.sessionUrl});

  @override
  State<VerificationScreen> createState() => _VerificationScreenState();
}

class _VerificationScreenState extends State<VerificationScreen> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _setupWebView();
  }

  void _setupWebView() {
    late final PlatformWebViewControllerCreationParams params;
    
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const {},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    _controller = WebViewController.fromPlatformCreationParams(params)
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setUserAgent(
        'Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 '
        '(KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
      )
      ..setNavigationDelegate(
        NavigationDelegate(
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.contains('yourapp.com/callback')) {
              _handleResult(request.url);
              return NavigationDecision.prevent;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(Uri.parse(widget.sessionUrl));

    // Grant camera/microphone permissions
    final platform = _controller.platform;
    platform.setOnPlatformPermissionRequest((request) {
      request.grant();
    });

    // Android-specific
    if (platform is AndroidWebViewController) {
      platform.setMediaPlaybackRequiresUserGesture(false);
    }
  }

  void _handleResult(String callbackUrl) {
    final uri = Uri.parse(callbackUrl);
    final sessionId = uri.queryParameters['verificationSessionId'];
    final status = uri.queryParameters['status'];
    
    Navigator.of(context).pop({
      'sessionId': sessionId,
      'status': status,
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Identity Verification')),
      body: WebViewWidget(controller: _controller),
    );
  }
}

Flutter Demo

Flutter WebView verification example

Critical Configuration

User Agent (Required)

You must set a generic mobile user agent for the WebView to work correctly:
Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36
This ensures proper camera access, correct UI rendering, and optimal media playback.

Media Settings (Required)

SettingPurpose
allowsInlineMediaPlaybackPrevents fullscreen video on iOS
mediaPlaybackRequiresUserGestureAllows auto-starting the camera
javaScriptEnabledRequired for SDK functionality
domStorageEnabledSession storage for Android

Handling the Callback

After verification, the WebView redirects to your callback URL with query parameters:
https://yourapp.com/callback?verificationSessionId=abc123&status=Approved
ParameterDescription
verificationSessionIdUnique session identifier
statusApproved, Declined, or In Review
For a better user experience, use a custom URL scheme (e.g., myapp://verification-complete) as your callback and handle it as a deep link in your app.

Troubleshooting

  1. Ensure mediaPlaybackRequiresUserGesture is false
  2. Verify camera permissions are granted at the OS level
  3. Check that the user agent string is set correctly
  1. Verify the session URL is valid and not expired
  2. Check internet connectivity
  3. Ensure JavaScript is enabled in the WebView settings
  1. Verify your callback URL matches what you set when creating the session
  2. Check that the navigation delegate/listener is properly configured
  3. Try setting callback_method to "both" when creating the session