Web to Mobile Authentication

Initiates a web to mobile authentication and obtains authentication result

About client-facing steps

A journey is a sequence of steps that are executed when it's invoked by a client application (known as the "client"). Some steps require involvement from the client, such as to collect user input. Other steps, like validating a token, are executed in the backend by the Mosaic journey engine alone.

When invoked, the journey begins executing the steps while the client waits for further instructions. When a journey reaches a client-facing step, the journey asks the client for the required input and then waits for the client to respond. The client presents their own UI if user interaction is required, and returns input to the journey. The journey then proceeds in a similar manner until it's completed.

Description

This step initiates the web-to-mobile decoupled authentication process, allowing a user to authenticate in the web app using a registered mobile device through push notifications. For complete flow implementation and step-by-step instructions, refer to Login with push.

To perform web to mobile authentication, a user must have a mobile device pre-registered. This involves installing a mobile app, authenticating in this app, cryptographically binding it to a user, and registering it as a target for push notifications. Refer to the following guide for details on device registration: Login with push.

Note

This journey step relies on the mobile approve journey that has to be created beforehand.

Before initiating authentication, the journey must obtain the external user identifier, such as an email. For example, a login form can be used to collect it from the user. When executed, the step triggers Mosaic to send a push notification to approve an action on the user's mobile device. In case the user has multiple mobile devices, they should choose the one to proceed with. The client has to poll to the Orchestration SDK for authentication result while waiting for the user to complete the flow on their mobile device.

If the user successfully authenticates to approve the request, the journey sets the user context to the authenticated user and continues to the next step. Tokens generated for authentication can be accessed in subsequent steps using @policy.userTokens().

If it fails (e.g., the user couldn't authenticate in the mobile app or didn't do it within the push notification timespan), the journey proceeds to the failure branch (if specified); otherwise, the journey is aborted and an error is sent to the client. The step cannot complete sucessfully unless the user has authenticated in the mobile journey.

If the user doesn't have any registered devices, the journey proceeds to the no_registered_device branch, for example, to present a user with alternative authentication options.

Configuration

Field Description
External user ID User identifier in your system, specified as an expression.
Mobile journey A mobile approve journey to be executed by the mobile client.
Notification title An interpolated string containing title of the push notification. Can contain expressions. Only available in Google push notifications.
Notification text An interpolated string containing the main text of the push notification. Can contain expressions.
Client polling time Polling frequency, 2-5 seconds. By default, 3 seconds. To avoid rate limiting, the client shouldn't poll Orchestration SDK more frequently than every 2 seconds.
Timeout Interval in seconds, before authentication fails. By default, 300 seconds

Example

Suppose a form is used to collect user's email address. The input will be stored in a variable named clientData.

When invoked, the web to mobile authentication step obtains the username from the form output (clientData.email, etc.) and triggers Mosaic to send a push notification to a user's mobile device. The step keeps polling while the mobile approve journey is being executed on the user's mobile device. The mobile approve journey can access parameters specified in the Web to mobile authentication step using @policy.getMobileApproveParameters(). Once the user finishes the flow in the mobile app, the step is complete.

Web to mobile step settings in editor
Click to open the image in a dedicated tab.

Below is sample code for the client side to support the journey step logic:

Copy
Copied
function handleWebToMobileAuthentication(idoResponse) {
  // Check if devices are present in the idoResponse
  if (idoResponse.data.devices) {
    // If devices are present, handle device selection
    handleDeviceSelection(idoResponse);
  } else {
    // If devices are not present, handle polling
    handlePolling(idoResponse);
  }
}

function handleDeviceSelection(idoResponse) {
  const html = `
    <div>
      <h1>Select a device</h1>
      <select id="device_select">
        ${idoResponse.data.devices
          .map(
            (device) => `<option value="${device.code}">${device.name}</option>`
          )
          .join("")}
      </select>
      <button id="select_device_button">Continue</button>
    </div>
  `;

  document.body.innerHTML = html;

  document
    .querySelector("#select_device_button")
    .addEventListener("click", () => {
      const deviceCode = document.querySelector("#device_select").value;

      // Submit the selected device code to the SDK
      window.tsPlatform.ido.submitClientResponse(
        ClientResponseOptionType.ClientInput,
        {
          selected_device_code: deviceCode,
        }
      );
    });
}

function handlePolling(idoResponse) {
  const pollingInterval = idoResponse.data.polling_interval * 1000; // Convert seconds to milliseconds
  const resendAttemptsLeft = idoResponse.data.resend_attempts_left;

  const html = `
    <div>
      <h1>Waiting for Approval</h1>
      <p>Please approve the action on your mobile device.</p>
      <button id="cancel_button">Cancel</button>
      <button id="resend_button" ${
        resendAttemptsLeft === 0 ? "disabled" : ""
      }>Resend</button>
    </div>
  `;

  document.body.innerHTML = html;

  document.querySelector("#cancel_button").addEventListener("click", () => {
    // Submit the cancel response to the SDK
    window.tsPlatform.ido.submitClientResponse(ClientResponseOptionType.Cancel);
  });

  document.querySelector("#resend_button").addEventListener("click", () => {
    // Check if there are resend attempts left
    if (resendAttemptsLeft > 0) {
      // Submit the resend response to the SDK
      window.tsPlatform.ido.submitClientResponse(ClientResponseOptionType.Resend);
    }
  });

  setTimeout(() => {
    // Submit a response back to the SDK
    // As long as the mobile device has not approved, we will keep receiving the same idoResponse with polling data
    window.tsPlatform.ido.submitClientResponse(ClientResponseOptionType.ClientInput);
  }, pollingInterval);
}