fix(auth): harden tht auth mutations

This commit is contained in:
2026-08-16 19:37:12 +02:00
parent 9646ae09a0
commit 856ac05edc
6 changed files with 245 additions and 31 deletions
+18 -11
View File
@@ -166,23 +166,30 @@ func applyMutationInvariants(before Registry, after *Registry) error {
return errInvalidAuthenticationConfig
}
securityChanged := user.PasswordHash != old.PasswordHash || user.Enabled != old.Enabled || !sameRoles(user.Roles, old.Roles)
explicitLogoutAll := user.AuthRevision == old.AuthRevision+1
if user.AuthRevision != old.AuthRevision && !explicitLogoutAll {
revision, err := reconciledAuthRevision(old.AuthRevision, user.AuthRevision, securityChanged)
if err != nil {
return errInvalidAuthenticationConfig
}
if securityChanged && !explicitLogoutAll {
if old.AuthRevision == ^uint64(0) {
return errInvalidAuthenticationConfig
}
user.AuthRevision = old.AuthRevision + 1
}
if !securityChanged && !explicitLogoutAll {
user.AuthRevision = old.AuthRevision
}
user.AuthRevision = revision
}
return validateRegistry(*after)
}
// reconciledAuthRevision is the single authority for local-user security revisions. Security
// changes get one bump; a caller may also request exactly one explicit logout-all bump.
func reconciledAuthRevision(previous, requested uint64, securityChanged bool) (uint64, error) {
if requested != previous && (previous == ^uint64(0) || requested != previous+1) {
return 0, errInvalidAuthenticationConfig
}
if securityChanged && requested == previous {
if previous == ^uint64(0) {
return 0, errInvalidAuthenticationConfig
}
return previous + 1, nil
}
return requested, nil
}
func sameRoles(left, right []Role) bool {
if len(left) != len(right) {
return false