# Risk Recommendation

div
div
Client SDK
div
Mobile approve
div
SSO
div
Sub-journey
> Branches the journey according to risk recommendation obtained from Fraud Prevention


## Description

This step is used to obtain risk recommendations so you can detect and respond to real-time risk. For example, this allows you to request additional verification when bots are detected during account opening or to step up authentication when a user is trying to login from a suspicious device or location.

Use this step before the user performs a sensitive action in order to detect risk and help you decide how to respond. The journey automatically evaluates the risk and proceeds to the appropriate branch based on the recommendation (either trust, allow, challenge, or deny). If defined, an output variable will store the risk recommendation result. In addition to a recommendation itself (allow, trust, deny, or challenge), the result includes more details such as risk score, reasons, and device details. This data can be used in subsequent journey steps in the expression fields (e.g., `account_protection_result.recommendation`) or as a part of an interpolated string (e.g., `You're using ${account_protection_result.context.browser_name}`).

Risk recommendations are provided by Mosaic's [Fraud Prevention](/guides/risk/overview) based on telemetry streamed by the client. It includes device, network, and other context data used to continuously assess risk. For Web, Fraud Prevention functionality is bundled with Journeys in the same [SDK](/sdk-ref/platform/introduction). For mobile apps, use a dedicated SDK: [Fraud Prevention SDK (iOS)](https://transmitsecurity.github.io/accountprotection-ios-sdk-docs/documentation/accountprotection/) or [Fraud Prevention SDK (Android)](https://transmitsecurity.github.io/accountprotection-android-sdk/).

Note
* Make sure Fraud Prevention is configured to work in the same region as other Mosaic services.
* For details on how to set up and initialize the Fraud Prevention SDK for mobile apps, see Steps 2 & 3 of [Android quickstart](/guides/risk/quick_start_android) or [iOS quickstart](/guides/risk/quick_start_ios). If the Fraud Prevention SDK is not initialized, the step fails with an `sdk_not_initialized` error.


## Configuration

div
| **Field** | **Description** |
|  --- | --- |
| **Action Type** | Specifies the action being evaluated for risk, such as `login`, `transaction`, or `password_reset`. A full list is available [here](/guides/risk/recommendations/#action-types). |
| **User auth state** | Indicates if the user has authenticated in this journey. If the user is authenticated (default), the user context is provided implicitly by the journey. If not, a user identifier must be configured. |
| **Identifiers** | Only configured if the journey doesn't authenticate the user before invoking this step. Can be an external user ID, email, phone number, username, or a [custom identifier](/guides/user/manage_user_schema), if configured for B2C users in your tenant. |
| **Output Variable** | Name of the variable used to store the result data from the completed step, which can be used in subsequent journey steps. Default is **account_protection_result**. The object has the structure that's described [here](/openapi/risk/recommendations.openapi/other/getriskrecommendation#other/getriskrecommendation/response&c=200). In addition to a recommendation itself (allow, trust, deny, or challenge), it includes more details such as risk score, reasons, and device details. |
| **Error Behavior** | Determines the behavior in case an unexpected error occurs during the process. You can choose to either abort the journey (default) or handle errors using a dedicated error branch. |


## Example

In our example, the user attempts to login with their credentials. This step obtains a risk recommendation for the login event and defines how to proceed with the journey. For example:

- **Trust**/**Allow**: The login is successful, and the journey proceeds to the Complete Journey step.
- **Challenge**: The user must complete an additional authentication step (e.g., an Email OTP Authentication) before proceeding.
- **Deny**: The login attempt is rejected, and the journey moves to the Reject Access step.


![](/assets/risk_recommendation.e4ffd161b967d996f3d8d349d241e66e288c5b3adae58af53117f000f34e2719.6f9096f8.png)

When executed, this step sends a callback to the client with the IDO service response object. It will have the `journeyStepId` set to `drsTriggerAction` and the `data` will include the `action_type` set to `login`. The client uses the data received from the Orchestration SDK as an input for Fraud Prevention SDK and triggers an action with the Fraud Prevention SDK. Having received the action token from the Fraud Prevention SDK, the client submits it to the journey using the Orchestration SDK call in order for the journey to fetch a recommendation and proceed accordingly.

Once the user is fully-authenticated, it is recommended to report the action result and set the user for all subsequent events in the device session. This is done by adding "Client Actions: Report action result API" step after the "Risk recommendation" and submitting the `action_token` and `user_id`.

JavaScript

```js
async function handleRiskRecommendations(idoResponse) {
  const correlationId = idoResponse.data.correlation_id;
  const claimedUserId = idoResponse.data.user_id;
  const actionType = idoResponse.data.action_type;

  // Triggers an action event using the SDK
  // If SDK was loaded via script tag, invoke functions inside 'window.tsPlatform'
  const { actionToken } = await drs.triggerActionEvent(actionType, {
    correlationId,
    claimedUserId,
  });

  const data = { action_token: actionToken };

  // Submits an action token to the journey using the Orchestration SDK
  // If SDK was loaded via script tag, invoke functions inside 'window.tsPlatform'
  await ido.submitClientResponse(ClientResponseOptionType.ClientInput, data);
}
```

Swift

```swift
do {
    // Initializes the Fraud Prevention SDK
    try TSAccountProtection.initializeSDK { result in
        switch result {
        case .success:
            guard let actionType = idoResponse.data["action_type"] as? String else { return }
            let correlationId = idoResponse.data["correlation_id"] as? String
            let claimedUserId = idoResponse.data["user_id"] as? String

            // Triggers an action event using the Fraud Prevention SDK
            TSAccountProtection.triggerAction(actionType) { result in
                switch result {
                case .success(let response):
                    debugPrint("[DEBUG] Fraud Prevention access token: \(response.actionToken)")

                    // Submits an action token to the journey using the Orchestration SDK
                    do {
                        try TSIdo.submitClientResponse(clientResponseOptionId: .clientInput,
                                                       data: ["action_token": response.actionToken])
                    } catch {
                        debugPrint("[DEBUG] Failed to submit action token: \(error)")
                    }
                case .failure(let error):
                    debugPrint("[DEBUG] Trigger action error: \(error)")
                    do {
                        try TSIdo.submitClientResponse(clientResponseOptionId: .fail)
                    } catch {
                        debugPrint("[DEBUG] Failed to submit failure response: \(error)")
                    }
                }
            }
        case .failure(let error):
            debugPrint("[DEBUG] Initialize Fraud Prevention SDK error: \(error)")
        }
    }
} catch {
    debugPrint("[DEBUG] SDK Initialization error: \(error)")
}
```

Kotlin

```kotlin
data class DrsActionToken(val action_token: String)
...
private fun triggerActionAndSubmit(serviceResponse: TSIdoServiceResponse) {
    val actionType = (serviceResponse.data as JSONObject).optString(“action_type”)
    if (!action.isNullOrEmpty()) {
           // Triggers an action event using the Fraud Prevention SDK
           TSAccountProtection.triggerAction(actionType, object :
               ITransmitSecurityTriggerActionEventCallback {
               override fun onResponse(transmitSecurityTriggerActionResponse: TransmitSecurityTriggerActionResponse) {
                   val token= transmitSecurityTriggerActionResponse.token();
                   // Submits an action token to the journey using the Orchestration SDK
                   TSIdo.submitClientResponse(TSIdoClientResponseOptionType.ClientInput.type, DrsActionToken(token), callback)
               }
               override fun onFailed(error: TransmitSecurityAccountProtectionError) {
                   //TODO: Handle error
               }
           })
    }
}
```

The risk recommendation is stored in the output variable (default: `account_protection_result`) and can be used in subsequent steps to determine security policies dynamically.