Allow LDAP fallback for managed users

This commit is contained in:
Firehawk 2026-07-12 03:25:32 +09:30
parent 0fbc6946a7
commit a33e3c7f9b
2 changed files with 36 additions and 3 deletions

View File

@ -176,7 +176,7 @@ func Sources(ctx context.Context) []AuthSource {
func Authenticate(ctx context.Context, ds model.DataStore, sourceID, username, password string) (*model.User, error) {
if sourceID == "" || sourceID == "internal" {
u, found, err := authInternal(ctx, ds, username, password)
u, found, err := authInternal(ctx, ds, username, password, sourceID == "")
if err != nil || found {
return u, err
}
@ -205,7 +205,7 @@ func Authenticate(ctx context.Context, ds model.DataStore, sourceID, username, p
}
return nil, nil
}
func authInternal(ctx context.Context, ds model.DataStore, username, password string) (*model.User, bool, error) {
func authInternal(ctx context.Context, ds model.DataStore, username, password string, skipExternal bool) (*model.User, bool, error) {
u, err := ds.User(ctx).FindByUsernameWithPassword(username)
if errors.Is(err, model.ErrNotFound) {
return nil, false, nil
@ -213,6 +213,10 @@ func authInternal(ctx context.Context, ds model.DataStore, username, password st
if err != nil {
return nil, true, err
}
if skipExternal && u.AuthSource != "" {
log.Debug(ctx, "Skipping internal password check for externally managed user", "username", username, "authSource", u.AuthSource, "authSourceId", u.AuthSourceID)
return nil, false, nil
}
if u.Password != password {
return nil, true, nil
}

View File

@ -1,6 +1,11 @@
package ldapauth
import "testing"
import (
"testing"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/tests"
)
func TestLoginUserFilter(t *testing.T) {
t.Parallel()
@ -55,3 +60,27 @@ func TestDedupeStrings(t *testing.T) {
}
}
}
func TestAuthInternalSkipsExternalUsersForFallback(t *testing.T) {
t.Parallel()
repo := tests.CreateMockUserRepo()
repo.Data["firehawk"] = &model.User{ID: "1", UserName: "firehawk", Password: "generated", AuthSource: "ldap", AuthSourceID: "freeipa"}
ds := &tests.MockDataStore{MockedUser: repo}
user, found, err := authInternal(t.Context(), ds, "firehawk", "ldap-password", true)
if err != nil {
t.Fatalf("authInternal() unexpected error: %v", err)
}
if found || user != nil {
t.Fatalf("authInternal() found=%v user=%#v, want external user to be skipped for fallback", found, user)
}
user, found, err = authInternal(t.Context(), ds, "firehawk", "ldap-password", false)
if err != nil {
t.Fatalf("authInternal() unexpected error: %v", err)
}
if !found || user != nil {
t.Fatalf("authInternal() found=%v user=%#v, want explicit internal auth to stop", found, user)
}
}