[[_authentication-flows]] === Authentication flows An _authentication flow_ is a container of authentications, screens, and actions, during log in, registration, and other {project_name} workflows. To view all the flows, actions, and checks, each flow requires: .Procedure . Click *Authentication* in the menu. . Click the *Flows* tab. ==== Built-in flows {project_name} has several built-in flows. You cannot modify these flows, but you can alter the flow's requirements to suit your needs. In the drop-down list, select *browser* to display the Browser Flow screen. .Browser flow image:{project_images}/browser-flow.png[Browser Flow] Hover over the question-mark tooltip of the drop-down list to view a description of the flow. Two sections exist. ===== Auth type The name of the authentication or the action to execute. If an authentication is indented, it is in a sub-flow. It may or may not be executed, depending on the behavior of its parent. . Cookie + The first time a user logs in successfully, {project_name} sets a session cookie. If the cookie is already set, this authentication type is successful. Since the cookie provider returned success and each execution at this level of the flow is _alternative_, {project_name} does not perform any other execution. This results in a successful login. . Kerberos + This authenticator is disabled by default and is skipped during the Browser Flow. . Identity Provider Redirector + This action is configured through the *Actions* > *Config* link. It redirects to another IdP for <<_identity_broker, identity brokering>>. . Forms + Since this sub-flow is marked as _alternative_, it will not be executed if the *Cookie* authentication type passed. This sub-flow contains an additional authentication type that needs to be executed. {project_name} loads the executions for this sub-flow and processes them. The first execution is the *Username Password Form*, an authentication type that renders the username and password page. It is marked as _required_, so the user must enter a valid username and password. The second execution is the *Browser - Conditional OTP* sub-flow. This sub-flow is _conditional_ and executes depending on the result of the *Condition - User Configured* execution. If the result is true, {project_name} loads the executions for this sub-flow and processes them. The next execution is the *Condition - User Configured* authentication. This authentication checks if {project_name} has configured other executions in the flow for the user. The *Browser - Conditional OTP* sub-flow executes only when the user has a configured OTP credential. The final execution is the *OTP Form*. {project_name} marks this execution as _required_ but it runs only when the user has an OTP credential set up because of the setup in the _conditional_ sub-flow. If not, the user does not see an OTP form. ===== Requirement A set of radio buttons that control the execution of an action executes. [[_execution-requirements]] ====== Required All _Required_ elements in the flow must be successfully sequentially executed. The flow terminates if a required element fails. ====== Alternative Only a single element must successfully execute for the flow to evaluate as successful. Because the _Required_ flow elements are sufficient to mark a flow as successful, any _Alternative_ flow element within a flow containing _Required_ flow elements will not execute. ====== Disabled The element does not count to mark a flow as successful. ====== Conditional This requirement type is only set on sub-flows. * A _Conditional_ sub-flow contains executions. These executions must evaluate to logical statements. * If all executions evaluate as _true_, the _Conditional_ sub-flow acts as _Required_. * If all executions evaluate as _false_, the _Conditional_ sub-flow acts as _Disabled_. * If you do not set an execution, the _Conditional_ sub-flow acts as _Disabled_. * If a flow contains executions and the flow is not set to _Conditional_, {project_name} does not evaluate the executions, and the executions are considered functionally _Disabled_. ==== Creating flows Important functionality and security considerations apply when you design a flow. To create a flow, perform the following: .Procedure . Click *Authentication* in the menu. . Click *New*. [NOTE] ==== You can copy and then modify an existing flow. Select a flow, click *Copy*, and enter a name for the new flow. ==== When creating a new flow, you must create a top-level flow first with the following options: Alias:: The name of the flow. Description:: The description you can set to the flow. Top-Level Flow Type:: The type of flow. The type *client* is used only for the authentication of clients (applications). For all other cases, choose *generic*. .Create a top-level flow image:{project_images}/Create-top-level-flow.png[Top Level Flow] When {project_name} has created the flow, {project_name} displays the *Delete*, *Add execution*, and *Add flow* buttons. .An empty new flow image:{project_images}/New-flow.png[New Flow] Three factors determine the behavior of flows and sub-flows. * The structure of the flow and sub-flows. * The executions within the flows * The requirements set within the sub-flows and the executions. Executions have a wide variety of actions, from sending a reset email to validating an OTP. Add executions with the *Add execution* button. Hover over the question mark next to *Provider*, to see a description of the execution. .Adding an authentication execution image:{project_images}/Create-authentication-execution.png[Adding an Authentication Execution] Two types of executions exist, _automatic executions_ and _interactive executions_. _Automatic executions_ are similar to the *Cookie* execution and will automatically perform their action in the flow. _Interactive executions_ halt the flow to get input. Executions executing successfully set their status to _success_. For a flow to complete, it needs at least one execution with a status of _success_. You can add sub-flows to top-level flows with the *Add flow* button. The *Add flow* button displays the *Create Execution Flow* page. This page is similar to the *Create Top Level Form* page. The difference is that the *Flow Type* can be *generic* (default) or *form*. The *form* type constructs a sub-flow that generates a form for the user, similar to the built-in *Registration* flow. Sub-flows success depends on how their executions evaluate, including their contained sub-flows. See the <<_execution-requirements, execution requirements section>> for an in-depth explanation of how sub-flows work. [NOTE] ==== After adding an execution, check the requirement has the correct value. ==== All elements in a flow have a *Delete* option in the *Actions* menu. This action removes the element from the flow. Executions have a *Config* menu option to configure the execution. It is also possible to add executions and sub-flows to sub-flows with the *Add execution* and *Add flow* menu options. Since the order of execution is important, you can move executions and sub-flows up and down within their flows using the up and down buttons beside their names. [WARNING] ==== Make sure to properly test your configuration when you configure the authentication flow to confirm that no security holes exist in your setup. We recommend that you test various corner cases. For example, consider testing the authentication behavior for a user when you remove various credentials from the user's account before authentication. As an example, when 2nd-factor authenticators, such as OTP Form or WebAuthn Authenticator, are configured in the flow as REQUIRED and the user does not have credential of particular type, the user will be able to setup the particular credential during authentication itself. This situation means that the user does not authenticate with this credential as he setup it right during the authentication. So for browser authentication, make sure to configure your authentication flow with some 1st-factor credentials such as Password or WebAuthn Passwordless Authenticator. ==== ==== Creating a password-less browser login flow To illustrate the creation of flows, this section describes creating an advanced browser login flow. The purpose of this flow is to allow a user a choice between logging in using a password-less manner with <<_webauthn, WebAuthn>>, or two-factor authentication with a password and OTP. .Procedure . Click *Authentication* in the menu. . Click the *Flows* tab. . Click *New*. . Enter `Browser Password-less` as an alias. . Click *Save*. . Click *Add execution*. . Select *Cookie* from the drop-down list. . Click *Save*. . Click *Alternative* for the *Cookie* authentication type to set its requirement to alternative. . Click *Add execution*. . Select *Kerberos* from the drop-down list. . Click *Add execution*. . Select *Identity Provider Redirector* from the drop-down list. . Click *Save*. . Click *Alternative* for the *Identity Provider Redirector* authentication type to set its requirement to alternative. . Click *Add flow*. . Enter *Forms* as an alias. . Click *Save*. . Click *Alternative* for the *Forms* authentication type to set its requirement to alternative. + .The common part with the browser flow image:images/Passwordless-browser-login-common.png[] + . Click *Actions* for the *Forms* execution. . Select *Add execution*. . Select *Username Form* from the drop-down list. . Click *Save*. . Click *Required* for the *Username Form* authentication type to set its requirement to required. At this stage, the form requires a username but no password. We must enable password authentication to avoid security risks. . Click *Actions* for the *Forms* sub-flow. . Click *Add flow*. . Enter `Authentication` as an alias. . Click *Save*. . Click *Required* for the *Authentication* authentication type to set its requirement to required. . Click *Actions* for the *Authentication* sub-flow. . Click *Add execution*. . Select *Webauthn Passwordless Authenticator* from the drop-down list. . Click *Save*. . Click *Alternative* for the *Webauthn Passwordless Authenticator* authentication type to set its requirement to alternative. . Click *Actions* for the *Authentication* sub-flow. . Click *Add flow*. . Enter `Password with OTP` as an alias. . Click *Save*. . Click *Alternative* for the *Password with OTP* authentication type to set its requirement to alternative. . Click *Actions* for the *Password with OTP* sub-flow. . Click *Add execution*. . Select *Password Form* from the drop-down list. . Click *Save*. . Click *Required* for the *Password Form* authentication type to set its requirement to required. . Click *Actions* for the *Password with OTP* sub-flow. . Click *Add execution*. . Select *OTP Form* from the drop-down list. . Click *Save*. . Click *Required* for the *OTP Form* authentication type to set its requirement to required. Finally, change the bindings. . Click the *Bindings* tab. . Click the *Browser Flow* drop-down list. . Select *Browser Password-less* from the drop-down list. . Click *Save*. .A password-less browser login image:images/Passwordless-browser-login.png[] After entering the username, the flow works as follows: If users have WebAuthn passwordless credentials recorded, they can use these credentials to log in directly. This is the password-less login. The user can also select *Password with OTP* because the `WebAuthn Passwordless` execution and the `Password with OTP` flow are set to *Alternative*. If they are set to *Required*, the user has to enter WebAuthn, password, and OTP. If the user selects the *Try another way* link with `WebAuthn passwordless` authentication, the user can choose between `Password` and `Security Key` (WebAuthn passwordless). When selecting the password, the user will need to continue and log in with the assigned OTP. If the user has no WebAuthn credentials, the user must enter the password and then the OTP. If the user has no OTP credential, they will be asked to record one. [NOTE] ==== Since the WebAuthn Passwordless execution is set to *Alternative* rather than *Required*, this flow will never ask the user to register a WebAuthn credential. For a user to have a Webauthn credential, an administrator must add a required action to the user. Do this by: . Enabling the *Webauthn Register Passwordless* required action in the realm (see the <<_webauthn,WebAuthn>> documentation). . Setting the required action using the *Credential Reset* part of a user's xref:ref-user-credentials_{context}[Credentials] management menu. Creating an advanced flow such as this can have side effects. For example, if you enable the ability to reset the password for users, this would be accessible from the password form. In the default `Reset Credentials` flow, users must enter their username. Since the user has already entered a username earlier in the `Browser Password-less` flow, this action is unnecessary for {project_name} and sub-optimal for user experience. To correct this problem, you can: * Copy the `Reset Credentials` flow. Set its name to `Reset Credentials for password-less`, for example. * Select *Delete* in the *Actions* menu of the *Choose user* execution. * In the *Bindings* menu, change the reset credential flow from *Reset Credentials* to *Reset Credentials for password-less* ==== [[_step-up-flow]] ==== Creating a browser login flow with step-up mechanism This section describes how to create advanced browser login flow using the step-up mechanism. The purpose of step-up authentication is to allow access to clients or resources based on a specific authentication level of a user. .Procedure . Click *Authentication* in the menu. . Click the *Flows* tab. . Click *New*. . Enter `Browser Incl Step up Mechanism` as an alias. . Click *Save*. . Click *Add execution*. . Select *Cookie* from the item list. . Click *Save*. . Click *Alternative* for the *Cookie* authentication type to set its requirement to alternative. . Click *Add flow*. . Enter *Auth Flow* as an alias. . Click *Save*. . Click *Alternative* for the *Auth Flow* authentication type to set its requirement to alternative. Now you configure the flow for the first authentication level. . Click *Actions* for the *Auth Flow*. . Click *Add flow*. . Enter `1st Condition Flow` as an alias. . Click *Save*. . Click *Conditional* for the *1st Condition Flow* authentication type to set its requirement to conditional. . Click *Actions* for the *1st Condition Flow*. . Click *Add execution*. . Select *Conditional - Level Of Authentication* from the item list. . Click *Save*. . Click *Required* for the *Conditional - Level Of Authentication* authentication type to set its requirement to required. . Click *Actions* for the *Conditional - Level Of Authentication*. . Click *Config*. . Enter `Level 1` as an alias. . Enter `1` for the Level of Authentication (LoA). . Set Store LoA in user session *ON*. . Click *Save* + .Configure the condition for the first authentication level image:images/authentication-step-up-condition-1.png[] . Click *Actions* for the *1st Condition Flow*. . Click *Add execution*. . Select *Username Password Form* from the item list. . Click *Save*. . Click *Required* for the *Username Password Form* authentication type to set its requirement to required. Now you configure the flow for the second authentication level. . Click *Actions* for the *Auth Flow*. . Click *Add flow*. . Enter `2nd Condition Flow` as an alias. . Click *Save*. . Click *Conditional* for the *2nd Condition Flow* authentication type to set its requirement to conditional. . Click *Actions* for the *2nd Condition Flow*. . Click *Add execution*. . Select *Conditional - Level Of Authentication* from the item list. . Click *Save*. . Click *Required* for the *Conditional - Level Of Authentication* authentication type to set its requirement to required. . Click *Actions* for the *Conditional - Level Of Authentication*. . Click *Config*. . Enter `Level 2` as an alias. . Enter `2` for the Level of Authentication (LoA). . Set Store LoA in user session *OFF*. . Click *Save* + .Configure the condition for the second authentication level image:images/authentication-step-up-condition-2.png[] . Click *Actions* for the *2nd Condition Flow*. . Click *Add execution*. . Select *OTP Form* from the item list. . Click *Save*. . Click *Required* for the *OTP Form* authentication type to set its requirement to required. Finally, change the bindings. . Click the *Bindings* tab. . Click the *Browser Flow* item list. . Select *Browser Incl Step up Mechanism* from the item list. . Click *Save*. .Browser login with step-up mechanism image:images/authentication-step-up-flow.png[] .Request a certain authentication level To use the step-up mechanism, you have to specify a requested level of authentication (LoA) in your authentication request. The claims parameter is used for this purpose: [source] ---- https://{DOMAIN}/auth/realms/{REALMNAME}/protocol/openid-connect/auth?client_id={CLIENT-ID}&redirect_uri={REDIRECT-URI}&scope=openid&response_type=code&response_mode=query&nonce=exg16fxdjcu&claims=%7B%22id_token%22%3A%7B%22acr%22%3A%7B%22essential%22%3Atrue%2C%22values%22%3A%5B%22gold%22%5D%7D%7D%7D ---- The claims parameter is specified in a JSON representation: [source] ---- claims= { "id_token": { "acr": { "essential": true, "values": ["gold"] } } } ---- NOTE: To request the acr_vale as text (such as `gold`) instead of a numeric value, you have to configure the mapping between the ACR and the LoA at the client level. For configuration see <<_mapping-acr-to-loa,ACR to LoA Mapping>>) For more details see the https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics[official OIDC specification]. .Flow logic The logic for the previous configured authentication flow is as follows: + If a client request a high authentication level, meaning Level of Authentication 2 (LoA 2), a user has to perform full 2-factor authentication: Username/Password + OTP. However, if a user already has a session in Keycloak, that was logged in with username and password (LoA 1), the user is only asked for the second authenticaton factor (OTP). The *option in the condition to store the achieved LoA in the user session* determines wheather the user will be asked to present the authentication factor again during a subsequent authentication. If true, the user will not be re-authenticated with this level during subsequent authentication. If false, it means that subsequent authentications will re-authentication with that level again. This is useful for operations that require higher security in the application (e.g. send payment) and always require authentication with the specific level. .Implications about possible acr inputs in authentication request [cols="2",options="header"] |=== | Authentication Request | Implication | *No acr claim* is requested | Minimum authentication (*1st Condition Flow*) is executed | *No essential claim* is requested in the acr claim | Default is *false* | *Unknown acr* value is requested | If essential false, minimum authentication is executed. If essential true, the outcome is a failed authentication attempt | User is re-authenticated via a *cookie* | Acr value in access token und ID token is `0` |=== NOTE: A conflict situation may arise when an admin specifies several flows, sets different LoA levels to each, and assigns the flows to different clients. However, the rule is always the same: if a user has a certain level, it needs only have that level to connect to a client. It's up to the admin to make sure that the LoA is coherent. ifeval::[{project_community}==true] === Script Authenticator Ability to upload scripts through the Admin Console and REST endpoints is deprecated. For more details see link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}]. endif::[]