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

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
FieldDescription
userIDIdentifier for the user who is being challenged.
verificationKeyThis 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.
attemptsLeftHow many OTP attempts remain before lockout.
challengeResponse.statusStatus of the previous invocation of the same challenge.
challengeResponse.status.statusCodeNumeric result code (e.g., 100 = Success).
challengeResponse.status.statusMessageDescriptive message for status.
challengeResponse.session.sessionTypeType of session (e.g., 0 = app session).
challengeResponse.session.sessionIDUnique identifier for the SDK session.
challengeResponse.additionalInfoOptional metadata about user/session/environment.
challengeResponse.additionalInfo.currentWorkFlowWorkflow name (e.g., AdditionalDeviceActivation).
challengeResponse.challengeInfoUI 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.longErrorCodeDetailed SDK error code.
error.shortErrorCodeShort-form error code for UI display.
error.errorStringText message describing the error state.

📤 Responding with setActivationCode

Submit the user-entered OTP using this API.

✅ Success Response

{
  "status": {
    "statusCode": 100,
    "statusMessage": "Success"
  }
}

❌ Error Scenarios - TODO

CodeMessageDescription / Handling Recommendation
106Invalid activation code provided. Please try again.Shown when an incorrect code is provided, but retry attempts are still available. Prompt user to retry.
110Activation 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