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:
- Display a clear, non-technical explanation of the security threats detected
- Present the severity level of each threat in a user-friendly manner
- Provide clear options for the user to either:
- Proceed with the action despite the threats (consent)
- Cancel the action to avoid potential security risks
- Include educational information about the potential risks of proceeding
- Maintain brand consistency while emphasizing the security context
- 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
Field | Description | Possible Values |
---|---|---|
threatId | Unique identifier for the threat | Integer (e.g., 17, 32) |
threatName | Human-readable name of the threat | "Developer Options", "Usb Debugging", etc. |
threatMsg | User-friendly description of the threat | "Device is insecure, developer option is enabled." |
threatReason | Additional details about why the threat was detected | System-specific reason strings |
threatCategory | Category of the threat | "SYSTEM", "APP", "NETWORK" |
threatSeverity | Severity level of the threat | "LOW", "MEDIUM", "HIGH" |
configuredAction | The default action configured for this threat | "REPORT", "TERMINATE" |
shouldProceedWithThreats | Flag to indicate whether to proceed with threats | Boolean (to be set by the app) |
rememberActionForSession | Flag to remember the action for the current session | Boolean (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:
- Allow the operation to proceed despite the threats
- 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
Parameter | Type | Description | Platform-Specific Notes |
---|---|---|---|
userConsentThreats | String (JSON) | Stringified threats JSON with updated threat actions | React Native, Cordova |
userConsentThreats | List<RDNAThreat> | List of threat objects with updated threat actions | Flutter |
userConsentThreats | NSArray<RDNAThreat*> | Array of threat objects with updated threat actions | Native iOS |
rdnaThreats | RDNA.RDNAThreat[] | Array of threat objects with updated threat actions | Native 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:
shouldProceedWithThreats | rememberActionForSession | Action Taken |
---|---|---|
true | true | ALLOW_FOR_SESSION (Allow and remember for this session) |
false | true | TERMINATE (Do not allow and remember decision) |
true | false | ALLOW (Allow but ask again if threat reappears) |
false | false | TERMINATE (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
-
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
-
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
- If you set
shouldProceedWithThreats
to true, your app will continue despite security threats - Setting
rememberActionForSession
to true prevents the same threats from triggering the event again in the current session
📊 Best Practices
- Always respond to the
onUserConsentThreats
event by callingtakeActionOnThreats
- Present security threats in a user-friendly way without technical jargon
- Use appropriate UI elements to indicate the severity of threats (colors, icons)
- Group threats by category when multiple threats are detected
- Provide clear explanations of the risks if the user chooses to proceed
- Remember that the SDK remains in a halt state until
takeActionOnThreats
is called - Consider your app's security policy when deciding default recommendations
- Implement proper logging for security threats for audit purposes
- Test threat handling thoroughly on both clean and compromised devices
- Use the
rememberActionForSession
flag judiciously to balance security and user experience
Updated 2 months ago