Conditions
Conditions in Descope Flows allow you to create dynamic, branching authentication journeys based on user attributes, environmental factors, and/or authentication results. They act as decision points in your flow, determining which path a user should take next.
For example, you might want to:
- Require additional verification for high-risk users
- Show different screens based on the user's country
- Branch to different authentication methods based on the user's domain
- Skip certain steps for returning users
You can add conditions to your flow by dragging and dropping them in the flow builder. Each condition can evaluate multiple attributes and use different operators to create complex decision logic.
Using Conditions in Flows
If you want to use conditions in your authentication flow, you can follow these simple steps:
Add the Condition
Select the flow you want to edit in the Flows Tab of the Descope Console, and select the Blue + button in the top left corner:
![]()
Click on Condition, and a condition box will appear. Place this anywhere on the Flows panel and a popup will appear will all of the possible customizable options:
![]()
Design the Condition
To create a conditional statement, select which key you would like to use, along with the respective operator.
For example, in the case of "Is new user?", you will set key to authInfo.firstSeen, and operator to Is True. If that condition
is not met, we can conclude that the user already exists:
![]()
When you have multiple steps in your condition, you can change their evaluation order by dragging and dropping them in the condition editor.
Dynamic Fields
You can check keys for specific strings, integers, boolean values, location data, and more. The Operator and Value options will change depending on the key you wish to add a conditional statement for.
The following operators are available when creating conditions in your flows. The available operators will depend on the data type of the key you're evaluating.
Operators marked with "No" in the "Requires Value" column only evaluate the target value itself and don't need an additional comparison value.
| Operator | Description | Applicable Types | Requires Value |
|---|---|---|---|
| Equals | Determine if two values are equivalent | String, Number, IP Address | Yes |
| Doesn't Equal | Determine if two values are not equivalent | String, Number, IP Address | Yes |
| Contains | Determine if the target contains the predicate (supports both lists and strings) | String | Yes |
| Matches | Determine if the target matches the regex predicate | String | Yes |
| Greater Than | Determine if the target is greater than its predicate | Number | Yes |
| Greater Than or Equal | Determine if the target is greater than or equal to its predicate | Number | Yes |
| Less Than | Determine if the target is less than its predicate | Number | Yes |
| Less Than or Equal | Determine if the target is less than or equal to its predicate | Number | Yes |
| Is Empty | Determine if value is empty | String, IP Address | No |
| Is Not Empty | Determine if value is not empty | String, IP Address | No |
| Is True | Determine if value is true | Boolean | No |
| Is False | Determine if value is false | Boolean | No |
| In | Determine if value is in the array | String | Yes |
| Not In | Determine if value is not in the array | String | Yes |
| Is Email | Determine if value is a valid email address | String | No |
| Is Phone | Determine if value is a valid phone number | String | No |
| Within x hours ago | Determine if value is within x hours from now | Time | Yes |
| Within x days ago | Determine if value is within x days from now | Time | Yes |
| Within x minutes ago | Determine if value is within x minutes from now | Time | Yes |
| Over x hours ago | Determine if value is over x hours from now | Time | Yes |
| Over x days ago | Determine if value is over x days from now | Time | Yes |
| Over x minutes ago | Determine if value is over x minutes from now | Time | Yes |
| IP Address In | Determine if an IP address is within a list of ranges | String, IP Address | Yes |
| Is Approved Domain | Validate if domain is in the approved domain list | String | No |
| In Range | Determine if value is in range (requires min, max values) | Number | Yes |
| Not In Range | Determine if value is not in range (requires min, max values) | Number | Yes |
| Divided By | Determine if value is evenly divisible by predicate | Number | Yes |
For a full list of dynamic fields available, check out our dynamic values doc.
In this example, to check if a user is located in the US, we check if the geo.country key equals "US".
![]()
Use the Condition
Finally, you can take your conditional statements and add them to your flow by dragging arrows to and from the previous and next step, as shown below. In this example, if the user is new, they will be prompted to set up passkeys after authentication. If they are an existing user, they will proceed to the end of the flow:
![]()
Common Use cases
First Seen
A common use case for conditions is differentiating between new users and those already onboard. Refer to the design the condition step for implementation details.
User Roles
You can utilize user specific keys, like user roles, within a flow to handle users with different roles accordingly. In this example, we add MFA only for "Admin" users, since Admins typically have the ability to take higher-risk actions:
![]()
![]()
Authentication Methods
You can use conditions to check whether a certain authentication method has been used by the user. For example, you might want to prompt a user to use TOTP for MFA if they have it configured, and prompt them to use an OTP via SMS if not:
![]()
![]()
Adaptive MFA
Adaptive MFA dynamically adjusts authentication requirements during login attempts based on real-time risk factors. You can implement Adaptive MFA in your authentication flows using conditional logic and dynamic values. For details on setting this up, see our Adaptive MFA Guide.
IsEmail and IsPhone Handling
After prompting the user to enter their login Id, you can use a condition to check if it is an email or phone number. You can then use the result of the condition to call the corresponding authentication action. In this example, if the login Id is a phone number, we will send an OTP via SMS, and if the login Id is an email address, we will send the OTP via email.
![]()
![]()
Check for Disabled Users
You can check for disabled users using the unauthUser.status key, and present a customized screen accordingly.
![]()
![]()
Check for Approved Domain
For use cases where you need to validate if a given domain is in the approved domain list, Descope supports "is Approved Domain" operator in a flow condition. This operator will check against the approved domain list within the project settings. This is usually helpful in scenarios where a malicious user could potentially manipulate the current hostname using browser injection techniques which could inturn be used to send embedded links (or other types) with a fraudulent URL. This operator ensures that the current domain matches against the trusted domains for the project.
![]()
Access External Cookies
Users can access non-Descope cookies on the same domain within a flow. In flow conditions, a cookie can be accessed using the cookies.<name> key, where <name> represents the cookie's name.
![]()