This is the new Headless authentication SDK that is significantly faster and more robust than the previous version. This upgrade enhances performance, reliability, and security, ensuring a seamless authentication experience, along with a seamless integration process. We strongly recommend migrating to the new SDK for improved efficiency and better support. To migrate from the old SDK, remove the previous SDK dependency and integration and follow the below mentioned steps.

Step 1: Install OTPLESS SDK Dependency

Install the OTPLESS SDK dependency by running the following command in your terminal at the root of your React Native project:

npm i otpless-headless-rn

Step 2: Platform-specific Integrations

  1. Add intent filter inside your android/app/src/main/AndroidManifest.xml file into your Main activity code block:
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data
      android:host="otpless"
      android:scheme= "otpless.YOUR_APP_ID_IN_LOWERCASE"/>
</intent-filter>

Replace YOUR_APP_ID with your actual App ID provided in your OTPLESS dashboard.

  1. Add Network Security Config inside your android/app/src/main/AndroidManifest.xml file into your <application> code block (Only required if you are using the SNA feature):
android:networkSecurityConfig="@xml/otpless_network_security_config"
  1. Change your activity launchMode to singleTop and exported true for your Main Activity:
android:launchMode="singleTop"
android:exported="true"

Step 3: Configure Sign up/Sign in

  1. Import the OtplessHeadlessModule on your page..
login_page.tsx
import { OtplessHeadlessModule } from 'otpless-headless-rn';
  1. Create an instance of OtplessHeadlessModule.
login_page.tsx
const headlessModule = new OtplessHeadlessModule();
  1. Use useEffect hook to initialize the OtplessHeadlessModule and set callback.
login_page.tsx
useEffect(() => {
      headlessModule.initialize("YOUR_APPID")
      headlessModule.setResponseCallback(onHeadlessResult);
      return () => {
          headlessModule.clearListener();
          headlessModule.cleanup();
      };
  }, []);

Replace YOUR_APP_ID with your actual App ID provided in your OTPLESS dashboard.

  1. Add a method to receive callbacks from OtplessHeadlessModule.
login_page.tsx
const onHeadlessResult = (result: any) => {
  headlessModule.commitResponse(result);
  const responseType = result.responseType;

  switch (responseType) {
    case "SDK_READY": {
      // Notify that SDK is ready
      console.log("SDK is ready");
      break;
    }
    case "FAILED": {
        console.log("SDK initialization failed");
        // Handle SDK initialization failure
      break;
    }
    case "INITIATE": {
      // Notify that headless authentication has been initiated
      if (result.statusCode == 200) {
        console.log("Headless authentication initiated");
        const authType = result.response.authType; // This is the authentication type
        if (authType === "OTP") {
          // Take user to OTP verification screen
        } else if (authType === "SILENT_AUTH") {
          // Handle Silent Authentication initiation by showing 
          // loading status for SNA flow.
        }
      } else {
        // Handle initiation error. 
        // To handle initiation error response, please refer to the error handling section.
        if (Platform.OS === 'ios') {
            handleInitiateErrorIOS(result.response);
        } else if (Platform.OS === 'android') {
            handleInitiateErrorAndroid(result.response);
        }
      }
      break;
    }
    case "OTP_AUTO_READ": {
        // OTP_AUTO_READ is triggered only in Android devices for WhatsApp and SMS.
      if (Platform.OS === "android") {
        const otp = result.response.otp;
        console.log(`OTP Received: ${otp}`);
      }
      break;
    }
    case "VERIFY": {
        // notify that verification has failed.
        if (result.response.authType == "SILENT_AUTH") {
            if (result.statusCode == 9106) {
                // Silent Authentication and all fallback authentication methods in SmartAuth have failed.
                //  The transaction cannot proceed further. 
                // Handle the scenario to gracefully exit the authentication flow 
            }  else {
                // Silent Authentication failed. 
                // If SmartAuth is enabled, the INITIATE response 
                // will include the next available authentication method configured in the dashboard.
            }
        } else {
            // To handle verification failed response, please refer to the error handling section.
            if (Platform.OS === 'ios') {
                handleVerifyErrorIOS(result.response);
            } else if (Platform.OS === 'android') {
                handleVerifyErrorAndroid(result.response);
            }
        }

      break;
    }
    case "DELIVERY_STATUS": {
        // This function is called when delivery is successful for your authType.
        const authType = result.response.authType;
        // It is the authentication type (OTP, MAGICLINK, OTP_LINK) for which the delivery status is being sent
        const deliveryChannel = result.response.deliveryChannel;
        // It is the delivery channel (SMS, WHATSAPP, etc) on which the authType has been delivered
    }

    case "ONETAP": {
      const token = result.response.token;
      if (token != null) {
        console.log(`OneTap Data: ${token}`);
      // Process token and proceed. 
      }
      break;
    }
    case "FALLBACK_TRIGGERED": {
    // A fallback occurs when an OTP delivery attempt on one channel fails,  
    // and the system automatically retries via the subsequent channel selected on Otpless Dashboard.  
    // For example, if a merchant opts for SmartAuth with primary channal as WhatsApp and secondary channel as SMS,
    // in that case, if OTP delivery on WhatsApp fails, the system will automatically retry via SMS.
    // The response will contain the deliveryChannel to which the OTP has been sent.
      if (response.response.deliveryChannel != null) {
          const newDeliveryChannel = response.response.deliveryChannel 
          // This is the deliveryChannel to which the OTP has been sent
      }
      break;
    }
    default: {
      console.warn(`Unknown response type: ${responseType}`);
      break;
    }
  }

};

Step 4: Initiate Authentication

Initiate the authentication process based on the user’s selected method.

Phone authentication allows users to verify their identity using their phone number. Merchants can choose from various authentication methods:

  • Silent Authentication (SNA) – Automatically verifies the user without requiring OTP or MAGICLINK.
  • OTP on Desired Channel – Sends a one-time password (OTP) via SMS, WhatsApp, or another preferred channel.
  • Magic Link – Sends a link that users can click to authenticate.
  • SNA + OTP – Uses silent authentication first and falls back to OTP if needed.
  • OTP + Magic Link – Sends both an OTP and a magic link, allowing users to authenticate via either method.
const startPhoneAuth = (phoneNumber: string, countryCode: string) => {
  const request = {
      phone: phoneNumber,
      countryCode
  };
  headlessModule.start(request);
};

Verify OTP

To verify the OTP entered by the user, use the verify method with the necessary parameters. Verifying OTP is required only in case of OTP authentication. No need to verify OTP in case of MAGICLINK.

const verifyPhoneOtp = (phoneNumber: string, countryCode: string, otp: string) => {
  const request = {
      phone: phoneNumber,
      countryCode,
      otp
  };
  headlessModule.start(request);
};

Error Handling

The error codes for android and iOS have to be handled separately.

const handleInitiateErrorAndroid = (response: any) => {
    const errorCode = response?.errorCode as string;
    const errorMessage = response?.errorMessage as string;

    if (!errorCode) {
        console.log("OTPless Error: Unknown error -", errorMessage);
        return;
    }

    switch (errorCode) {
        case "7101":
            console.log("OTPless Error: Invalid parameters values or missing parameters -", errorMessage);
            break;
        case "7102":
            console.log("OTPless Error: Invalid phone number -", errorMessage);
            break;
        case "7103":
            console.log("OTPless Error: Invalid phone number delivery channel -", errorMessage);
            break;
        case "7104":
            console.log("OTPless Error: Invalid email -", errorMessage);
            break;
        case "7105":
            console.log("OTPless Error: Invalid email channel -", errorMessage);
            break;
        case "7106":
            console.log("OTPless Error: Invalid phone number or email -", errorMessage);
            break;
        case "7113":
            console.log("OTPless Error: Invalid expiry -", errorMessage);
            break;
        case "7116":
            console.log("OTPless Error: OTP Length is invalid (4 or 6 only allowed) -", errorMessage);
            break;
        case "7121":
            console.log("OTPless Error: Invalid app hash -", errorMessage);
            break;
        case "4000":
            console.log("OTPless Error: Invalid request values -", errorMessage);
            break;
        case "4001":
            console.log("OTPless Error: Unsupported 2FA request -", errorMessage);
            break;
        case "4003":
            console.log("OTPless Error: Incorrect request channel -", errorMessage);
            break;
        case "401":
        case "7025":
            console.log("OTPless Error: Unauthorized request or country not enabled -", errorMessage);
            break;
        case "7020":
        case "7022":
        case "7023":
        case "7024":
            console.log("OTPless Error: Too many requests (rate limiting) -", errorMessage);
            break;
        case "9002":
        case "9003":
        case "9004":
        case "9005":
        case "9006":
        case "9007":
        case "9008":
        case "9009":
            console.log("OTPless Error: Passkey authentication error -", errorMessage);
            break;
        case "500":
            console.log("OTPless Error: Unknown passkey error -", errorMessage);
            break;
        case "9100":
        case "9104":
        case "9103":
            console.log("OTPless Error: Network connectivity error -", errorMessage);
            break;
        default:
            console.log("OTPless Error: Unknown error -", errorMessage);
    }
};