Bring Your Own Screen
When using Flows, you can use Descope's Bring Your Own Screen (BYOS) functionality if you want to utilize your own custom screens. This allows you to maintain complete control over the UI while still leveraging the logic of Descope flows.
Warning
Using custom screens (Bring Your Own Screens) means giving up the flexibility of Descope flows — including the ability to update authentication logic and UI without redeploying code. We only recommend BYOS in exceptional cases, such as strict compliance needs or deeply embedded native experiences.
Overview
Bring Your Own Screen works by:
- Using the Descope web component
- Implementing the
onScreenUpdate
callback to handle screen transitions - Rendering your custom components based on the current screen name
- Managing the required inputs and outputs of each screen
Critical Concepts
When implementing BYOS, the most important aspects to get right are:
-
Interaction IDs
- Each next step in your flow has a unique Interaction ID, often tied to a button or a state change
- These IDs are required to proceed to the next step in the flow
-
Inputs and Outputs
- Each screen expects specific inputs from the previous screen
- Each screen produces specific outputs for the next screen
- These must match exactly what the flow expects
-
Screen Names
- Each screen has a name found and modified from the screen editor
- Each screen in your flow must have a unique name
To find the Interaction IDs, Inputs, and Outputs for each screen, you can expand the screen details within the flow builder.
The Interaction IDs can be seen on the screen widget, and the expected inputs and outputs of the screen can be seen in the expanded details on the right.
Each step has an automatically generated unique Interaction ID. You can choose to modify it from the screen editor itself.
Warning
It is very important to rename your Interaction IDs to something unique and easy to reuse. This will allow you to more easily make changes to your flow without having to redeploy your code every time.
The screen name can also be seen and modified from the screen editor.
Warning
It is extremely important to rename your screen names so that within a flow they are all unique. If your screen names are not unique, you will run into conflicts, and be unable to properly run your flow.
Implementation Walkthrough
We'll use a simple example to illustrate how this works. Instead of showing the original "Welcome Screen" from our "sign-up-or-in" flow, we will show a custom "Welcome Screen" component:
Key Components
These are the key components to the example above:
-
Descope Component:
flowId
: Specifies which flow to useonScreenUpdate
: Callback that determines when to use custom screensonSuccess
: Handles successful authentication
-
Custom Screen Components:
- Can be any custom component
- Receive props to:
- Update and use form values
- Handle user actions
- Display errors
- Contain event handlers to define when to proceed to the next step in the flow
-
State Management:
state
: Contains the flow state, including the screen name, errors, and the next functionform
: Manages form datanext
: Function to proceed to the next screen
Within the Descope component, we check if the current state's "Screen Name" matches the name of a screen we want to replace. If it does, we show our custom screen component instead of the default one. The custom screen component must implement all required inputs and outputs, as shown below.
Custom Screen Implementation
Here's an example of a custom screen component:
The form
object maintains state throughout your flow, collecting and passing data between screens and actions. Each screen receives the current form values and can update them using the onFormUpdate
function.
In this example, any change in the email input box on the custom screen updates the form object:
Note
Each screen must update the form with all values listed in the "Outputs" section of that screen in the Descope flow builder. These outputs are required for the next steps in your flow to function correctly.
When the user clicks on the "Continue" button in the custom screen, the onClick
handler is triggered.
The onClick
handler calls the state.next()
function, passing in the interaction-id
, in this case "sign-up-or-in", corresponding to that button in the flow. We also pass in the form
object, so that
the email and any other updated values are available in the next step of the flow.
Error Handling
When implementing custom screens, you can access error information through the state
object passed to your component. The state
object contains an error
property that provides details about any errors that occur during the flow execution.
The error object contains the following fields:
Field | Description | Example |
---|---|---|
code | A unique error code that identifies the specific error type | "E011003" |
text | A high-level error message that describes the general error category | "Failed to sign up or in" |
description | A more detailed explanation of what went wrong | "Request is invalid" |
message | The specific reason for the error | "The loginId field is required" |
You can handle errors by either showing all errors in your screen, like in the example screen above, or by handling errors with more granularity.
For example, if an OTP sent to the user has expired, within your custom screen you can call a function to handle the resend of the OTP:
Within the flow component, we handle the onResendClick() event by proceeding to the step where the resend
Interaction Id points
For a full list of common errors that are included in the error object, see our Common Errors doc.
Note
Input validation must be handled within your custom screen component. The error object passed through the state only contains flow-level errors and does not include input validation errors. You'll need to implement your own validation logic for form inputs.
Best Practices
- Keep your custom components focused and reusable
- Handle errors appropriately using the provided error state
- Maintain consistent styling with your application
- Use the
next
function to pass all required data to the next screen - Test thoroughly to ensure proper flow progression
The most common issues when implementing BYOS are:
- Using incorrect interaction IDs
- Missing required inputs
- Providing inputs in the wrong format
- Not handling all required outputs
Always verify these in the Descope Console before implementing your custom screens.
Security Considerations
- Never expose sensitive data in the UI
- Validate all user inputs
Sample App
For a complete working example of Bring Your Own Screen, check out the BYOS Sample App.