WebView iOS and Android
The WebView option allows individuals to verify their identity in a mobile app with the Android WebView or iOS WKWebView.
Mobile WebView Integration (iOS & Android)
For a seamless, in-app user experience, you can embed the Trust Swiftly verification flow within your native mobile app using a WebView component. This guide will walk you through the implementation for both Android and iOS.
The core technology is the same Magic Link used in web integrations, but with a specific pattern to control the user flow.
The Core Concept: The "Redirect-to-Close" Pattern
This is the most important concept for a successful WebView integration.
Get the Link: Your app gets a unique
magic_link
for a user from your backend.Provide a Redirect URL: When your backend creates or requests the user link from the Trust Swiftly API, it must include a
redirect_url
. This URL should be a custom, non-existent URL that your app can uniquely identify (e.g.,https://yourapp.com/verification-complete
).Open the WebView: Your app opens the
magic_link
in a full-screen WebView.User Completes Flow: The user completes the verification steps inside the WebView.
Trust Swiftly Redirects: Upon completion, our server redirects the WebView to the
redirect_url
you provided.Your App Intercepts the Redirect: Your app's native code must listen for navigation events within the WebView. When it detects the WebView attempting to navigate to your specific
redirect_url
, it knows the process is complete.Your App Closes the WebView: Upon detecting the redirect, your app programmatically closes the WebView and returns the user to your native UI.
This pattern ensures a smooth transition back to your application without the user getting "stuck" on a "verification complete" page inside the WebView.
Android WebView
Guide
WebView
GuideStep 1: Configure Permissions & Manifest
First, ensure your AndroidManifest.xml
includes the necessary permissions for camera access and is configured to handle the WebView activity.
<!-- AndroidManifest.xml -->
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<application ...>
<activity android:name=".TrustSwiftlyWebViewActivity" />
<!-- ... other activities -->
</application>
</manifest>
Step 2: Implement the WebView Activity
Create a dedicated Activity
to host the WebView
. This code provides a complete, robust implementation that handles permissions, file uploads, and the critical redirect-to-close pattern.
// TrustSwiftlyWebViewActivity.java
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
public class TrustSwiftlyWebViewActivity extends AppCompatActivity {
public static final String EXTRA_MAGIC_LINK = "extra_magic_link";
private static final String REDIRECT_URL = "https://yourapp.com/verification-complete"; // Your unique redirect URL
private WebView webView;
private ValueCallback<Uri[]> filePathCallback;
// ... (Add other variables for file chooser logic from your original docs if needed)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview); // Assume a simple layout with a WebView
webView = findViewById(R.id.webView);
String magicLink = getIntent().getStringExtra(EXTRA_MAGIC_LINK);
// --- Basic WebView Settings ---
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setMediaPlaybackRequiresUserGesture(false);
// --- The two most important clients ---
webView.setWebViewClient(new TrustSwiftlyWebViewClient());
webView.setWebChromeClient(new TrustSwiftlyWebChromeClient());
if (magicLink != null) {
webView.loadUrl(magicLink);
}
}
// This client handles page navigation and the redirect-to-close pattern.
private class TrustSwiftlyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// === THIS IS THE MOST IMPORTANT PART ===
// Check if the WebView is being redirected to our special URL.
if (url.startsWith(REDIRECT_URL)) {
// The flow is complete. Set a result and finish this activity.
setResult(Activity.RESULT_OK);
finish();
return true; // Stop the redirect from actually loading.
}
return super.shouldOverrideUrlLoading(view, url);
}
}
// This client handles UI-related events like permissions and file choosers.
private class TrustSwiftlyWebChromeClient extends WebChromeClient {
// This is for requesting camera permission when needed by the webpage.
@Override
public void onPermissionRequest(PermissionRequest request) {
// NOTE: This is a simplified example. A production app should handle
// permission requests more gracefully.
request.grant(request.getResources());
}
// This is for handling file uploads (e.g., uploading an ID document).
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
TrustSwiftlyWebViewActivity.this.filePathCallback = filePathCallback;
// (Your existing robust file chooser logic goes here)
// ...
return true;
}
}
// (Your existing onActivityResult and onRequestPermissionsResult logic goes here)
// ...
}
Step 3: Launch the Activity
From another part of your app, launch the TrustSwiftlyWebViewActivity
and pass the magic_link
.
// In your main activity or fragment
Intent intent = new Intent(this, TrustSwiftlyWebViewActivity.class);
intent.putExtra(TrustSwiftlyWebViewActivity.EXTRA_MAGIC_LINK, "YOUR_MAGIC_LINK_FROM_API");
startActivityForResult(intent, YOUR_REQUEST_CODE);
iOS WKWebView
Guide
WKWebView
GuideStep 1: Configure Permissions (Info.plist
)
Your app must include an entry for NSCameraUsageDescription
in its Info.plist
file to explain why it needs camera access.
<!-- Info.plist -->
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to verify your identity.</string>
Step 2: Implement the WebView Controller
Create a dedicated UIViewController
to manage the WKWebView
. This controller will handle loading the URL, delegating permissions, and intercepting the final redirect.
// TrustSwiftlyWebViewController.swift
import UIKit
import WebKit
class TrustSwiftlyWebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
var magicLink: URL!
var webView: WKWebView!
let redirectUrl = "https://yourapp.com/verification-complete" // Your unique redirect URL
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true // Prevents fullscreen video takeover
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.navigationDelegate = self
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.load(URLRequest(url: magicLink))
}
// === THIS IS THE MOST IMPORTANT PART ===
// This delegate method is called whenever the WebView decides to navigate.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let urlString = navigationAction.request.url?.absoluteString, urlString.starts(with: redirectUrl) {
// The flow is complete. Dismiss this view controller.
self.dismiss(animated: true, completion: nil)
decisionHandler(.cancel) // Stop the redirect from actually happening.
return
}
decisionHandler(.allow) // Allow all other navigation.
}
// This delegate handles JavaScript UI, like permission requests.
func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
// Automatically grant camera permission to provide a smoother experience.
decisionHandler(.grant)
}
}
Step 3: Present the Controller (SwiftUI Example)
From your main application view, present the TrustSwiftlyWebViewController
as a sheet.
// Your main SwiftUI View
import SwiftUI
struct ContentView: View {
@State private var showVerification = false
// In a real app, this would be fetched from your backend.
let magicLink = "YOUR_MAGIC_LINK_FROM_API"
var body: some View {
Button("Start Verification") {
self.showVerification.toggle()
}
.sheet(isPresented: $showVerification) {
// Bridge to the UIKit ViewController
VerificationView(magicLink: URL(string: magicLink)!)
}
}
}
// A helper to wrap our UIViewController for use in SwiftUI
struct VerificationView: UIViewControllerRepresentable {
let magicLink: URL
func makeUIViewController(context: Context) -> some UIViewController {
return TrustSwiftlyWebViewController(magicLink: magicLink)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}
Common Issues
❗️Multiple signups
If testing your app and creating multiple verify sessions you should clear the cookies and cache of WKWebView inbetween new user sessions. (Refer to this guide)
WKWebsiteDataStore.default().removeData(ofTypes: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache], modifiedSince: Date(timeIntervalSince1970: 0), completionHandler:{ })
❗️Webkit Inline Media Playback
Please ensure
allowsInlineMediaPlayback
is enabled when creating a webview on a webkit browser (mobile Safari). This defaults to false and the camera preview will incorrectly open as a fullscreen live broadcast.
❗Camera Configuration
The WebView Flow requires access to the device camera. Please include the
NSCameraUsageDescription
key your app'sInfo.plist
file as described in the Apple Developer documentation.
❗️Allow External Network Requests
Trust Swiftly makes external network calls within the Inquiry Flow that need to be allowlisted for the flow to properly function. Certain frameworks such as Cordova require such requests to be allow listed. Please include
*.trustswiftly.com/*
in such an allow list if needed
Make sure permissions are correctly set for your app bundle.
Camera and Microphone Permission

Last updated