diff --git a/actions.go b/actions.go index 62e2b2013bf929899b4cc383ce2ba448eb14edb0..5277b4a959aa5483a7af4ca0513cf53ee516e4e9 100644 --- a/actions.go +++ b/actions.go @@ -177,6 +177,8 @@ type PasswordRecoveryResponse struct { // RecoverPassword lets users reset their password by providing // secondary credentials, which we authenticate ourselves. // +// Two-factor authentication is disabled on successful recovery. +// // TODO: call out to auth-server for secondary authentication? func (s *AccountService) RecoverPassword(ctx context.Context, tx TX, req *PasswordRecoveryRequest) (*PasswordRecoveryResponse, error) { user, err := getUserOrDie(ctx, tx, req.Username) @@ -208,6 +210,7 @@ func (s *AccountService) RecoverPassword(ctx context.Context, tx TX, req *Passwo if err := s.changeUserPasswordAndUpdateEncryptionKeys(ctx, tx, user, req.RecoveryPassword, req.Password); err != nil { return err } + // Disable 2FA. return s.disable2FA(ctx, tx, user) }) diff --git a/backend/model.go b/backend/model.go index d467ae7d4cb1d22e0afa06ce1e462494bda9fc25..31a07bce8765709f36163bd3ef1d5e4f790b3cae 100644 --- a/backend/model.go +++ b/backend/model.go @@ -128,12 +128,11 @@ func newUser(entry *ldap.Entry) (*accountserver.User, error) { UID: uidNumber, PasswordRecoveryHint: entry.GetAttributeValue(recoveryHintLDAPAttr), U2FRegistrations: decodeU2FRegistrations(entry.GetAttributeValues(u2fRegistrationsLDAPAttr)), + HasOTP: entry.GetAttributeValue(totpSecretLDAPAttr) != "", } // The user has 2FA enabled if it has a TOTP secret or U2F keys. - if (entry.GetAttributeValue(totpSecretLDAPAttr) != "") || (len(user.U2FRegistrations) > 0) { - user.Has2FA = true - } + user.Has2FA = (user.HasOTP || (len(user.U2FRegistrations) > 0)) if user.Lang == "" { user.Lang = "en" diff --git a/types.go b/types.go index 91adf6a0c19e11a1ee232f5354970be69dfab7f9..2bb3d7f43837fc2da3e71f035f3436d63393322d 100644 --- a/types.go +++ b/types.go @@ -30,13 +30,23 @@ type User struct { // UNIX user id. UID int `json:"uid"` - Has2FA bool `json:"has_2fa"` - HasEncryptionKeys bool `json:"has_encryption_keys"` + // Has2FA is true if the user has a second-factor authentication + // mechanism properly set up. In practice, this is the case if either + // HasOTP is true, or len(U2FRegistrations) > 0. + Has2FA bool `json:"has_2fa"` + + // HasOTP is true if TOTP is set up. + HasOTP bool `json:"has_otp"` + + // HasEncryptionKeys is true if encryption keys are properly set up for + // this user. TODO: consider disabling it. + HasEncryptionKeys bool `json:"has_encryption_keys"` + PasswordRecoveryHint string `json:"password_recovery_hint"` AppSpecificPasswords []*AppSpecificPasswordInfo `json:"app_specific_passwords,omitempty"` - U2FRegistrations []*u2f.Registration `json:"u2f_registrations"` + U2FRegistrations []*u2f.Registration `json:"u2f_registrations,omitempty"` Resources []*Resource `json:"resources,omitempty"` }