From fb359cb9d58a4df610a7ff741b366be534eb69a9 Mon Sep 17 00:00:00 2001 From: Amir Raminfar Date: Tue, 23 Sep 2025 09:03:07 -0700 Subject: [PATCH] fix: if roles changed after a restart of Dozzle, then it resets user session (#4139) --- internal/auth/roles.go | 3 ++- internal/auth/simple.go | 3 ++- internal/auth/users.go | 11 ++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/auth/roles.go b/internal/auth/roles.go index 8bb5ed23..059b35bd 100644 --- a/internal/auth/roles.go +++ b/internal/auth/roles.go @@ -17,8 +17,9 @@ const ( const All = Shell | Actions | Download +// ParseRole parses a comma-separated string of roles and returns the corresponding Role. Default is All for empty input. func ParseRole(commaValues string) Role { - if commaValues == "" { + if strings.TrimSpace(commaValues) == "" { return All } diff --git a/internal/auth/simple.go b/internal/auth/simple.go index 8818820a..244c1b52 100644 --- a/internal/auth/simple.go +++ b/internal/auth/simple.go @@ -21,6 +21,7 @@ func NewSimpleAuth(userDatabase UserDatabase, ttl time.Duration) *simpleAuthCont h := sha256.New() for _, user := range userDatabase.Users { h.Write([]byte(user.Password)) + h.Write([]byte(user.RolesConfigured)) } tokenAuth := jwtauth.New("HS256", h.Sum(nil), nil) @@ -38,7 +39,7 @@ func (a *simpleAuthContext) CreateToken(username, password string) (string, erro return "", ErrInvalidCredentials } - claims := map[string]interface{}{"username": user.Username, "email": user.Email, "name": user.Name, "filter": user.Filter, "roles": user.RolesConfigured} + claims := map[string]interface{}{"username": user.Username, "email": user.Email, "name": user.Name, "filter": user.Filter, "roles": user.Roles} jwtauth.SetIssuedNow(claims) if a.ttl > 0 { diff --git a/internal/auth/users.go b/internal/auth/users.go index 43c742c2..96e7df5d 100644 --- a/internal/auth/users.go +++ b/internal/auth/users.go @@ -112,6 +112,8 @@ func decodeUsersFromFile(path string) (UserDatabase, error) { if user.Name == "" { user.Name = username } + + user.Roles = ParseRole(user.RolesConfigured) } return users, nil @@ -201,15 +203,18 @@ func UserFromContext(ctx context.Context) *User { email := claims["email"].(string) name := claims["name"].(string) containerFilter := container.ContainerLabels{} - roles := All + if filter, ok := claims["filter"].(string); ok { containerFilter, err = container.ParseContainerFilter(filter) if err != nil { log.Fatal().Err(err).Str("filter", filter).Msg("Failed to parse container filter") } } - if role, ok := claims["roles"].(string); ok { - roles = ParseRole(role) + roles := None + if r, ok := claims["roles"].(float64); ok { + roles = Role(r) + } else { + log.Warn().Interface("roles", claims["roles"]).Msg("Failed to parse roles from JWT claims") } user := newUser(username, email, name, containerFilter, roles)