For a flow to be evaluated as successful, all required elements in the flow must evaluate as successful. This means that all _Required_ elements in the flow
must be sequentially executed, from top to bottom, unless one of the elements causes the flow to fail. However, this is only true for the current flow.
This requirement type can only be set on sub-flows. A _Conditional_ sub-flow can contain a "Condition" execution. These "Condition" executions must evaluate as
logical statements. If all "Condition" executions evaluate as _true_ then the _Conditional_ sub-flow acts as _Required_. If not, the _Conditional_ sub-flow
acts as _Disabled_. If no "Condition" execution is set, the _Conditional_ sub-flow acts as _Disabled_. If a flow contains "Condition" executions and is not set to
_Conditional_, the "Condition" executions are not evaluated, and can be considered functionally _Disabled_.
If this cookie has already been set, then this authentication type is successful. In this case,
since the cookie provider returned success and each execution at this level of the flow is _alternative_, no other execution is executed and this results in a successful login.
. The second execution of the flow looks at the `Kerberos` execution. This authenticator is disabled by default and will be skipped.
. The third execution is the `Identity Provider Redirector`. It can be configured through the `Actions` > `Config` link to automatically redirect to another IdP for <<_identity_broker, identity brokering>>.
. The next execution is a sub-flow called `Forms`. Since this sub-flow is marked as _alternative_ it will not be executed if the `Cookie` authentication type passed.
This sub-flow contains additional authentication type that needs to be executed.
The executions for this sub-flow are loaded and the same processing logic occurs.
. The second execution in the Forms sub-flow is a new sub-flow: the `Browser - Conditional OTP` sub-flow. Since this sub-flow is _conditional_, whether it is executed depends on the result of the
evaluation of the `Condition - User Configured` execution. If it is, the executions for this sub-flow are loaded and the same processing logic occurs
. The next execution is the `Condition - User Configured`. This checks if the other executions in the flow are configured for the user.
Meaning that the `Browser - Conditional OTP` sub-flow will only be executed if the user has an OTP credential configured.
. The final execution is the `OTP Form`. This is marked as _required_, but because of the setup in the _conditional_ subflow, it will only be run if the user
has an OTP credential set up. If he doesn't, the user will not see an OTP form.
==== Creating flows
This section explains in greater depth how flows work, and how to create your own flows. Note that there are important functionality and security
considerations when designing your own flow. A badly created flow could either let no one log in, let users in with less verification than you would
Once the flow is created, in addition to the `New` and `Copy` buttons, you now have, `Delete`, `Add execution` and `Add flow`.
.An empty new flow
image:{project_images}/New-flow.png[]
What a flow finally does is determined by the structure of the flow and sub-flows, the executions in those flows, and the requirements set on the
sub-flows and the executions.
Executions can be added with the `Add execution` button. Executions can have a wide variety of actions, from sending a reset email to validating an OTP. If you hover over the
tooltip (the tiny question mark) next to `Provider`, this will describe what the execution does.
These can be divided into _automatic executions_ and _interactive executions_. _Automatic executions_ are similar to the `Cookie` execution, and will automatically
perform their action when they are encountered in the flow. _Interactive executions_ will halt the flow, usually to get some user input. Executions that execute
successfully will get the _success_ status. This is important, because this is part of whether a flow is successful or not. For example, an empty `Browser` flow
would not allow anyone to log in. For that it would need at least one execution that successfully evaluates, for example a `Username Password Form` that is correctly
Sub-flows can be added in top level flow with the `Add flow` button, which opens a `Create Execution Flow` page that is very similar to the `Create Top Level Form`
page. The only difference is that the `Flow Type` can be either `generic` (like before), or `form`. The `form` type is used to construct a sub-flow that generates
a single form for the user, like what is done for the built-in `Registration` flow. Sub-flows are a special type of execution that evaluate as successful
depending on how the executions they contain evaluate (and this includes the evaluation of their contained sub-flows). And the logic of this evaluation
depends on the Requirement of each execution and sub-flow.
Note that after adding an execution, you should check that the Requirement is set to the correct value. Even if there is only a single possible Requirement, it
can happen that it is not set.
When constructing a flow, all elements added to the flow will have an `Actions` menu on the right-hand side. All elements added to the flow have a `Delete`
option in this menu to remove it from the flow. Executions can contain a `Config` menu option to configure the execution, as is the case for the
`Identity Provider Redirector`. Sub-flows can also have executions and sub-flows added to them, with their `Add execution` and `Add flow` menu options.
Finally, since the order of execution is important, you can move executions and sub-flows up and down within their respective flows with the up and down buttons
that are set to left of their name.
==== Creating a password-less browser login flow
To illustrate the creation of flows, this section describes the creation of a more advanced browser login flow. The purpose of this flow is to allow a
user to choose between logging in in a password-less manner using <<_webauthn, WebAuthn>>, and a two-factor authentication with password and OTP.
The flow to create is similar to the standard browser login, but diverges when reaching the username selection. Instead of copying the flow however, you'll be
creating the flow from the start:
* Select a realm, click on Authentication link
* Select "new", and give the new flow a distinctive Alias, i.e. "Browser Password-less"
* Select "Add execution", and using the drop-down select "Cookie". After pressing "Save", set its Requirement to _Alternative_.
* Select "Add execution", and using the drop-down select "Kerberos".
* Select "Add execution", and using the drop-down select "Identity Provider Redirector". After pressing "Save", set its Requirement to _Alternative_.
* Select "Add flow", and choose an representative Alias, e.g. "Forms". After pressing "Save", set its Requirement to _Alternative_.
The Username form is similar to "Browser" flow's Username Password Form, but only asks for a username, allowing a user to perform a password-less login.
However, note that this inevitably allows a user enumeration attack on your {project_name} server. This is an unavoidable security risk for the convenience,
so the flow should make sure that an attacker cannot just have to guess a password to be able to enter.
* Using the `Actions` menu on the right-hand side of the "Forms" subflow, select "Add flow". Choose an representative Alias, e.g. "Authentication".
After pressing "Save", set its Requirement to _Required_.
* Using the `Actions` menu on the right-hand side of the "Authentication" subflow, select "Add execution". Using the drop-down select
* Using the `Actions` menu on the right-hand side of the "Authentication" subflow, select "Add flow". Choose an representative Alias, e.g. "Password with OTP".
After pressing "Save", set its Requirement to _Alternative_.
* Using the `Actions` menu on the right-hand side of the "Password with OTP" subflow, select "Add execution". Using the drop-down select
"Password Form". After pressing "Save", set its Requirement to Required.
* Using the `Actions` menu on the right-hand side of the "Password with OTP" subflow, select "Add execution". Using the drop-down select
"OTP Form". After pressing "Save", set its Requirement to Required.
* In the "Bindings" menu, change the browser flow from "Browser" to "Browser Password-less"
The final flow that is produced is the following:
.A password-less browser login
image:images/Passwordless-browser-login.png[]
After entering the username, the way this flow works is the following:
* If the user has any WebAuthn passwordless credentials recorded, that user will be able to use any of them to log in directly. This is the password-less login.
The user can instead select "Password with OTP". The user can do this because the "WebAuthn Passwordless" execution and the "Password with OTP"
It is important to note that since the WebAuthn Passwordless execution is set to _Alternative_ instead of _Required_, this flow will never ask the user to register a WebAuthn credential. For a user
to have a Webauthn credential, that user must have a required action added by an administrator. This is done first by making sure that the `Webauthn Register Passwordless`
required action is enabled in the realm (see the <<_webauthn,WebAuthn>> documentation), and then by setting the required action by using the `Credential Reset` part of a
Creating a more advanced flow such as this one can have some subtle side effects. For example, if you were to enable the ability to reset the password
for the user, then this would be accessible from the password form. In the default "Reset Credentials" flow, the user has to enter his username. Since
he's already entered his username earlier in the "Browser Password-less" flow, this would be unnecessary for {project_name}, and a sub-optimal in terms of user
experience. To correct this, you could:
* Copy the "Reset Credentials" flow, setting its name to, for example "Reset Credentials for password-less"
* Use the `Actions` menu on the right-hand side of the "Choose user" execution, select "Delete"
* In the "Bindings" menu, change the reset credential flow from "Reset Credentials" to "Reset Credentials for password-less"