mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:07:30 +00:00
fix: check password complexity policy and respect changeRequired on password change (#7884)
* fix: check password complexity policy on password change and respect require_change * pass changeRequired where available and add tests * fix requested changes --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -43,10 +43,10 @@ type Profile struct {
|
||||
|
||||
type Password struct {
|
||||
// Either you have to have permission, a password code or the old password to change
|
||||
PasswordCode *string
|
||||
OldPassword *string
|
||||
Password *string
|
||||
EncodedPasswordHash *string
|
||||
PasswordCode string
|
||||
OldPassword string
|
||||
Password string
|
||||
EncodedPasswordHash string
|
||||
|
||||
ChangeRequired bool
|
||||
}
|
||||
@@ -73,12 +73,12 @@ func (h *ChangeHuman) Validate(hasher *crypto.Hasher) (err error) {
|
||||
}
|
||||
|
||||
func (p *Password) Validate(hasher *crypto.Hasher) error {
|
||||
if p.EncodedPasswordHash != nil {
|
||||
if !hasher.EncodingSupported(*p.EncodedPasswordHash) {
|
||||
if p.EncodedPasswordHash != "" {
|
||||
if !hasher.EncodingSupported(p.EncodedPasswordHash) {
|
||||
return zerrors.ThrowInvalidArgument(nil, "USER-oz74onzvqr", "Errors.User.Password.NotSupported")
|
||||
}
|
||||
}
|
||||
if p.Password == nil && p.EncodedPasswordHash == nil {
|
||||
if p.Password == "" && p.EncodedPasswordHash == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-3klek4sbns", "Errors.User.Password.Empty")
|
||||
}
|
||||
return nil
|
||||
@@ -285,7 +285,7 @@ func (c *Commands) ChangeUserHuman(ctx context.Context, human *ChangeHuman, alg
|
||||
}
|
||||
}
|
||||
if human.Password != nil {
|
||||
cmds, err = c.changeUserPassword(ctx, cmds, existingHuman, human.Password, alg)
|
||||
cmds, err = c.changeUserPassword(ctx, cmds, existingHuman, human.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -370,57 +370,34 @@ func changeUserProfile(ctx context.Context, cmds []eventstore.Command, wm *UserV
|
||||
return cmds, err
|
||||
}
|
||||
|
||||
func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Command, wm *UserV2WriteModel, password *Password, alg crypto.EncryptionAlgorithm) ([]eventstore.Command, error) {
|
||||
func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Command, wm *UserV2WriteModel, password *Password) ([]eventstore.Command, error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.End() }()
|
||||
|
||||
// Either have a code to set the password
|
||||
if password.PasswordCode != nil {
|
||||
if err := crypto.VerifyCode(wm.PasswordCodeCreationDate, wm.PasswordCodeExpiry, wm.PasswordCode, *password.PasswordCode, alg); err != nil {
|
||||
return cmds, err
|
||||
}
|
||||
// if no verification is set, the user must have the permission to change the password
|
||||
verification := c.setPasswordWithPermission(wm.AggregateID, wm.ResourceOwner)
|
||||
// otherwise check the password code...
|
||||
if password.PasswordCode != "" {
|
||||
verification = c.setPasswordWithVerifyCode(wm.PasswordCodeCreationDate, wm.PasswordCodeExpiry, wm.PasswordCode, password.PasswordCode)
|
||||
}
|
||||
var encodedPassword string
|
||||
// or have the old password to change it
|
||||
if password.OldPassword != nil {
|
||||
// newly encode old password if no new and already encoded password is set
|
||||
pw := *password.OldPassword
|
||||
if password.Password != nil {
|
||||
pw = *password.Password
|
||||
}
|
||||
alreadyEncodedPassword, err := c.verifyAndUpdatePassword(ctx, wm.PasswordEncodedHash, *password.OldPassword, pw)
|
||||
if err != nil {
|
||||
return cmds, err
|
||||
}
|
||||
encodedPassword = alreadyEncodedPassword
|
||||
// ...or old password
|
||||
if password.OldPassword != "" {
|
||||
verification = c.checkCurrentPassword(password.Password, password.EncodedPasswordHash, password.OldPassword, wm.PasswordEncodedHash)
|
||||
}
|
||||
|
||||
// password already hashed in request
|
||||
if password.EncodedPasswordHash != nil {
|
||||
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.EncodedPasswordHash, "", password.ChangeRequired, true)
|
||||
if cmd != nil {
|
||||
return append(cmds, cmd), err
|
||||
}
|
||||
return cmds, err
|
||||
cmd, err := c.setPasswordCommand(
|
||||
ctx,
|
||||
&wm.Aggregate().Aggregate,
|
||||
wm.UserState,
|
||||
password.Password,
|
||||
password.EncodedPasswordHash,
|
||||
"",
|
||||
password.ChangeRequired,
|
||||
verification,
|
||||
)
|
||||
if cmd != nil {
|
||||
return append(cmds, cmd), err
|
||||
}
|
||||
// password already hashed in verify
|
||||
if encodedPassword != "" {
|
||||
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, encodedPassword, "", password.ChangeRequired, true)
|
||||
if cmd != nil {
|
||||
return append(cmds, cmd), err
|
||||
}
|
||||
return cmds, err
|
||||
}
|
||||
// password still to be hashed
|
||||
if password.Password != nil {
|
||||
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.Password, "", password.ChangeRequired, false)
|
||||
if cmd != nil {
|
||||
return append(cmds, cmd), err
|
||||
}
|
||||
return cmds, err
|
||||
}
|
||||
// no password changes necessary
|
||||
return cmds, nil
|
||||
return cmds, err
|
||||
}
|
||||
|
||||
func (c *Commands) userExistsWriteModel(ctx context.Context, userID string) (writeModel *UserV2WriteModel, err error) {
|
||||
|
Reference in New Issue
Block a user