Hybrid App integration
What is a Hybrid App
A Hybrid App uses both native URL requests and web views to communicate with your server. In the context of HUMAN, it's crucial to ensure that both native requests and web views are synchronized to provide the expected behavior for end users.
How Do I Know if My App is a Hybrid App
Your app is considered a Hybrid App if it has ALL of the following:
- A web view component (
WKWebView
on iOS orWebView
on Android) that loads your website. - Your website is protected by HUMAN (Bot Defender or Account Defender).
On iOS, if your app uses SFSafariViewController
, please let us know, and we will guide you through a specific integration.
How to Enable Hybrid App Support in My App
Integrate the SDK (Native)
You should integrate the SDK into your native app. You may choose one of the following methods:
Enable Hybrid App Support
When starting the SDK, declare your website's root domain in the policy. This should be the domain where the SDK will set cookies.
The SDK enables Hybrid App support ONLY for the specified domains. It checks if the website's domain ends with one of the specified domains. For example, setting example.com
will also support www.example.com
and api.example.com
.
You should pass the WebView
instance to the SDK using the following functions:
- iOS:
HumanSecurity.setupWebView(webView:navigationDelegate:)
- Android:
HumanSecurity.setupWebView(webView:webViewClient:)
Important: Do not set the navigationDelegate
(iOS) or webViewClient
(Android) properties after calling the setupWebView
function.
On iOS, you can enable automatic detection and setup of WKWebView
s by setting HSHybridAppPolicy.automaticSetup
to true
. This eliminates the need to manually call setupWebView
for each instance.
Example Implementation
Android
Kotlin:
import android.app.Application
import com.humansecurity.mobile_sdk.HumanSecurity
import com.humansecurity.mobile_sdk.main.policy.HSPolicy
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
startHumanSDK()
}
private fun startHumanSDK() {
try {
val policy = HSPolicy().apply {
// Configure the policy...
automaticInterceptorPolicy.interceptorType = HSAutomaticInterceptorType.INTERCEPT_WITH_DELAYED_RESPONSE // or INTERCEPT_AND_RETRY_REQUEST
hybridAppPolicy.setWebRootDomains(setOf(".example.com"), "<APP_ID>")
}
HumanSecurity.start(this, "<APP_ID>", policy)
} catch (exception: Exception) {
println("Exception: ${exception.message}")
}
}
}
Java:
import android.app.Application;
import android.util.Log;
import java.util.HashSet;
import com.humansecurity.mobile_sdk.HumanSecurity;
import com.humansecurity.mobile_sdk.main.policy.HSPolicy;
import com.humansecurity.mobile_sdk.main.policy.HSAutomaticInterceptorType;
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
startHumanSDK();
}
void startHumanSDK() {
try {
HSPolicy policy = new HSPolicy();
// Configure the policy...
policy.getAutomaticInterceptorPolicy().setInterceptorType(HSAutomaticInterceptorType.INTERCEPT_WITH_DELAYED_RESPONSE); // or INTERCEPT_AND_RETRY_REQUEST
HashSet<String> domains = new HashSet<>();
domains.add(".example.com");
policy.getHybridAppPolicy().setWebRootDomains(domains, "<APP_ID>");
HumanSecurity.INSTANCE.start(this, "<APP_ID>", policy);
} catch (Exception exception) {
Log.e("MainApplication", "Exception: " + exception.getMessage());
}
}
}
Kotlin (Activity):
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
import com.humansecurity.mobile_sdk.HumanSecurity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val webView = findViewById<WebView>(R.id.web_view)
val webViewClient = MyWebViewClient()
HumanSecurity.setupWebView(webView, webViewClient)
// Load your website in the web view...
}
}
Java (Activity):
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.humansecurity.mobile_sdk.HumanSecurity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = findViewById(R.id.web_view);
MyWebViewClient webViewClient = new MyWebViewClient();
HumanSecurity.INSTANCE.setupWebView(webView, webViewClient);
// Load your website in the web view...
}
}
iOS
Swift:
import UIKit
import HUMAN
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
startHumanSDK()
return true
}
func startHumanSDK() {
do {
let policy = HSPolicy()
// Configure the policy...
policy.hybridAppPolicy.set(webRootDomains: [".example.com"], forAppId: "<APP_ID>")
HSAutomaticInterceptorPolicy.urlSessionRequestTimeout = 10 // Set the timeout you would like for your requests.
try HumanSecurity.start(appId: "<APP_ID>", policy: policy)
} catch {
print("Error: \(error)")
}
}
}
Objective-C:
@import HUMAN;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self startHumanSDK];
return YES;
}
- (void)startHumanSDK {
HSPolicy *policy = [[HSPolicy alloc] init];
// Configure the policy...
[policy.hybridAppPolicy setWithWebRootDomains:[NSSet setWithObject:@".example.com"] forAppId:@"<APP_ID>"];
HSAutomaticInterceptorPolicy.urlSessionRequestTimeout = 10; // Set the timeout you would like for your requests.
NSError *error = nil;
[HumanSecurity startWithAppId:@"<APP_ID>" policy:policy error:&error];
if (error != nil) {
NSLog(@"Error: %@", error);
}
}
@end
Explanation of the Code
- Adding Web Root Domains:
- Specify your website's root domain (e.g.,
.example.com
) in the policy'swebRootDomains
. This ensures that the SDK only intercepts requests to these domains.
- Specify your website's root domain (e.g.,
- Starting the SDK:
- Initialize the SDK as early as possible on the main thread to ensure all URL requests include the necessary HTTP headers.
- Setting Up Web Views:
- Android: Use
HumanSecurity.setupWebView(webView:webViewClient:)
to set up theWebView
with the SDK'sWebViewClient
. Do not set theWebViewClient
directly after this. - iOS: Use
HumanSecurity.setupWebView(webView:navigationDelegate:)
to set up theWKWebView
with the SDK'snavigationDelegate
. Do not set thenavigationDelegate
directly after this.
- Android: Use
Notes:
- iOS Automatic Setup: If you enable
HSHybridAppPolicy.automaticSetup
, the SDK will automatically detect and set up allWKWebView
instances without needing to callsetupWebView
for each one. - Multiple AppIDs: If your app communicates with multiple servers having different AppIDs, use the
HumanSecurity.start(appIds:policy:)
function to pass an array of AppIDs and specify the relevant AppID for each API call.
Apple Pay on the Web
If your website uses Apple Pay on the Web, you should disable JavaScript evaluation by the SDK. To protect the security of Apple Pay transactions in WKWebView
, Apple Pay cannot be used alongside script injection APIs (relevant for iOS 13-15). Disable JavaScript evaluation by setting the SDK's policy accordingly.
Note: If your app targets only iOS 16 or above, you don't need to disable JavaScript evaluation by the SDK.
Swift:
policy.hybridAppPolicy.allowJavaScriptEvaluation = false
Objective-C:
policy.hybridAppPolicy.allowJavaScriptEvaluation = NO;
External Web Views (Available from v4.0.1)
If your app uses web views that are created outside the native side of the app but are still based on Apple's WKWebView
or Android's WebView
(e.g., react-native-webview), you should enable support for them in the SDK's policy.
Android
Kotlin:
policy.hybridAppPolicy.supportExternalWebViews = true
Java:
policy.getHybridAppPolicy().setSupportExternalWebViews(true);
iOS
Swift:
policy.hybridAppPolicy.supportExternalWebViews = true
Objective-C:
policy.hybridAppPolicy.supportExternalWebViews = YES;
Updated 7 days ago