mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 12:30:19 +08:00
feat: improve MFA by using user's own Email and Phone (#2002)
* refactor: mfa * fix: clean code * fix: clean code * fix: fix crash and improve robot
This commit is contained in:
@ -370,6 +370,7 @@ func (c *ApiController) GetAccount() {
|
||||
|
||||
user.Permissions = object.GetMaskedPermissions(user.Permissions)
|
||||
user.Roles = object.GetMaskedRoles(user.Roles)
|
||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||
|
||||
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
||||
if err != nil {
|
||||
|
@ -71,7 +71,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
|
||||
if form.Password != "" && user.IsMfaEnabled() {
|
||||
c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
|
||||
resp = &Response{Status: object.NextMfa, Data: user.GetPreferMfa(true)}
|
||||
resp = &Response{Status: object.NextMfa, Data: user.GetPreferredMfaProps(true)}
|
||||
return
|
||||
}
|
||||
|
||||
@ -656,15 +656,20 @@ func (c *ApiController) Login() {
|
||||
}
|
||||
|
||||
if authForm.Passcode != "" {
|
||||
MfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferMfa(false))
|
||||
err = MfaUtil.Verify(authForm.Passcode)
|
||||
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
|
||||
if mfaUtil == nil {
|
||||
c.ResponseError("Invalid multi-factor authentication type")
|
||||
return
|
||||
}
|
||||
|
||||
err = mfaUtil.Verify(authForm.Passcode)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if authForm.RecoveryCode != "" {
|
||||
err = object.RecoverTfs(user, authForm.RecoveryCode)
|
||||
err = object.MfaRecover(user, authForm.RecoveryCode)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
@ -177,6 +177,10 @@ func (c *ApiController) SetSessionData(s *SessionData) {
|
||||
}
|
||||
|
||||
func (c *ApiController) setMfaSessionData(data *object.MfaSessionData) {
|
||||
if data == nil {
|
||||
c.SetSession(object.MfaSessionUserId, nil)
|
||||
return
|
||||
}
|
||||
c.SetSession(object.MfaSessionUserId, data.UserId)
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
func (c *ApiController) MfaSetupInitiate() {
|
||||
owner := c.Ctx.Request.Form.Get("owner")
|
||||
name := c.Ctx.Request.Form.Get("name")
|
||||
authType := c.Ctx.Request.Form.Get("type")
|
||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||
userId := util.GetId(owner, name)
|
||||
|
||||
if len(userId) == 0 {
|
||||
@ -42,10 +42,11 @@ func (c *ApiController) MfaSetupInitiate() {
|
||||
return
|
||||
}
|
||||
|
||||
MfaUtil := object.GetMfaUtil(authType, nil)
|
||||
MfaUtil := object.GetMfaUtil(mfaType, nil)
|
||||
if MfaUtil == nil {
|
||||
c.ResponseError("Invalid auth type")
|
||||
}
|
||||
|
||||
user, err := object.GetUser(userId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
@ -79,16 +80,20 @@ func (c *ApiController) MfaSetupInitiate() {
|
||||
// @Success 200 {object} Response object
|
||||
// @router /mfa/setup/verify [post]
|
||||
func (c *ApiController) MfaSetupVerify() {
|
||||
authType := c.Ctx.Request.Form.Get("type")
|
||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||
passcode := c.Ctx.Request.Form.Get("passcode")
|
||||
|
||||
if authType == "" || passcode == "" {
|
||||
if mfaType == "" || passcode == "" {
|
||||
c.ResponseError("missing auth type or passcode")
|
||||
return
|
||||
}
|
||||
MfaUtil := object.GetMfaUtil(authType, nil)
|
||||
mfaUtil := object.GetMfaUtil(mfaType, nil)
|
||||
if mfaUtil == nil {
|
||||
c.ResponseError("Invalid multi-factor authentication type")
|
||||
return
|
||||
}
|
||||
|
||||
err := MfaUtil.SetupVerify(c.Ctx, passcode)
|
||||
err := mfaUtil.SetupVerify(c.Ctx, passcode)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
} else {
|
||||
@ -108,7 +113,7 @@ func (c *ApiController) MfaSetupVerify() {
|
||||
func (c *ApiController) MfaSetupEnable() {
|
||||
owner := c.Ctx.Request.Form.Get("owner")
|
||||
name := c.Ctx.Request.Form.Get("name")
|
||||
authType := c.Ctx.Request.Form.Get("type")
|
||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||
|
||||
user, err := object.GetUser(util.GetId(owner, name))
|
||||
if err != nil {
|
||||
@ -121,8 +126,13 @@ func (c *ApiController) MfaSetupEnable() {
|
||||
return
|
||||
}
|
||||
|
||||
twoFactor := object.GetMfaUtil(authType, nil)
|
||||
err = twoFactor.Enable(c.Ctx, user)
|
||||
mfaUtil := object.GetMfaUtil(mfaType, nil)
|
||||
if mfaUtil == nil {
|
||||
c.ResponseError("Invalid multi-factor authentication type")
|
||||
return
|
||||
}
|
||||
|
||||
err = mfaUtil.Enable(c.Ctx, user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -137,11 +147,9 @@ func (c *ApiController) MfaSetupEnable() {
|
||||
// @Description: Delete MFA
|
||||
// @param owner form string true "owner of user"
|
||||
// @param name form string true "name of user"
|
||||
// @param id form string true "id of user's MFA props"
|
||||
// @Success 200 {object} Response object
|
||||
// @router /delete-mfa/ [post]
|
||||
func (c *ApiController) DeleteMfa() {
|
||||
id := c.Ctx.Request.Form.Get("id")
|
||||
owner := c.Ctx.Request.Form.Get("owner")
|
||||
name := c.Ctx.Request.Form.Get("name")
|
||||
userId := util.GetId(owner, name)
|
||||
@ -151,28 +159,18 @@ func (c *ApiController) DeleteMfa() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
c.ResponseError("User doesn't exist")
|
||||
return
|
||||
}
|
||||
|
||||
mfaProps := user.MultiFactorAuths[:0]
|
||||
i := 0
|
||||
for _, mfaProp := range mfaProps {
|
||||
if mfaProp.Id != id {
|
||||
mfaProps[i] = mfaProp
|
||||
i++
|
||||
}
|
||||
}
|
||||
user.MultiFactorAuths = mfaProps
|
||||
_, err = object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
|
||||
err = object.DisabledMultiFactorAuth(user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(user.MultiFactorAuths)
|
||||
c.ResponseOk(object.GetAllMfaProps(user, true))
|
||||
}
|
||||
|
||||
// SetPreferredMfa
|
||||
@ -185,7 +183,7 @@ func (c *ApiController) DeleteMfa() {
|
||||
// @Success 200 {object} Response object
|
||||
// @router /set-preferred-mfa [post]
|
||||
func (c *ApiController) SetPreferredMfa() {
|
||||
id := c.Ctx.Request.Form.Get("id")
|
||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||
owner := c.Ctx.Request.Form.Get("owner")
|
||||
name := c.Ctx.Request.Form.Get("name")
|
||||
userId := util.GetId(owner, name)
|
||||
@ -195,29 +193,15 @@ func (c *ApiController) SetPreferredMfa() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
c.ResponseError("User doesn't exist")
|
||||
return
|
||||
}
|
||||
|
||||
mfaProps := user.MultiFactorAuths
|
||||
for i, mfaProp := range user.MultiFactorAuths {
|
||||
if mfaProp.Id == id {
|
||||
mfaProps[i].IsPreferred = true
|
||||
} else {
|
||||
mfaProps[i].IsPreferred = false
|
||||
}
|
||||
}
|
||||
|
||||
_, err = object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
|
||||
err = object.SetPreferredMultiFactorAuth(user, mfaType)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for i, mfaProp := range mfaProps {
|
||||
mfaProps[i] = object.GetMaskedProps(mfaProp)
|
||||
}
|
||||
c.ResponseOk(mfaProps)
|
||||
c.ResponseOk(object.GetAllMfaProps(user, true))
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ func (c *ApiController) GetUser() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||
err = object.ExtendUserWithRolesAndPermissions(user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -93,9 +93,10 @@ func (c *ApiController) SendVerificationCode() {
|
||||
}
|
||||
}
|
||||
|
||||
// mfaSessionData != nil, means method is MfaSetupVerification
|
||||
// mfaSessionData != nil, means method is MfaAuthVerification
|
||||
if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil {
|
||||
user, err = object.GetUser(mfaSessionData.UserId)
|
||||
c.setMfaSessionData(nil)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -129,7 +130,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
} else if vform.Method == ResetVerification {
|
||||
user = c.getCurrentUser()
|
||||
} else if vform.Method == MfaAuthVerification {
|
||||
mfaProps := user.GetPreferMfa(false)
|
||||
mfaProps := user.GetPreferredMfaProps(false)
|
||||
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
|
||||
vform.Dest = mfaProps.Secret
|
||||
}
|
||||
@ -157,12 +158,14 @@ func (c *ApiController) SendVerificationCode() {
|
||||
}
|
||||
|
||||
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
||||
} else if vform.Method == ResetVerification {
|
||||
if user = c.getCurrentUser(); user != nil {
|
||||
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
||||
} else if vform.Method == ResetVerification || vform.Method == MfaSetupVerification {
|
||||
if vform.CountryCode == "" {
|
||||
if user = c.getCurrentUser(); user != nil {
|
||||
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
||||
}
|
||||
}
|
||||
} else if vform.Method == MfaAuthVerification {
|
||||
mfaProps := user.GetPreferMfa(false)
|
||||
mfaProps := user.GetPreferredMfaProps(false)
|
||||
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
|
||||
vform.Dest = mfaProps.Secret
|
||||
}
|
||||
|
Reference in New Issue
Block a user