Skip to content

Commit c86aaa9

Browse files
authored
fix: onboarding states generation
This commit fixes the following issues: - Generation of onboarding states on registration does not consider all possible values for the acquire_on_registration configuration option. - Generation of onboarding states on login does not consider WebAuthn availability/capability.
1 parent 1d004e3 commit c86aaa9

File tree

2 files changed

+92
-73
lines changed

2 files changed

+92
-73
lines changed

backend/flow_api/flow/login/hook_schedule_onboarding_states.go

+60-49
Original file line numberDiff line numberDiff line change
@@ -47,57 +47,68 @@ func (h ScheduleOnboardingStates) determineCredentialOnboardingStates(c flowpilo
4747
cfg := deps.Cfg
4848
result := make([]flowpilot.StateName, 0)
4949

50-
alwaysAcquirePasskey := cfg.Passkey.Enabled && cfg.Passkey.AcquireOnLogin == "always"
51-
alwaysAcquirePassword := cfg.Password.Enabled && cfg.Password.AcquireOnLogin == "always"
52-
conditionalAcquirePasskey := cfg.Passkey.Enabled && cfg.Passkey.AcquireOnLogin == "conditional"
53-
conditionalAcquirePassword := cfg.Password.Enabled && cfg.Password.AcquireOnLogin == "conditional"
54-
neverAcquirePasskey := !cfg.Passkey.Enabled || cfg.Passkey.AcquireOnLogin == "never"
55-
neverAcquirePassword := !cfg.Password.Enabled || cfg.Password.AcquireOnLogin == "never"
56-
57-
if alwaysAcquirePasskey && alwaysAcquirePassword {
58-
if !hasPasskey && !hasPassword {
59-
if !cfg.Password.Optional && cfg.Passkey.Optional {
60-
result = append(result, shared.StatePasswordCreation, shared.StateOnboardingCreatePasskey)
61-
} else {
62-
result = append(result, shared.StateOnboardingCreatePasskey, shared.StatePasswordCreation)
50+
webauthnAvailable := c.Stash().Get(shared.StashPathWebauthnAvailable).Bool()
51+
passkeyEnabled := webauthnAvailable && deps.Cfg.Passkey.Enabled
52+
passwordEnabled := deps.Cfg.Password.Enabled
53+
passwordAndPasskeyEnabled := passkeyEnabled && passwordEnabled
54+
55+
alwaysAcquirePasskey := cfg.Passkey.AcquireOnLogin == "always"
56+
alwaysAcquirePassword := cfg.Password.AcquireOnLogin == "always"
57+
conditionalAcquirePasskey := cfg.Passkey.AcquireOnLogin == "conditional"
58+
conditionalAcquirePassword := cfg.Password.AcquireOnLogin == "conditional"
59+
neverAcquirePasskey := cfg.Passkey.AcquireOnLogin == "never"
60+
neverAcquirePassword := cfg.Password.AcquireOnLogin == "never"
61+
62+
if passwordAndPasskeyEnabled {
63+
if alwaysAcquirePasskey && alwaysAcquirePassword {
64+
if !hasPasskey && !hasPassword {
65+
if !cfg.Password.Optional && cfg.Passkey.Optional {
66+
result = append(result, shared.StatePasswordCreation, shared.StateOnboardingCreatePasskey)
67+
} else {
68+
result = append(result, shared.StateOnboardingCreatePasskey, shared.StatePasswordCreation)
69+
}
70+
} else if hasPasskey && !hasPassword {
71+
result = append(result, shared.StatePasswordCreation)
72+
} else if !hasPasskey && hasPassword {
73+
result = append(result, shared.StateOnboardingCreatePasskey)
74+
}
75+
} else if alwaysAcquirePasskey && conditionalAcquirePassword {
76+
if !hasPasskey && !hasPassword {
77+
result = append(result, shared.StateOnboardingCreatePasskey) // skip should lead to password onboarding
78+
} else if !hasPasskey && hasPassword {
79+
result = append(result, shared.StateOnboardingCreatePasskey)
80+
}
81+
} else if conditionalAcquirePasskey && alwaysAcquirePassword {
82+
if !hasPasskey && !hasPassword {
83+
result = append(result, shared.StatePasswordCreation) // skip should lead to passkey onboarding
84+
} else if hasPasskey && !hasPassword {
85+
result = append(result, shared.StatePasswordCreation)
86+
}
87+
} else if conditionalAcquirePasskey && conditionalAcquirePassword {
88+
if !hasPasskey && !hasPassword {
89+
result = append(result, shared.StateCredentialOnboardingChooser) // credential_onboarding_chooser can be skipped
90+
}
91+
} else if conditionalAcquirePasskey && neverAcquirePassword {
92+
if !hasPasskey && !hasPassword {
93+
result = append(result, shared.StateOnboardingCreatePasskey)
94+
}
95+
} else if neverAcquirePasskey && conditionalAcquirePassword {
96+
if !hasPasskey && !hasPassword {
97+
result = append(result, shared.StatePasswordCreation)
98+
}
99+
} else if neverAcquirePasskey && alwaysAcquirePassword {
100+
if !hasPassword {
101+
result = append(result, shared.StatePasswordCreation)
102+
}
103+
} else if alwaysAcquirePasskey && neverAcquirePassword {
104+
if !hasPasskey {
105+
result = append(result, shared.StateOnboardingCreatePasskey)
63106
}
64-
} else if hasPasskey && !hasPassword {
65-
result = append(result, shared.StatePasswordCreation)
66-
} else if !hasPasskey && hasPassword {
67-
result = append(result, shared.StateOnboardingCreatePasskey)
68-
}
69-
} else if alwaysAcquirePasskey && conditionalAcquirePassword {
70-
if !hasPasskey && !hasPassword {
71-
result = append(result, shared.StateOnboardingCreatePasskey) // skip should lead to password onboarding
72-
} else if !hasPasskey && hasPassword {
73-
result = append(result, shared.StateOnboardingCreatePasskey)
74-
}
75-
} else if conditionalAcquirePasskey && alwaysAcquirePassword {
76-
if !hasPasskey && !hasPassword {
77-
result = append(result, shared.StatePasswordCreation) // skip should lead to passkey onboarding
78-
} else if hasPasskey && !hasPassword {
79-
result = append(result, shared.StatePasswordCreation)
80-
}
81-
} else if conditionalAcquirePasskey && conditionalAcquirePassword {
82-
if !hasPasskey && !hasPassword {
83-
result = append(result, shared.StateCredentialOnboardingChooser) // credential_onboarding_chooser can be skipped
84-
}
85-
} else if conditionalAcquirePasskey && neverAcquirePassword {
86-
if !hasPasskey && !hasPassword {
87-
result = append(result, shared.StateOnboardingCreatePasskey)
88-
}
89-
} else if neverAcquirePasskey && conditionalAcquirePassword {
90-
if !hasPasskey && !hasPassword {
91-
result = append(result, shared.StatePasswordCreation)
92-
}
93-
} else if neverAcquirePasskey && alwaysAcquirePassword {
94-
if !hasPassword {
95-
result = append(result, shared.StatePasswordCreation)
96-
}
97-
} else if alwaysAcquirePasskey && neverAcquirePassword {
98-
if !hasPasskey {
99-
result = append(result, shared.StateOnboardingCreatePasskey)
100107
}
108+
} else if passkeyEnabled && (alwaysAcquirePasskey || conditionalAcquirePasskey) {
109+
result = append(result, shared.StateOnboardingCreatePasskey)
110+
} else if passwordEnabled && (alwaysAcquirePassword || conditionalAcquirePassword) {
111+
result = append(result, shared.StatePasswordCreation)
101112
}
102113

103114
return result

backend/flow_api/flow/registration/action_register_login_identifier.go

+32-24
Original file line numberDiff line numberDiff line change
@@ -166,42 +166,50 @@ func (a RegisterLoginIdentifier) Execute(c flowpilot.ExecutionContext) error {
166166
func (a RegisterLoginIdentifier) generateRegistrationStates(c flowpilot.ExecutionContext) []flowpilot.StateName {
167167
deps := a.GetDeps(c)
168168

169-
stateNames := make([]flowpilot.StateName, 0)
169+
result := make([]flowpilot.StateName, 0)
170170

171171
emailExists := len(c.Input().Get("email").String()) > 0
172172
if emailExists && deps.Cfg.Email.RequireVerification {
173-
stateNames = append(stateNames, shared.StatePasscodeConfirmation)
173+
result = append(result, shared.StatePasscodeConfirmation)
174174
}
175175

176176
webauthnAvailable := c.Stash().Get(shared.StashPathWebauthnAvailable).Bool()
177177
passkeyEnabled := webauthnAvailable && deps.Cfg.Passkey.Enabled
178178
passwordEnabled := deps.Cfg.Password.Enabled
179-
bothEnabled := passkeyEnabled && passwordEnabled
180-
181-
alwaysPasskey := deps.Cfg.Passkey.AcquireOnRegistration == "always"
182-
conditionalPasskey := deps.Cfg.Passkey.AcquireOnRegistration == "conditional"
183-
alwaysPassword := deps.Cfg.Password.AcquireOnRegistration == "always"
184-
conditionalPassword := deps.Cfg.Password.AcquireOnRegistration == "conditional"
185-
186-
if bothEnabled {
187-
if conditionalPasskey && conditionalPassword {
188-
stateNames = append(stateNames, shared.StateCredentialOnboardingChooser)
189-
} else if alwaysPasskey && !alwaysPassword {
190-
stateNames = append(stateNames, shared.StateOnboardingCreatePasskey)
191-
} else if !alwaysPasskey && alwaysPassword {
192-
stateNames = append(stateNames, shared.StatePasswordCreation)
193-
} else if alwaysPassword && alwaysPasskey {
179+
passwordAndPasskeyEnabled := passkeyEnabled && passwordEnabled
180+
181+
alwaysAcquirePasskey := deps.Cfg.Passkey.AcquireOnRegistration == "always"
182+
conditionalAcquirePasskey := deps.Cfg.Passkey.AcquireOnRegistration == "conditional"
183+
alwaysAcquirePassword := deps.Cfg.Password.AcquireOnRegistration == "always"
184+
conditionalAcquirePassword := deps.Cfg.Password.AcquireOnRegistration == "conditional"
185+
neverAcquirePasskey := deps.Cfg.Passkey.AcquireOnLogin == "never"
186+
neverAcquirePassword := deps.Cfg.Password.AcquireOnLogin == "never"
187+
188+
if passwordAndPasskeyEnabled {
189+
if alwaysAcquirePasskey && alwaysAcquirePassword {
194190
if !deps.Cfg.Password.Optional && deps.Cfg.Passkey.Optional {
195-
stateNames = append(stateNames, shared.StatePasswordCreation, shared.StateOnboardingCreatePasskey)
191+
result = append(result, shared.StatePasswordCreation, shared.StateOnboardingCreatePasskey)
196192
} else {
197-
stateNames = append(stateNames, shared.StateOnboardingCreatePasskey, shared.StatePasswordCreation)
193+
result = append(result, shared.StateOnboardingCreatePasskey, shared.StatePasswordCreation)
198194
}
195+
} else if alwaysAcquirePasskey && conditionalAcquirePassword {
196+
result = append(result, shared.StateOnboardingCreatePasskey)
197+
} else if conditionalAcquirePasskey && alwaysAcquirePassword {
198+
result = append(result, shared.StatePasswordCreation)
199+
} else if conditionalAcquirePasskey && conditionalAcquirePassword {
200+
result = append(result, shared.StateCredentialOnboardingChooser)
201+
} else if conditionalAcquirePasskey && neverAcquirePassword {
202+
result = append(result, shared.StateOnboardingCreatePasskey)
203+
} else if neverAcquirePasskey && (alwaysAcquirePassword || conditionalAcquirePassword) {
204+
result = append(result, shared.StatePasswordCreation)
205+
} else if (alwaysAcquirePasskey || conditionalAcquirePasskey) && neverAcquirePassword {
206+
result = append(result, shared.StateOnboardingCreatePasskey)
199207
}
200-
} else if passkeyEnabled && (alwaysPasskey || conditionalPasskey) {
201-
stateNames = append(stateNames, shared.StateOnboardingCreatePasskey)
202-
} else if passwordEnabled && (alwaysPassword || conditionalPassword) {
203-
stateNames = append(stateNames, shared.StatePasswordCreation)
208+
} else if passkeyEnabled && (alwaysAcquirePasskey || conditionalAcquirePasskey) {
209+
result = append(result, shared.StateOnboardingCreatePasskey)
210+
} else if passwordEnabled && (alwaysAcquirePassword || conditionalAcquirePassword) {
211+
result = append(result, shared.StatePasswordCreation)
204212
}
205213

206-
return stateNames
214+
return result
207215
}

0 commit comments

Comments
 (0)