iOS Integration

Overview

This document details the specific integration steps for the EdgeOne Client Authentication SDK in an iOS project, including SDK importing, permission configuration, initialization, authentication engine startup, challenge handling, and token usage in API requests.

Integration steps

Note:
Before the integration is started, please ensure you have read and understood the Mobile Integration Overview to comprehend the basic authentication flow on mobile devices.

1. Add the EdgeOne SDK to your project

Integrating the EdgeOne Client Authentication SDK into your iOS project is the first step. You can import the SDK via CocoaPods. Add the following content to your Podfile:
pod 'ClientAttestation', :podspec => './SDK' // Configuration example, please replace with actual SDK podspec address
Then run the following commands:
pod install

2. Initialize the SDK

Before using any authentication features, you need to initialize the EdgeOne SDK using your service domain and an optional log level. This is typically performed once in your AppDelegate or during application launch.
#import <TCBasCommon/TCBasCommon.h>
#import <ClientAttestation/ClientAttestation.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// SDK initialization
TCBasConfig *basConfig = [[TCBasConfig alloc] init];
basConfig.baseUrl = @"www.example.com"; // Set to the business domain
basConfig.logLevel = TCBCLogLevelTypeWARN; // Optional. Set the log level
[TCBas initializeWithOptions:basConfig];
return YES;
}
Parameter description:
baseUrl: Your EdgeOne service domain, for example www.example.com.
logLevel: Optional parameter used to control the log output level of the SDK. Optional values include:
TCBCLogLevelTypeNONE: Disable logs (default)
TCBCLogLevelTypeVERBOSE: Enable verbose and higher level logs.
TCBCLogLevelTypeDEBUG: Enable debug and higher level logs.
TCBCLogLevelTypeINFO: Enable info and higher level logs.
TCBCLogLevelTypeWARN: Enable warning and higher level logs.
TCBCLogLevelTypeERROR: Enable error and higher level logs.
extraDataProvider: Optional parameter. Set IDFV to enhance risk identification capabilities.

3. Start the authentication engine

After the SDK is initialized, you need to start the client authentication engine to enable the SDK to begin obtaining and managing authentication tokens. This operation starts the necessary background processes within the SDK.
#import <ClientAttestation/ClientAttestation.h>

// Start the client authentication engine.
[[ClientAttestation sharedInstance] start];
Note: After the authentication engine is started, the SDK will be ready to handle authentication challenges and manage authentication tokens.

4. Perform the client authentication challenge

Authentication challenge is a key step in obtaining authentication tokens. This process involves obtaining the challenge ID and passing it to the SDK. The SDK will display necessary UI as needed (for example, showing Captcha in WKWebView) and compute the authentication token. This is accomplished through the attestWithParams() method provided by the SDK.
#import <ClientAttestation/ClientAttestation.h>

// attestId
// Obtain from the console when actively initiating a challenge.
// Obtain from the 'EO-Attest-Challenge' header field in the http response when challenges are passively initiated.
NSString *attestId = @"your-attestId";
AttestParams *params = [[AttestParams alloc] init];
params.attestId = attestId;
params.webView = self.webView; // WebView used to display the Captcha page
params.reqTimeoutMillis = 60000; // Optional request timeout
[[ClientAttestation sharedInstance] attestWithParams:params
callback:self];

// Implement the AttestCallbackDelegate protocol
#pragma mark - AttestCallbackDelegate
- (void)onSuccess:(NSString *)token {
// Return the risk token and place it in the 'EO-Attest-Token' header field of the http request.
}

- (void)onError:(NSError *)error {
// Error message callback
}
Parameter description:
attestId: Configure challenge ID, obtain from the console or returned in the request result.
webView: Optional parameter, a WKWebView instance. This parameter must be provided when the authenticator requires user interaction (such as Captcha). If no UI interaction is needed, the WKWebView can be hidden.
vCodeDispType: Optional parameter, display mode for interactive Captcha UI. Use VCodeDispTypePopup for pop-up full-screen display, VCodeDispTypeFull for embedded display within the page. Default: VCodeDispTypePopup.
reqTimeoutMillis: Optional parameter to set the request timeout period, unit: milliseconds, default 60000 milliseconds.

5. Include the authentication token in the API request

When your iOS application initiates API requests to backend services protected by EdgeOne, must include the attestation token in the request headers. You can invoke the getAttestationToken() method provided by the SDK to obtain the currently valid attestation token at any time.
Note:
After a successful call to attestWithParams() is made, the SDK generates or updates the attestation token. Before the token is attached to the request header, you must call getAttestationToken() again to obtain the latest token. Each time you need to use the token data, retrieve it again. Do not save or reuse the token data returned by getAttestationToken().
#import <ClientAttestation/ClientAttestation.h>

// Obtain client authentication token
[[ClientAttestation sharedInstance] getAttestationTokenWithCompletion:^(NSString *token) {
// Example: Add the token to your network request header
// Assume you are using URLSession or other networking libraries
if (token) {
// Your request object
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://your-backend-api.com/data"]];
[request setValue:token forHTTPHeaderField:@"EO-Attest-Token"];
// Continue sending the request
}
}];
Important: Ensure this token is included in every API request that requires authentication. The SDK automatically manages the token life-cycle; you just need to retrieve the latest token before sending requests.

6. Handle server responses and challenges

When your backend service (protected by EdgeOne) receives a client request, it checks whether the request contains a valid attestation token. If authentication is required but no valid token is provided, the server returns an HTTP 428 status code, indicating that the client requires additional authentication. This is a critical step in iOS client integration that requires active adaptation by developers.
Your iOS application needs to implement a mechanism to capture and handle these HTTP 428 responses. For the detailed process, refer to re-obtain the attestation token, or renew an expired attestation token (handling HTTP 428 challenges).
Here is a simplified sample for handling HTTP 428 challenges:
#import <ClientAttestation/ClientAttestation.h>

// Assume your network request handling logic
- (void)sendAPIRequest:(NSMutableURLRequest *)request {
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"Network request error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 428) {
// Received a 428 challenge, extract the challenge ID
NSString *challengeId = httpResponse.allHeaderFields[@"EO-Attest-Challenge"];
if (challengeId) {
NSLog(@"Received a 428 challenge, challenge ID: %@", challengeId);
// Execute the authentication challenge
AttestParams *attestParams = [[AttestParams alloc] init];
attestParams.attestId = challengeId;
attestParams.webView = self.webView;
[[ClientAttestation sharedInstance] attestWithParams:attestParams callback:self];
// Note: You need to handle the AttestCallbackDelegate callbacks and resend the request in onSuccess.
} else {
NSLog(@"EO-Attest-Challenge header not found in 428 response");
}
} else if (httpResponse.statusCode == 200) {
NSLog(@"Request succeeded!");
// Process business data
} else {
NSLog(@"Request failed, status code: %ld", (long)httpResponse.statusCode);
// Handle other errors
}
}];
[task resume];
}

// Example call
// NSMutableURLRequest *initialRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://your-backend-api.com/protected-data"]];
// [self sendAPIRequest:initialRequest];

// Resend the request in the onSuccess method of AttestCallbackDelegate.
#pragma mark - AttestCallbackDelegate
- (void)onSuccess:(NSString *)token {
NSLog(@"Challenge succeeded, obtained a new token: %@", token);
// Resend the original request with the new token
// Obtain the previous request object and resend it
// For example:
// NSMutableURLRequest *retryRequest = [self.lastFailedRequest mutableCopy]; // assuming you saved the last failed request
// [retryRequest setValue:token forHTTPHeaderField:@"EO-Attest-Token"];
// [self sendAPIRequest:retryRequest];
}

- (void)onError:(NSError *)error {
NSLog(@"Authentication challenge failed: %@", error.localizedDescription);
}

7. (Optional) Use WKWebView for interactive authentication (and JS authentication)

In some client authentication scenarios, the authenticator may require user interaction (such as interactive Captcha) or perform computationally intensive tasks (such as cryptographic proof of work). At this point, the EdgeOne SDK requires specific runtime environment support. On mobile platforms, WKWebView (iOS platform) is a key component for implementing these features.
When the authenticator requires rendering an interactive CAPTCHA or running a JavaScript-based cryptographic Proof-of-Work challenge, the SDK requires a WKWebView instance to be provided when the attestWithParams() method is called. This means developers must pre-allocate a WKWebView instance in the application and pass it as a parameter to the SDK when invoking the authentication API.

Interactive authentication scenarios

Some authenticators (such as TC-CAPTCHA using embedded or pop-up interactive settings) require a WKWebView instance to render their interactive interface. This WKWebView instance will display the CAPTCHA page within the application, thus requiring pre-configuration to ensure proper rendering.
Embedded Interactive Authentication: The CAPTCHA interface is displayed as a fixed block on the device screen. To ensure correct UI rendering without compromising user experience, developers must preset the size, stacking order, and alignment of the rendering window. Note that the embedded authentication GUI does not scale with the screen view. For example, TC-CAPTCHA embedded mode recommends reserving at least 300x230 pixels for optimal rendering and user interaction.
Pop-up Interactive Authentication: The CAPTCHA interface appears as a floating window on the device screen when authentication is invoked. Similar to embedded authentication, the size, stacking order, and alignment of the rendering window need to be preset. The characteristic of pop-up authentication is that when the screen view is smaller than a specific threshold, the pop-up authentication GUI automatically scales to adapt to different screen sizes. For example, the initial rendering block size for TC-CAPTCHA pop-up mode is 360x360 pixels.

JavaScript-based authentication scenarios

Some authenticators (such as TC-CAPTCHA using invisible mode) require a WKWebView instance as a JavaScript runtime environment, primarily for executing cryptographic Proof-of-Work (PoW) challenges. In this scenario, the WKWebView instance only provides a JavaScript execution sandbox and does not visibly render any UI. Therefore, the passed WKWebView instance does not need to be visible, and the SDK will not use it for UI rendering.