Using WiFi for Silent Network Auth

Using WiFi is more complicated when trying to use Silent Network Auth. By default, all traffic on all operating systems will favor WiFi above cellular connections. However for Silent Network Auth, the API request must be made using the cellular connection. We realize that users are unlikely to turn off WiFi and so the following code is provided for both iOS and Android to include in your applications that will allow a small payload (~40 bytes) to be delivered over the cellular modem, even when WiFi is connected.

❗️

This article is for apps only.

Only downloadable and installable applications are suitable for this fix. If you are attempting to use Silent Network Auth in a website this solution will not work. You should instruct users to turn off WiFi.

Android Sample Code

The following will allow Android applications using API Release M and above to use Cellular for the Silent Network Auth API request.

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void doAPIonCellularNetwork(Context context, final String url) {
       
       ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
       
       NetworkRequest request = new NetworkRequest.Builder()
               .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
               .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();

       connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() {

           @Override
           public void onAvailable(final Network network) {
         OkHttpClient okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build();
         Request request = new Request.Builder()
               .url(url)
               .build();
         try {
            Response response = okHttpClient.newCall(request).execute();
            Log.i("", "doAPIonCellularNetwork RESULT:\n" + response.body().string());
         } catch (Exception ex) {            
                ex.printStackTrace();
         }
           }
       });
   }

iOS Sample Code

For iOS, start by downloading the library from here.

Add the NetworkingLogic folder, which contains six files, to your project folder as shown below.

421421

Include #import "HTTPRequester.h in the Swift bridging header file. Also, include the code below as a member function in the ViewController that fires the EVURL.

//
//  EvurlRequestWithCellularData.swift
//
//  Created by BENJAMIN BRYANT BUDIMAN on 05/09/18.
//  Copyright © 2021 Boku, Inc. All rights reserved.
//

import Foundation

/**
Requests the EvURL with cellular data, and checks whether the Silent Network Auth process completes or not.
Important note: this function shall always return false if cellular data is not available.

 - Parameter evurl: The EvURL to be requested
 - Returns: true if the Silent Network Auth process is successful and vice versa
 */
func requestEvurlWithCellularData(evurl:String) -> Bool {
    let response = requestHelper(url: evurl)
    
    // If any internal and network errors occured in HTTPRequester.performGetRequest, the function will return "ERROR"
    if response == "ERROR" {
        return false;
    }
    
    // Boku returns "ErrorCode=0&ErrorDescription=Success" only when the Silent Network Auth process is complete
    if response.range(of:"ErrorCode=0&ErrorDescription=Success") != nil {
        return true;
    }
    
    // Any HTTP responses without the above substring indicate an incomplete Silent Network Auth process
    return false;
}

/**
 Recursive function that keeps requesting a new URL with cellular data when the HTTP request returns a HTTP redirect code (3xx)
 
 - Parameter url: The URL to be requested
 - Returns: string response from the HTTP request
 */
func requestHelper(url:String) -> String {
    // If the HTTP GET request returns a HTTP redirect code (3xx), HTTPRequester.performGetRequest returns a
    // formatted string that contains the redirect URL. The formatted string starts with "REDIRECT:"
    // and it's followed with the redirect URL (e.g. REDIRECT:https://www.boku.com)
    var response = HTTPRequester.performGetRequest(URL(string: url))
    
    if response!.range(of:"REDIRECT:") != nil {
        // 1. Get the redirect URL by getting rid of the "REDIRECT:" substring
        let redirectRange = response!.index(response!.startIndex, offsetBy: 9)...
        let redirectLink = String(response![redirectRange])
        
        // 2. Make a request to the redirect URL
        response = requestHelper(url: redirectLink)
    }
    
    return response!
}

Execute the EVURL as shown in the code sample below. Please note the EVURL will change and must be created each time.

override func viewDidLoad() {
  super.viewDidLoad()
  
  let EVURL = "http://boku-url/cimi/evurl?SKEY=BEHBuKkD3yxt6dD6NgEHKhjBLZTPwQgT2Yb06NMnCilwuVgEetIlH7lUL%2BgmAEY%2FlaFVkoxzfdndPlVmP9FBRycx%2BhKZeLAo1gmvBP9qdb0%3D"
  
  _ = requestEvurlWithCellularData(evurl: EVURL) 
}

🚧

EVURLs are Unique!

EVURLs are unique to each request, do not hard code one. EVURLs can be created manually using the Create an EVURL endpoint.