onUserConsentThreats

📱 Overview

The onUserConsentThreats event is triggered when the REL-ID SDK detects security threats on the device that require user consent to continue. This event allows mobile app developers to handle security threats appropriately by presenting consent options to the user.

When this event is triggered, the application must respond by calling the takeActionOnThreats API with the user's decision on how to handle the detected threats.


Purpose

  • Notifies the app about security threats detected by the REL-ID SDK
  • Provides information about the specific threats and their severity
  • Enables developers to seek user consent to continue despite threats
  • Helps implement appropriate security measures based on threat context
  • Maintains compliance with security policies while allowing controlled user experience
  • Requires the app to call takeActionOnThreats API in response

🖥️ User Interface Requirements

When handling the onUserConsentThreats event, mobile application developers should:

  1. Display a clear, non-technical explanation of the security threats detected
  2. Present the severity level of each threat in a user-friendly manner
  3. Provide clear options for the user to either:
    • Proceed with the action despite the threats (consent)
    • Cancel the action to avoid potential security risks
  4. Include educational information about the potential risks of proceeding
  5. Maintain brand consistency while emphasizing the security context
  6. Consider accessibility guidelines to ensure all users can understand the severity

🔌Sample code by framework


React Native
// Import the necessary modules
import RdnaClient from 'react-native-rdna-client';

// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the listener for it

// Set up event listener for onUserConsentThreats event
let onUserConsentThreatsSubscription = rdnaEventRegistery.addListener(
  'onUserConsentThreats', (response) => {
    // Handle the response
    console.log("onUserConsentThreats event received:", response);
    // Implement your logic here
  }
);

// Don't forget to remove the event listener when component unmounts
componentWillUnmount() {
  onUserConsentThreatsSubscription.remove();
}
Flutter
import 'package:flutter/material.dart';
import 'package:rdna_plugin/rdna_plugin.dart';

// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the listener for it

// Set up event listener for onUserConsentThreats event
rdnaClient.on(RdnaClient.onUserConsentThreats, onUserConsentThreats);

// Define the callback function
void onUserConsentThreats(RDNAUserConsentThreats response) {
  // Handle the response
  print("onUserConsentThreats event received");
  // Implement your logic here
}
Cordova
// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the listener for it

// Set up event listener for onUserConsentThreats event
document.addEventListener('onUserConsentThreats', onUserConsentThreats);

// Define the callback function
function onUserConsentThreats(response) {
  // Handle the response
  console.log("onUserConsentThreats event received:", response);
  // Implement your logic here
}
Native iOS
// Objective-C
// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the handler for it

// Set up event listener for onUserConsentThreats event
- (void)onUserConsentThreats:(RDNAChallengeResponse *)response {
    // Handle the response
    NSLog(@"onUserConsentThreats event received");
    // Implement your logic here
}

// Swift
// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the handler for it

// Set up event listener for onUserConsentThreats event
func onUserConsentThreats(_ response: RDNAChallengeResponse) {
    // Handle the response
    print("onUserConsentThreats event received")
    // Implement your logic here
}
Native Android
// Note: onUserConsentThreats is an event, not a method to call
// This event is triggered when the SDK detects security threats 
// and needs user consent to continue

// The event will be triggered automatically by the SDK
// You only need to set up the handler for it

// Set up event listener for onUserConsentThreats event
void onUserConsentThreats(RDNA.RDNAChallengeResponse response, RDNAError error) {
    // Handle the response
    Log.d("REL-ID", "onUserConsentThreats event received");
    // Implement your logic here
}

Event Payload

When the SDK triggers the onUserConsentThreats event, it provides the following payload:

React Native / Cordova

Stringified JSON array containing threat information:

[
  {
    "threatId": 17,
    "threatName": "Developer Options",
    "threatMsg": "Device is insecure, developer option is enabled.",
    "threatReason": "",
    "threatCategory": "SYSTEM",
    "threatSeverity": "LOW",
    "configuredAction": "REPORT",
    "appInfo": {
      "appName": "",
      "appSha256": "",
      "packageName": ""
    },
    "networkInfo": {
      "ssid": "",
      "bssid": "",
      "maliciousAddress": "",
      "maliciousMacAddress": ""
    },
    "shouldProceedWithThreats": false,
    "rememberActionForSession": false
  }
]

Flutter

Array of RDNAThreat objects with the following structure:

class RDNAThreat {
  int? threatId = 0;
  String? threatName = "";
  String? threatMsg = "";
  String? threatReason = "";
  String? threatCategory = "";
  String? threatSeverity = "";
  String? configuredAction = "";
  RDNAAppInfo? appInfo;
  RDNANetworkInfo? networkInfo;
  bool? shouldProceedWithThreats;
  bool? rememberActionForSession;
}

Native iOS

Array of RDNAThreat objects with the following structure:

@interface RDNAThreat : NSObject
@property (nonatomic, strong) NSString *threatName;
@property (nonatomic, strong) NSString *threatMsg;
@property (nonatomic, strong) NSString *threatReason;
@property (nonatomic, strong) NSString *threatSeverity;
@property (nonatomic, strong) NSString *threatCategory;
@property (nonatomic, strong) NSString *configured_action;
@property (nonatomic) int threatId;
@property (nonatomic) RDNAAppInfo *appInfo;
@property (nonatomic) RDNANetworkInfo *networkInfo;
@property (nonatomic) BOOL shouldProceedWithThreats;
@property (nonatomic) BOOL rememberActionForSession;
@end

Native Android

Array of RDNAThreat objects with the following structure:

public class RDNAThreat {
  private int threatId = 0;
  private String threatName = "";
  private String threatCategory = "";
  private String threatMsg = "";
  private String threatReason = "";
  private String threatSeverity = "";
  private String configuredAction = "";
  private RDNAAppInfo appInfo;
  private RDNANetworkInfo networkInfo;
  private boolean shouldProceedWithThreats;
  private boolean rememberActionForSession;
}

Key Payload Fields

FieldDescriptionPossible Values
threatIdUnique identifier for the threatInteger (e.g., 17, 32)
threatNameHuman-readable name of the threat"Developer Options", "Usb Debugging", etc.
threatMsgUser-friendly description of the threat"Device is insecure, developer option is enabled."
threatReasonAdditional details about why the threat was detectedSystem-specific reason strings
threatCategoryCategory of the threat"SYSTEM", "APP", "NETWORK"
threatSeveritySeverity level of the threat"LOW", "MEDIUM", "HIGH"
configuredActionThe default action configured for this threat"REPORT", "TERMINATE"
shouldProceedWithThreatsFlag to indicate whether to proceed with threatsBoolean (to be set by the app)
rememberActionForSessionFlag to remember the action for the current sessionBoolean (to be set by the app)

Response API: takeActionOnThreats

API Overview

The takeActionOnThreats API allows your application to respond to security threats detected by the REL-ID SDK. When security threats are detected, the SDK issues the onUserConsentThreats event and enters a halt state. Your application must call this API to either:

  1. Allow the operation to proceed despite the threats
  2. Terminate the operation due to security concerns

The API takes the threat information that was received in the onUserConsentThreats event, with your decision flags set appropriately, and communicates your decision back to the SDK.


API Purpose

  • Responds to detected security threats with user consent information
  • Instructs the SDK whether to proceed or terminate
  • Optionally remembers decisions for the current session
  • Releases the SDK from its halt state
  • Ensures critical security decisions are explicitly made

Request Parameters

ParameterTypeDescriptionPlatform-Specific Notes
userConsentThreatsString (JSON)Stringified threats JSON with updated threat actionsReact Native, Cordova
userConsentThreatsList<RDNAThreat>List of threat objects with updated threat actionsFlutter
userConsentThreatsNSArray<RDNAThreat*>Array of threat objects with updated threat actionsNative iOS
rdnaThreatsRDNA.RDNAThreat[]Array of threat objects with updated threat actionsNative Android

After receiving the onUserConsentThreats event, your application must call the takeActionOnThreats API to respond to the threats:


API Integration

React Native Implementation
// Process the threats and set user decision
const processThreats = (threats) => {
  // Parse the stringified threats JSON
  const threatsList = JSON.parse(threats);
  
  // Ask user for consent or make a decision based on app policy
  // For each threat in the list, set:
  // - shouldProceedWithThreats: true to continue, false to terminate
  // - rememberActionForSession: true to remember decision for this session
  
  // Example: allowing all threats and remembering for the session
  threatsList.forEach(threat => {
    threat.shouldProceedWithThreats = true;
    threat.rememberActionForSession = true;
  });
  
  // Convert back to string to pass to the API
  return JSON.stringify(threatsList);
};

// When onUserConsentThreats event is received
const handleUserConsentThreats = (response) => {
  // Display threats to the user and get decision
  const processedThreats = processThreats(response);
  
  // Call the takeActionOnThreats API with user's decision
  RdnaClient.takeActionOnThreats(processedThreats, (syncResponse) => {
    console.log("Threat actions processed:", syncResponse);
  });
};
Flutter Implementation
// Process the threats and set user decision
void processThreatsAndTakeAction(List<RDNAThreat> threats) {
  // Ask user for consent or make a decision based on app policy
  // For each threat in the list, set:
  // - shouldProceedWithThreats: true to continue, false to terminate
  // - rememberActionForSession: true to remember decision for this session
  
  // Example: allowing all threats and remembering for the session
  for (var threat in threats) {
    threat.shouldProceedWithThreats = true;
    threat.rememberActionForSession = true;
  }
  
  // Call the takeActionOnThreats API with user's decision
  rdnaClient.takeActionOnThreats(threats);
}

// When onUserConsentThreats event is received
void onUserConsentThreats(List<RDNAThreat> threatList) {
  // Display threats to the user
  // Then process threats and take action
  processThreatsAndTakeAction(threatList);
}
Cordova Implementation
// Process the threats and set user decision
function processThreats(threats) {
  // Parse the stringified threats JSON if it's a string
  const threatsList = typeof threats === 'string' ? JSON.parse(threats) : threats;
  
  // Ask user for consent or make a decision based on app policy
  // For each threat in the list, set:
  // - shouldProceedWithThreats: true to continue, false to terminate
  // - rememberActionForSession: true to remember decision for this session
  
  // Example: allowing all threats and remembering for the session
  threatsList.forEach(threat => {
    threat.shouldProceedWithThreats = true;
    threat.rememberActionForSession = true;
  });
  
  // Convert back to string to pass to the API
  return JSON.stringify(threatsList);
}

// When onUserConsentThreats event is received
function onUserConsentThreats(response) {
  // Display threats to the user and get decision
  const processedThreats = processThreats(response);
  
  // Call the takeActionOnThreats API with user's decision
  com.uniken.rdnaplugin.RdnaClient.takeActionOnThreats(
    function(success) {
      console.log("Threat actions processed successfully");
    },
    function(error) {
      console.error("Error processing threat actions:", error);
    },
    [processedThreats]
  );
}
Native iOS Implementation
// Objective-C
- (void)onUserConsentThreats:(NSArray<RDNAThreat*> *)threats {
    // Display threats to the user and get decision
    
    // Example: allowing all threats and remembering for the session
    for (RDNAThreat *threat in threats) {
        threat.shouldProceedWithThreats = YES;
        threat.rememberActionForSession = YES;
    }
    
    // Call the takeActionOnThreats API with user's decision
    RDNAError *error = [rdnaClient takeActionOnThreats:threats];
    if (error.shortErrorCode != 0) {
        NSLog(@"Error taking action on threats: %@", error.errorString);
    }
}
// Swift
func onUserConsentThreats(_ threats: [RDNAThreat]) {
    // Display threats to the user and get decision
    
    // Example: allowing all threats and remembering for the session
    for threat in threats {
        threat.shouldProceedWithThreats = true
        threat.rememberActionForSession = true
    }
    
    // Call the takeActionOnThreats API with user's decision
    let error = rdnaClient.takeActionOnThreats(threats)
    if error.shortErrorCode != 0 {
        print("Error taking action on threats: \(error.errorString)")
    }
}
Native Android Implementation
@Override
public void onUserConsentThreats(RDNA.RDNAThreat[] threats) {
    // Display threats to the user and get decision
    
    // Example: allowing all threats and remembering for the session
    for (RDNA.RDNAThreat threat : threats) {
        threat.setShouldProceedWithThreats(true);
        threat.setRememberActionForSession(true);
    }
    
    // Call the takeActionOnThreats API with user's decision
    RDNAError error = rdnaClient.takeActionOnThreats(threats);
    if (error.getShortErrorCode() != 0) {
        Log.e("REL-ID", "Error taking action on threats: " + error.getErrorString());
    }
}

Threat Action Combinations

When responding to threats, you can configure the following combinations of actions:

shouldProceedWithThreatsrememberActionForSessionAction Taken
truetrueALLOW_FOR_SESSION (Allow and remember for this session)
falsetrueTERMINATE (Do not allow and remember decision)
truefalseALLOW (Allow but ask again if threat reappears)
falsefalseTERMINATE (Do not allow and ask again if threat reappears)


✅ Developer Notes

When the SDK triggers the onUserConsentThreats event:

    • Display the detected threats to the user in a clear, non-technical manner
    • Explain the severity and potential risks
    • Present options to proceed or cancel
  1. After user makes a decision, call takeActionOnThreats API with:

    • shouldProceedWithThreats set according to user's choice (true to proceed, false to terminate)
    • rememberActionForSession set according to whether to remember this choice for the session
  2. After calling takeActionOnThreats:

    • If successful (error code 0), the SDK will continue or terminate based on the provided action
    • If there's an error, display the appropriate error message to the user

Points to Remember

The SDK will remain in a halt state until you call takeActionOnThreats

  1. If you set shouldProceedWithThreats to true, your app will continue despite security threats
  2. Setting rememberActionForSession to true prevents the same threats from triggering the event again in the current session


📊 Best Practices

  1. Always respond to the onUserConsentThreats event by calling takeActionOnThreats
  2. Present security threats in a user-friendly way without technical jargon
  3. Use appropriate UI elements to indicate the severity of threats (colors, icons)
  4. Group threats by category when multiple threats are detected
  5. Provide clear explanations of the risks if the user chooses to proceed
  6. Remember that the SDK remains in a halt state until takeActionOnThreats is called
  7. Consider your app's security policy when deciding default recommendations
  8. Implement proper logging for security threats for audit purposes
  9. Test threat handling thoroughly on both clean and compromised devices
  10. Use the rememberActionForSession flag judiciously to balance security and user experience