8aafa06259
* move CheckPasswordMFA to flow executor Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add mfa support field to radius Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package flow
|
|
|
|
import (
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const CodePasswordSeparator = ";"
|
|
|
|
var alphaNum = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
|
|
|
|
// CheckPasswordInlineMFA For protocols that only support username/password, check if the password
|
|
// contains the TOTP code
|
|
func (fe *FlowExecutor) CheckPasswordInlineMFA() {
|
|
password := fe.Answers[StagePassword]
|
|
// We already have an authenticator answer
|
|
if fe.Answers[StageAuthenticatorValidate] != "" {
|
|
return
|
|
}
|
|
// password doesn't contain the separator
|
|
if !strings.Contains(password, CodePasswordSeparator) {
|
|
return
|
|
}
|
|
// 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
|
|
}
|
|
} 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
|
|
}
|