refactor CheckPasswordInlineMFA to SetSecrets
This commit is contained in:
parent
cec021117c
commit
658b37c718
|
@ -10,39 +10,44 @@ const CodePasswordSeparator = ";"
|
||||||
|
|
||||||
var alphaNum = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
|
var alphaNum = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
|
||||||
|
|
||||||
// CheckPasswordInlineMFA For protocols that only support username/password, check if the password
|
// SetSecrets sets the secret answers for the flow executor for protocols that only support username/password
|
||||||
// contains the TOTP code
|
// acccording to used options
|
||||||
func (fe *FlowExecutor) CheckPasswordInlineMFA() {
|
func (fe *FlowExecutor) SetSecrets(password string, mfacodebased bool) {
|
||||||
password := fe.Answers[StagePassword]
|
if fe.Answers[StageAuthenticatorValidate] != "" || fe.Answers[StagePassword] != "" {
|
||||||
// We already have an authenticator answer
|
|
||||||
if fe.Answers[StageAuthenticatorValidate] != "" {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// password doesn't contain the separator
|
fe.Answers[StagePassword] = password
|
||||||
if !strings.Contains(password, CodePasswordSeparator) {
|
if mfacodebased {
|
||||||
return
|
// password doesn't contain the separator
|
||||||
}
|
if !strings.Contains(password, CodePasswordSeparator) {
|
||||||
// password ends with the separator, so it won't contain an answer
|
|
||||||
if strings.HasSuffix(password, CodePasswordSeparator) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
idx := strings.LastIndex(password, CodePasswordSeparator)
|
|
||||||
authenticator := password[idx+1:]
|
|
||||||
// Authenticator is either 6 chars (totp code) or 8 chars (long totp or static)
|
|
||||||
if len(authenticator) == 6 {
|
|
||||||
// authenticator answer isn't purely numerical, so won't be value
|
|
||||||
if _, err := strconv.Atoi(authenticator); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if len(authenticator) == 8 {
|
// password ends with the separator, so it won't contain an answer
|
||||||
// 8 chars can be a long totp or static token, so it needs to be alphanumerical
|
if strings.HasSuffix(password, CodePasswordSeparator) {
|
||||||
if !alphaNum.MatchString(authenticator) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
idx := strings.LastIndex(password, CodePasswordSeparator)
|
||||||
|
authenticator := password[idx+1:]
|
||||||
|
// Authenticator is either 6 chars (totp code) or 8 chars (long totp or static)
|
||||||
|
if len(authenticator) == 6 {
|
||||||
|
// authenticator answer isn't purely numerical, so won't be value
|
||||||
|
if _, err := strconv.Atoi(authenticator); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if len(authenticator) == 8 {
|
||||||
|
// 8 chars can be a long totp or static token, so it needs to be alphanumerical
|
||||||
|
if !alphaNum.MatchString(authenticator) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Any other length, doesn't contain an answer
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fe.Answers[StagePassword] = password[:idx]
|
||||||
|
fe.Answers[StageAuthenticatorValidate] = authenticator
|
||||||
} else {
|
} else {
|
||||||
// Any other length, doesn't contain an answer
|
// If code-based MFA is disabled StageAuthenticatorValidate answer is set to password.
|
||||||
return
|
// This allows flows with a mfa stage only.
|
||||||
|
fe.Answers[StageAuthenticatorValidate] = password
|
||||||
}
|
}
|
||||||
fe.Answers[StagePassword] = password[:idx]
|
|
||||||
fe.Answers[StageAuthenticatorValidate] = authenticator
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,7 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
||||||
fe.Params.Add("goauthentik.io/outpost/ldap", "true")
|
fe.Params.Add("goauthentik.io/outpost/ldap", "true")
|
||||||
|
|
||||||
fe.Answers[flow.StageIdentification] = username
|
fe.Answers[flow.StageIdentification] = username
|
||||||
fe.Answers[flow.StagePassword] = req.BindPW
|
fe.SetSecrets(req.BindPW, db.si.GetMFASupport())
|
||||||
if db.si.GetMFASupport() {
|
|
||||||
fe.CheckPasswordInlineMFA()
|
|
||||||
}
|
|
||||||
|
|
||||||
passed, err := fe.Execute()
|
passed, err := fe.Execute()
|
||||||
flags := flags.UserFlags{
|
flags := flags.UserFlags{
|
||||||
|
|
|
@ -21,14 +21,7 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
|
||||||
fe.Params.Add("goauthentik.io/outpost/radius", "true")
|
fe.Params.Add("goauthentik.io/outpost/radius", "true")
|
||||||
|
|
||||||
fe.Answers[flow.StageIdentification] = username
|
fe.Answers[flow.StageIdentification] = username
|
||||||
fe.Answers[flow.StagePassword] = rfc2865.UserPassword_GetString(r.Packet)
|
fe.SetSecrets(rfc2865.UserPassword_GetString(r.Packet), r.pi.MFASupport)
|
||||||
if r.pi.MFASupport {
|
|
||||||
fe.CheckPasswordInlineMFA()
|
|
||||||
} else {
|
|
||||||
// If code-based MFA is disabled StageAuthenticatorValidate answer is set to StagePassword answer.
|
|
||||||
// This allows flows with only a mfa stage
|
|
||||||
fe.Answers[flow.StageAuthenticatorValidate] = fe.Answers[flow.StagePassword]
|
|
||||||
}
|
|
||||||
|
|
||||||
passed, err := fe.Execute()
|
passed, err := fe.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Reference in New Issue