OTP ( Email and sms)
The OTP (One-Time Password) Challenge is a commonly used step in the User Onboarding flow. It typically involves sending a one-time password via SMS or email to the user ( depending on the channel configured in Gateway Manager by REL-ID Admin), which they must enter for verification.
Here’s how you can implement the OTP challenge in your app using the REL-ID SDK.
📥 Event: getActivationCode
getActivationCode
The SDK triggers this event when an OTP challenge is required. The application must prompt the user to enter the activation code (OTP) and submit it using setActivationCode
.
🧾 Sample Payload
{
"userID": "testuser",
"verificationKey": "pkn35f",
"attemptsLeft": 3,
"challengeResponse": {
"status": {
"statusCode": 100,
"statusMessage": "Success."
},
"session": {
"sessionType": 0,
"sessionID": "5888NO9S5QK8..."
},
"additionalInfo": {
"currentWorkFlow": "AdditionalDeviceActivation"
},
"challengeInfo": [
{ "key": "Response label", "value": "OTP" },
{ "key": "description", "value": "Enter one time password" },
{ "key": "SDK_CHLNG", "value": "NO" },
{ "key": "SDK_CHLNG_MODE", "value": "NA" },
{ "key": "ENABLE_RESEND_ACTIVATION_CODE", "value": "true" }
]
},
"error": {
"longErrorCode": 0,
"shortErrorCode": 0,
"errorString": "Success"
}
}
🧾 Field Descriptions
Field | Description |
---|---|
userID | Identifier for the user who is being challenged. |
verificationKey | This is the key tied to the OTP sent to the user. This key will be present in the email and can be displayed in the UI as well so the user knows which OTP email they should refer to—especially useful when multiple emails are received. |
attemptsLeft | How many OTP attempts remain before lockout. |
challengeResponse.status | Status of the previous invocation of the same challenge. |
challengeResponse.status.statusCode | Numeric result code (e.g., 100 = Success). |
challengeResponse.status.statusMessage | Descriptive message for status. |
challengeResponse.session.sessionType | Type of session (e.g., 0 = app session). |
challengeResponse.session.sessionID | Unique identifier for the SDK session. |
challengeResponse.additionalInfo | Optional metadata about user/session/environment. |
challengeResponse.additionalInfo.currentWorkFlow | Workflow name (e.g., AdditionalDeviceActivation ). |
challengeResponse.challengeInfo | UI and control info related to the challenge. |
└ "Response label" | Label for the OTP input field. |
└ "description" | Instruction for user about the OTP. |
└ "SDK_CHLNG" | NO implies the host application is responsible for showing the UI and collecting input (e.g., OTP). |
└ "SDK_CHLNG_MODE" | Challenge delivery type: NA . |
└ "ENABLE_RESEND_ACTIVATION_CODE" | Boolean flag to enable OTP resend option. |
error.longErrorCode | Detailed SDK error code. |
error.shortErrorCode | Short-form error code for UI display. |
error.errorString | Text message describing the error state. |
📤 Responding with setActivationCode
setActivationCode
Submit the user-entered OTP using this API.
✅ Success Response
{
"status": {
"statusCode": 100,
"statusMessage": "Success"
}
}
❌ Error Scenarios - TODO
Code | Message | Description / Handling Recommendation |
---|---|---|
106 | Invalid activation code provided. Please try again. | Shown when an incorrect code is provided, but retry attempts are still available. Prompt user to retry. |
110 | Activation code expired. | Indicates the code has timed out. Prompt the user to request or generate a new activation code. |
🔄 OTP Validation Flow
- ✅ If the OTP is successfully validated, the OTP challenge is considered complete.
The SDK will then determine the next callback event to invoke. For example, if there’s another challenge in the flow, the corresponding challenge callback (e.g., getPassword, getEmailOTP, etc.) will be triggered. - ⚠️ If the OTP is invalid but attempts remain, the SDK will re-invoke the getActivationCode event, allowing the user another opportunity to enter the correct OTP.
- ❌ If all OTP attempts are exhausted, the OTP challenge is marked as failed.
The SDK will determine the next step based on the current workflow.
⚠️ Notes
- ✅ It is possible to Unblock a user account that is blocked due to exhausting OTP attempts.
- 🔁User can choose to Resend OTP if not received to email or sms
Code Snippets for getActivationCode and setActivationCode
React Native
import { NativeEventEmitter, NativeModules } from 'react-native';
import RdnaClient from 'react-native-rdna-client';
const rdnaEventRegistery = new NativeEventEmitter(NativeModules.RdnaClient);
class AppComponent extends React.Component {
componentDidMount() {
// Register the event listener
this.getActivationCodeSubscription = rdnaEventRegistery.addListener(
'getActivationCode',
this.getActivationCode.bind(this)
);
}
componentWillUnmount() {
// Remove the event listener on cleanup
if (this.getActivationCodeSubscription) {
this.getActivationCodeSubscription.remove();
}
}
getActivationCode(event) {
// Handle the SDK's request for activation code
RdnaClient.setActivationCode('MY-ACTIVATION-CODE');
}
render() {
return null;
}
}
});
Flutter
// Import the plugin files
import 'package:rdna_client/rdna_client.dart';
import 'package:rdna_client/rdna_struct.dart';
// Create and initialize RdnaClient instance
final RdnaClient rdnaClient = RdnaClient();
void initializeListeners() {
rdnaClient.on(RdnaClient.getActivationCode, getActivationCode);
}
// Callback function
void getActivationCode(RDNAGetActivationCode response) {
// Provide the activation code back to the SDK
rdnaClient.setActivationCode("MY-ACTIVATION-CODE");
}
Cordova
document.addEventListener('deviceready', function () {
// Register the event listener for getActivationCode
document.addEventListener('getActivationCode', function () {
// Respond with the activation code
RdnaClient.setActivationCode("MY-ACTIVATION-CODE");
}, false);
}, false);
iOS (Objective-C)
// Inside your RDNA callback handler class conforming to RDNACallbacks protocol
- (void)getActivationCode:(NSString *)userID
verificationKey:(NSString *)verificationKey
attemptsLeft:(int)attemptsLeft
response:(RDNAChallengeResponse *)response
error:(RDNAError *)error {
// Example: Set activation code
response.activationCode = @"MY-ACTIVATION-CODE";
// Pass the response back to SDK
[[RDNA sharedInstance] setActivationCode:response];
}
Android (Java)
@Override
public void getActivationCode(String userID, String verificationKey, int attemptsLeft,
RDNAChallengeResponse response, RDNAError error) {
// Log or use these parameters as needed
Log.d("REL-ID", "UserID: " + userID);
Log.d("REL-ID", "VerificationKey: " + verificationKey);
Log.d("REL-ID", "Attempts Left: " + attemptsLeft);
// Provide the activation code back to the SDK
response.setActivationCode("MY-ACTIVATION-CODE");
// Submit the response to SDK
RDNA.getInstance().setActivationCode(response);
}
Activation Code Event Flow
flowchart TD Start([Start]) --> A[getActivationCode] A --> |submit code| B[setActivationCode] A -->|code not received| H[resendActivationCode]:::right B --> C{Valid code?} C -->|Yes| D[→ next challenge] C -->|No| E{Attempts left?} E -->|Yes| A E -->|No| F[getUser] F --> G[Unblock User] style A fill:#d4fdd4,stroke:#228b22,stroke-width:2px style F fill:#d4fdd4,stroke:#228b22,stroke-width:2px style B fill:#ffe4b3,stroke:#ff8c00,stroke-width:2px style H fill:#ffe4b3,stroke:#ff8c00,stroke-width:2px style G fill:#ffe4b3,stroke:#ff8c00,stroke-width:2px
🟩 Green - Callbacks issued by REL-ID SDK
🟧 Orange - APIs invoked by the Client App
Updated 2 months ago