diff --git a/authui/src/authflowv2/botprotection/botProtection.ts b/authui/src/authflowv2/botprotection/botProtection.ts
index 574805caa2..175ee33cf0 100644
--- a/authui/src/authflowv2/botprotection/botProtection.ts
+++ b/authui/src/authflowv2/botprotection/botProtection.ts
@@ -1,5 +1,8 @@
import { Controller } from "@hotwired/stimulus";
-import { dispatchBotProtectionDialogOpen } from "./botProtectionDialog";
+import {
+ dispatchBotProtectionDialogClose,
+ dispatchBotProtectionDialogOpen,
+} from "./botProtectionDialog";
/**
* Dispatch a custom event to set captcha verified with success token
@@ -77,7 +80,10 @@ export class BotProtectionController extends Controller {
this.isVerified = true;
// Wait for bot-protection-token-input to process "bot-protection:verify-success" event
// so that the form submission will have bot protection token injected.
- setTimeout(() => this.formSubmitTarget?.click(), 0);
+ setTimeout(() => {
+ this.formSubmitTarget?.click();
+ dispatchBotProtectionDialogClose();
+ }, 0);
};
onVerifyFailed = () => {
diff --git a/pkg/auth/handler/webapp/authflow_controller.go b/pkg/auth/handler/webapp/authflow_controller.go
index 40153c29df..6428b0815c 100644
--- a/pkg/auth/handler/webapp/authflow_controller.go
+++ b/pkg/auth/handler/webapp/authflow_controller.go
@@ -747,7 +747,10 @@ func (c *AuthflowController) takeBranchRecursively(s *webapp.Session, screen *we
// Take the first branch, and first channel by default.
var zeroIndex int
var zeroChannel model.AuthenticatorOOBChannel
- takeBranchResult := screen.TakeBranch(zeroIndex, zeroChannel, &webapp.TakeBranchOptions{})
+ takeBranchResult := screen.TakeBranch(&webapp.TakeBranchInput{
+ Index: zeroIndex,
+ Channel: zeroChannel,
+ }, &webapp.TakeBranchOptions{})
switch takeBranchResult := takeBranchResult.(type) {
// This taken branch does not require an input to select.
@@ -935,8 +938,15 @@ func (c *AuthflowController) takeBranch(w http.ResponseWriter, r *http.Request,
return err
}
channel := r.Form.Get("x_channel")
-
- takeBranchResult := screen.TakeBranch(index, model.AuthenticatorOOBChannel(channel), &webapp.TakeBranchOptions{
+ input := &webapp.TakeBranchInput{
+ Index: index,
+ Channel: model.AuthenticatorOOBChannel(channel),
+ }
+ if hasBPInput := IsBotProtectionInputValid(r.Form); hasBPInput {
+ input.BotProtectionProviderType = r.Form.Get("x_bot_protection_provider_type")
+ input.BotProtectionProviderResponse = r.Form.Get("x_bot_protection_provider_response")
+ }
+ takeBranchResult := screen.TakeBranch(input, &webapp.TakeBranchOptions{
DisableFallbackToSMS: true,
})
diff --git a/pkg/auth/handler/webapp/bot_protection.go b/pkg/auth/handler/webapp/bot_protection.go
index e704f35be9..fc97b05cad 100644
--- a/pkg/auth/handler/webapp/bot_protection.go
+++ b/pkg/auth/handler/webapp/bot_protection.go
@@ -24,6 +24,11 @@ func ValidateBotProtectionInput(formData url.Values) error {
return AuthflowBotProtectionSchema.Validator().ValidateValue(FormToJSON(formData))
}
+func IsBotProtectionInputValid(formData url.Values) bool {
+ err := ValidateBotProtectionInput(formData)
+ return err == nil
+}
+
func InsertBotProtection(formData url.Values, input map[string]interface{}) {
bpType := formData.Get("x_bot_protection_provider_type")
bpResp := formData.Get("x_bot_protection_provider_response")
diff --git a/pkg/auth/handler/webapp/viewmodels/authflow_branch.go b/pkg/auth/handler/webapp/viewmodels/authflow_branch.go
index d418b78069..8a3d202634 100644
--- a/pkg/auth/handler/webapp/viewmodels/authflow_branch.go
+++ b/pkg/auth/handler/webapp/viewmodels/authflow_branch.go
@@ -18,6 +18,7 @@ type AuthflowBranch struct {
MaskedClaimValue string
OTPForm otp.Form
VerificationSkippable bool
+ BotProtectionRequired bool
}
func isAuthflowBranchSame(a AuthflowBranch, b AuthflowBranch) bool {
@@ -114,6 +115,8 @@ func newAuthflowBranchViewModelStepAuthenticate(screen *webapp.AuthflowScreenWit
Channel: channel,
MaskedClaimValue: o.MaskedDisplayName,
OTPForm: o.OTPForm,
+ // only add bot protection for channel branch
+ BotProtectionRequired: o.BotProtection.IsRequired(),
}
if !isAuthflowBranchSame(branch, takenBranch) {
branches = append(branches, branch)
diff --git a/pkg/auth/webapp/session_authflow.go b/pkg/auth/webapp/session_authflow.go
index ed27ae724e..8ddfdb3af8 100644
--- a/pkg/auth/webapp/session_authflow.go
+++ b/pkg/auth/webapp/session_authflow.go
@@ -382,45 +382,59 @@ func (s *AuthflowScreenWithFlowResponse) InheritTakenBranchState(from *AuthflowS
}
}
-func (s *AuthflowScreenWithFlowResponse) TakeBranch(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
+type TakeBranchInput struct {
+ Index int
+ Channel model.AuthenticatorOOBChannel
+
+ // bot protection specific inputs
+ BotProtectionProviderType string
+ BotProtectionProviderResponse string
+}
+
+func (i *TakeBranchInput) HasBotProtectionInput() bool {
+ return i != nil && i.BotProtectionProviderType != "" && i.BotProtectionProviderResponse != ""
+}
+
+func (s *AuthflowScreenWithFlowResponse) TakeBranch(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
switch s.StateTokenFlowResponse.Type {
case authflow.FlowTypeSignup:
- return s.takeBranchSignup(index, channel, options)
+ return s.takeBranchSignup(input, options)
case authflow.FlowTypePromote:
- return s.takeBranchPromote(index, channel, options)
+ return s.takeBranchPromote(input, options)
case authflow.FlowTypeLogin:
- return s.takeBranchLogin(index, channel, options)
+ return s.takeBranchLogin(input, options)
case authflow.FlowTypeSignupLogin:
- return s.takeBranchSignupLogin(index, options)
+ return s.takeBranchSignupLogin(input.Index, options)
case authflow.FlowTypeReauth:
- return s.takeBranchReauth(index, channel, options)
+ return s.takeBranchReauth(input, options)
case authflow.FlowTypeAccountRecovery:
- return s.takeBranchAccountRecovery(index, options)
+ return s.takeBranchAccountRecovery(input.Index, options)
default:
panic(fmt.Errorf("unexpected flow type: %v", s.StateTokenFlowResponse.Type))
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchSignup(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
- return s.takeBranchSignupPromote(index, channel, options)
+func (s *AuthflowScreenWithFlowResponse) takeBranchSignup(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
+ return s.takeBranchSignupPromote(input, options)
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchPromote(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
- return s.takeBranchSignupPromote(index, channel, options)
+func (s *AuthflowScreenWithFlowResponse) takeBranchPromote(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
+ return s.takeBranchSignupPromote(input, options)
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchSignupPromote(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
+func (s *AuthflowScreenWithFlowResponse) takeBranchSignupPromote(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
switch config.AuthenticationFlowStepType(s.StateTokenFlowResponse.Action.Type) {
case config.AuthenticationFlowStepTypeIdentify:
// In identify, the user input actually takes the branch.
// The branch taken here is unimportant.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowStepTypeCreateAuthenticator:
data := s.StateTokenFlowResponse.Action.Data.(declarative.IntentSignupFlowStepCreateAuthenticatorData)
- return s.takeBranchCreateAuthenticator(index, channel, options, data.Options[index])
+ return s.takeBranchCreateAuthenticator(input, options, data.Options[input.Index])
case config.AuthenticationFlowStepTypeVerify:
// If we ever reach here, this means we have to choose channels.
data := s.StateTokenFlowResponse.Action.Data.(declarative.SelectOOBOTPChannelsData)
+ channel := input.Channel
if channel == "" {
channel = data.Channels[0]
}
@@ -429,14 +443,14 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchSignupPromote(index int, chan
"channel": c,
}
}
- input := inputFactory(channel)
+ resultInput := inputFactory(channel)
onFailureHandler := s.makeFallbackToSMSFromWhatsappRetryHandler(
inputFactory,
data.Channels,
options.DisableFallbackToSMS,
)
return TakeBranchResultInput{
- Input: input,
+ Input: resultInput,
NewAuthflowScreenFull: func(flowResponse *authflow.FlowResponse, retriedForError error) *AuthflowScreenWithFlowResponse {
var nilIndex *int
isContinuation := func(flowResponse *authflow.FlowResponse) bool {
@@ -446,7 +460,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchSignupPromote(index int, chan
if d, ok := flowResponse.Action.Data.(declarative.VerifyOOBOTPData); ok {
takenChannel = d.Channel
}
- screen := s.makeScreenForTakenBranch(flowResponse, input, nilIndex, takenChannel, isContinuation)
+ screen := s.makeScreenForTakenBranch(flowResponse, resultInput, nilIndex, takenChannel, isContinuation)
return screen
},
OnRetry: &onFailureHandler,
@@ -456,10 +470,10 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchSignupPromote(index int, chan
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
+func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
switch data := s.StateTokenFlowResponse.Action.Data.(type) {
case declarative.StepAuthenticateData:
- option := data.Options[index]
+ option := data.Options[input.Index]
switch option.Authentication {
case config.AuthenticationFlowAuthenticationPrimaryPassword:
fallthrough
@@ -471,7 +485,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int,
fallthrough
case config.AuthenticationFlowAuthenticationPrimaryPasskey:
// All these can take the branch simply by setting index.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPEmail:
fallthrough
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPSMS:
@@ -480,21 +494,32 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int,
fallthrough
case config.AuthenticationFlowAuthenticationSecondaryOOBOTPSMS:
// This branch requires input to take.
+ channel := input.Channel
if channel == "" {
channel = option.Channels[0]
}
- if option.BotProtection.IsRequired() {
- return s.takeBranchResultSimple(index, channel, true)
+ // Below clause takes place only when index=0 branch is OOBOTP, and bot protection not in input
+ // otherwise, the bot protection is fed to auto-taken OOBOTP branch too
+ if option.BotProtection.IsRequired() && !input.HasBotProtectionInput() {
+ return s.takeBranchResultSimple(input, true)
}
inputFactory := func(c model.AuthenticatorOOBChannel) map[string]interface{} {
- return map[string]interface{}{
+ out := map[string]interface{}{
"authentication": option.Authentication,
- "index": index,
+ "index": input.Index,
"channel": c,
}
+ if input.HasBotProtectionInput() {
+ bp := map[string]interface{}{
+ "type": input.BotProtectionProviderType,
+ "response": input.BotProtectionProviderResponse,
+ }
+ out["bot_protection"] = bp
+ }
+ return out
}
- input := inputFactory(channel)
+ resultInput := inputFactory(channel)
onFailureHandler := s.makeFallbackToSMSFromWhatsappRetryHandler(
inputFactory,
option.Channels,
@@ -502,7 +527,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int,
)
return TakeBranchResultInput{
- Input: input,
+ Input: resultInput,
NewAuthflowScreenFull: func(flowResponse *authflow.FlowResponse, retriedForError error) *AuthflowScreenWithFlowResponse {
isContinuation := func(flowResponse *authflow.FlowResponse) bool {
return flowResponse.Action.Type == authflow.FlowActionType(config.AuthenticationFlowLoginFlowStepTypeAuthenticate) && flowResponse.Action.Authentication == option.Authentication
@@ -515,7 +540,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int,
// Skip if we do not have the channel.
}
- screen := s.makeScreenForTakenBranch(flowResponse, input, &index, takenChannel, isContinuation)
+ screen := s.makeScreenForTakenBranch(flowResponse, resultInput, &input.Index, takenChannel, isContinuation)
return screen
},
OnRetry: &onFailureHandler,
@@ -524,28 +549,28 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLoginAuthenticate(index int,
panic(fmt.Errorf("unexpected authentication: %v", option.Authentication))
}
case declarative.VerifyOOBOTPData:
- channel = data.Channel
- return s.takeBranchResultSimple(index, channel, false)
+ channel := data.Channel
+ return s.takeBranchResultSimple(&TakeBranchInput{Index: input.Index, Channel: channel}, false)
default:
panic(fmt.Errorf("unexpected data type: %T", s.StateTokenFlowResponse.Action.Data))
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchLogin(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
+func (s *AuthflowScreenWithFlowResponse) takeBranchLogin(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
switch config.AuthenticationFlowStepType(s.StateTokenFlowResponse.Action.Type) {
case config.AuthenticationFlowStepTypeIdentify:
// In identify, the user input actually takes the branch.
// The branch taken here is unimportant.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowStepTypeAuthenticate:
switch s.StateTokenFlowResponse.Action.Data.(type) {
case declarative.IntentLoginFlowStepCreateAuthenticatorData:
data := s.StateTokenFlowResponse.Action.Data.(declarative.IntentLoginFlowStepCreateAuthenticatorData)
- return s.takeBranchCreateAuthenticator(index, channel, options, data.Options[index])
+ return s.takeBranchCreateAuthenticator(input, options, data.Options[input.Index])
case declarative.IntentCreateAuthenticatorTOTPData:
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case declarative.StepAuthenticateData:
- return s.takeBranchLoginAuthenticate(index, channel, options)
+ return s.takeBranchLoginAuthenticate(input, options)
default:
panic(fmt.Errorf("unexpected action data: %T", s.StateTokenFlowResponse.Action.Data))
}
@@ -554,15 +579,15 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchLogin(index int, channel mode
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions) TakeBranchResult {
+func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(input *TakeBranchInput, options *TakeBranchOptions) TakeBranchResult {
switch config.AuthenticationFlowStepType(s.StateTokenFlowResponse.Action.Type) {
case config.AuthenticationFlowStepTypeIdentify:
// In identify, id_token is used.
// The branch taken here is unimportant.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowStepTypeAuthenticate:
data := s.StateTokenFlowResponse.Action.Data.(declarative.StepAuthenticateData)
- option := data.Options[index]
+ option := data.Options[input.Index]
switch option.Authentication {
case config.AuthenticationFlowAuthenticationPrimaryPassword:
fallthrough
@@ -572,7 +597,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(index int, channel mod
fallthrough
case config.AuthenticationFlowAuthenticationPrimaryPasskey:
// All these can take the branch simply by setting index.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPEmail:
fallthrough
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPSMS:
@@ -581,22 +606,23 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(index int, channel mod
fallthrough
case config.AuthenticationFlowAuthenticationSecondaryOOBOTPSMS:
// This branch requires input to take.
+ channel := input.Channel
if channel == "" {
channel = option.Channels[0]
}
if option.BotProtection.IsRequired() {
- return s.takeBranchResultSimple(index, channel, true)
+ return s.takeBranchResultSimple(input, true)
}
inputFactory := func(c model.AuthenticatorOOBChannel) map[string]interface{} {
return map[string]interface{}{
"authentication": option.Authentication,
- "index": index,
+ "index": input.Index,
"channel": c,
}
}
- input := inputFactory(channel)
+ resultInput := inputFactory(channel)
onFailureHandler := s.makeFallbackToSMSFromWhatsappRetryHandler(
inputFactory,
option.Channels,
@@ -604,7 +630,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(index int, channel mod
)
return TakeBranchResultInput{
- Input: input,
+ Input: resultInput,
NewAuthflowScreenFull: func(flowResponse *authflow.FlowResponse, retriedForError error) *AuthflowScreenWithFlowResponse {
isContinuation := func(flowResponse *authflow.FlowResponse) bool {
return flowResponse.Action.Type == authflow.FlowActionType(config.AuthenticationFlowStepTypeAuthenticate) && flowResponse.Action.Authentication == option.Authentication
@@ -617,7 +643,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchReauth(index int, channel mod
// Skip if we do not have the channel.
}
- screen := s.makeScreenForTakenBranch(flowResponse, input, &index, takenChannel, isContinuation)
+ screen := s.makeScreenForTakenBranch(flowResponse, resultInput, &input.Index, takenChannel, isContinuation)
return screen
},
OnRetry: &onFailureHandler,
@@ -635,7 +661,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchSignupLogin(index int, option
case config.AuthenticationFlowStepTypeIdentify:
// In identify, the user input actually takes the branch.
// The branch taken here is unimportant.
- return s.takeBranchResultSimple(index, "", false)
+ return s.takeBranchResultSimple(&TakeBranchInput{Index: index, Channel: ""}, false)
default:
panic(fmt.Errorf("unexpected action type: %v", s.StateTokenFlowResponse.Action.Type))
}
@@ -646,19 +672,19 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchAccountRecovery(index int, op
case config.AuthenticationFlowStepTypeIdentify:
// In identify, the user input actually takes the branch.
// The branch taken here is unimportant.
- return s.takeBranchResultSimple(index, "", false)
+ return s.takeBranchResultSimple(&TakeBranchInput{Index: index, Channel: ""}, false)
default:
panic(fmt.Errorf("unexpected action type: %v", s.StateTokenFlowResponse.Action.Type))
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchResultSimple(index int, channel model.AuthenticatorOOBChannel, botProtectionRequired bool) TakeBranchResultSimple {
+func (s *AuthflowScreenWithFlowResponse) takeBranchResultSimple(input *TakeBranchInput, botProtectionRequired bool) TakeBranchResultSimple {
xStep := s.Screen.StateToken.XStep
screen := NewAuthflowScreenWithFlowResponse(s.StateTokenFlowResponse, xStep, nil)
screen.Screen.BranchStateToken = s.Screen.StateToken
screen.BranchStateTokenFlowResponse = s.BranchStateTokenFlowResponse
- screen.Screen.TakenBranchIndex = &index
- screen.Screen.TakenChannel = channel
+ screen.Screen.TakenBranchIndex = &input.Index
+ screen.Screen.TakenChannel = input.Channel
screen.Screen.IsBotProtectionRequired = botProtectionRequired
return TakeBranchResultSimple{
Screen: screen,
@@ -752,20 +778,20 @@ func (s *AuthflowScreenWithFlowResponse) makeFallbackToSMSFromWhatsappRetryHandl
}
}
-func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(index int, channel model.AuthenticatorOOBChannel, options *TakeBranchOptions, option declarative.CreateAuthenticatorOptionForOutput) TakeBranchResult {
+func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(input *TakeBranchInput, options *TakeBranchOptions, option declarative.CreateAuthenticatorOptionForOutput) TakeBranchResult {
switch option.Authentication {
case config.AuthenticationFlowAuthenticationPrimaryPassword:
fallthrough
case config.AuthenticationFlowAuthenticationSecondaryPassword:
// Password branches can be taken by setting index.
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(input, false)
case config.AuthenticationFlowAuthenticationSecondaryTOTP:
// This branch requires input to take.
- input := map[string]interface{}{
+ resultInput := map[string]interface{}{
"authentication": "secondary_totp",
}
return TakeBranchResultInput{
- Input: input,
+ Input: resultInput,
NewAuthflowScreenFull: func(flowResponse *authflow.FlowResponse, retriedForError error) *AuthflowScreenWithFlowResponse {
var emptyChannel model.AuthenticatorOOBChannel
isContinuation := func(flowResponse *authflow.FlowResponse) bool {
@@ -773,12 +799,13 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(index int
flowResponse.Action.Authentication == config.AuthenticationFlowAuthenticationSecondaryTOTP
}
- return s.makeScreenForTakenBranch(flowResponse, input, &index, emptyChannel, isContinuation)
+ return s.makeScreenForTakenBranch(flowResponse, resultInput, &input.Index, emptyChannel, isContinuation)
},
}
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPEmail:
fallthrough
case config.AuthenticationFlowAuthenticationPrimaryOOBOTPSMS:
+ channel := input.Channel
if channel == "" {
channel = option.Channels[0]
}
@@ -788,7 +815,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(index int
"channel": c,
}
}
- input := inputFactory(channel)
+ resultInput := inputFactory(channel)
onFailureHandler := s.makeFallbackToSMSFromWhatsappRetryHandler(
inputFactory,
option.Channels,
@@ -806,7 +833,7 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(index int
takenChannel = d.Channel
}
- screen := s.makeScreenForTakenBranch(flowResponse, input, &index, takenChannel, isContinuation)
+ screen := s.makeScreenForTakenBranch(flowResponse, resultInput, &input.Index, takenChannel, isContinuation)
return screen
},
OnRetry: &onFailureHandler,
@@ -815,10 +842,14 @@ func (s *AuthflowScreenWithFlowResponse) takeBranchCreateAuthenticator(index int
case config.AuthenticationFlowAuthenticationSecondaryOOBOTPEmail:
fallthrough
case config.AuthenticationFlowAuthenticationSecondaryOOBOTPSMS:
+ channel := input.Channel
if channel == "" {
channel = option.Channels[0]
}
- return s.takeBranchResultSimple(index, channel, false)
+ return s.takeBranchResultSimple(&TakeBranchInput{
+ Index: input.Index,
+ Channel: channel,
+ }, false)
default:
panic(fmt.Errorf("unexpected authentication: %v", option.Authentication))
}
diff --git a/resources/authgear/templates/en/web/authflowv2/__authflow_branch.html b/resources/authgear/templates/en/web/authflowv2/__authflow_branch.html
index 4720b3d80b..7358ae1069 100644
--- a/resources/authgear/templates/en/web/authflowv2/__authflow_branch.html
+++ b/resources/authgear/templates/en/web/authflowv2/__authflow_branch.html
@@ -36,12 +36,15 @@
method="post"
novalidate
data-controller="turbo-form"
- data-action="submit->turbo-form#submitForm"
+ data-action="{{ if .BotProtectionRequired }}submit->bot-protection#verifyFormSubmit {{end}}submit->turbo-form#submitForm"
>
{{ $.CSRFField }}
+ {{ if .BotProtectionRequired }}
+ {{ template "web/authflowv2/__bot_protection_form_input.html" $ }}
+ {{ end }}