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.
Platform Native SDK WebView iOS iOS SDK Not recommended Android Android SDK Not recommended React Native Coming Soon Recommended Flutter Coming Soon Recommended
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
Open in WebView
Your app loads the verification_url in a WebView component.
User completes verification
The user goes through the verification flow inside the WebView.
Intercept callback
When done, the WebView navigates to your callback URL. Your app intercepts this navigation and extracts the result.
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.
Setting Purpose 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
Parameter Description 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
Ensure mediaPlaybackRequiresUserGesture is false
Verify camera permissions are granted at the OS level
Check that the user agent string is set correctly
White screen or loading issues
Verify the session URL is valid and not expired
Check internet connectivity
Ensure JavaScript is enabled in the WebView settings
Verify your callback URL matches what you set when creating the session
Check that the navigation delegate/listener is properly configured
Try setting callback_method to "both" when creating the session