feat: add multi-factor authentication (MFA) feature (#1800)

* feat: add two-factor authentication interface and api

* merge

* feat: add Two-factor authentication accountItem and two-factor api in frontend

* feat: add basic 2fa setup UI

* rebase

* feat: finish the two-factor authentication

* rebase

* feat: support recover code

* chore: fix eslint error

* feat: support multiple sms account

* fix: client application login

* fix: lint

* Update authz.go

* Update mfa.go

* fix: support phone

* fix: i18n

* fix: i18n

* fix: support preferred mfa methods

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
This commit is contained in:
Yaodong Yu
2023-05-05 21:23:59 +08:00
committed by GitHub
parent 5b27f939b8
commit eb39e9e044
51 changed files with 4215 additions and 2776 deletions

View File

@ -27,10 +27,12 @@ import (
)
const (
SignupVerification = "signup"
ResetVerification = "reset"
LoginVerification = "login"
ForgetVerification = "forget"
SignupVerification = "signup"
ResetVerification = "reset"
LoginVerification = "login"
ForgetVerification = "forget"
MfaSetupVerification = "mfaSetup"
MfaAuthVerification = "mfaAuth"
)
// SendVerificationCode ...
@ -78,6 +80,11 @@ func (c *ApiController) SendVerificationCode() {
user = object.GetUser(util.GetId(owner, vform.CheckUser))
}
// mfaSessionData != nil, means method is MfaSetupVerification
if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil {
user = object.GetUser(mfaSessionData.UserId)
}
sendResp := errors.New("invalid dest type")
switch vform.Type {
@ -99,6 +106,11 @@ func (c *ApiController) SendVerificationCode() {
}
} else if vform.Method == ResetVerification {
user = c.getCurrentUser()
} else if vform.Method == MfaAuthVerification {
mfaProps := user.GetPreferMfa(false)
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret
}
}
provider := application.GetEmailProvider()
@ -119,6 +131,13 @@ func (c *ApiController) SendVerificationCode() {
if user = c.getCurrentUser(); user != nil {
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
}
} else if vform.Method == MfaAuthVerification {
mfaProps := user.GetPreferMfa(false)
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret
}
vform.CountryCode = mfaProps.CountryCode
}
provider := application.GetSmsProvider()
@ -130,6 +149,11 @@ func (c *ApiController) SendVerificationCode() {
}
}
if vform.Method == MfaSetupVerification {
c.SetSession(object.MfaSmsCountryCodeSession, vform.CountryCode)
c.SetSession(object.MfaSmsDestSession, vform.Dest)
}
if sendResp != nil {
c.ResponseError(sendResp.Error())
} else {