diff --git a/pkg/services/authn/clients/basic.go b/pkg/services/authn/clients/basic.go index d23b55f5285..edfb3859c8b 100644 --- a/pkg/services/authn/clients/basic.go +++ b/pkg/services/authn/clients/basic.go @@ -21,6 +21,10 @@ type Basic struct { client authn.PasswordClient } +func (c *Basic) String() string { + return c.Name() +} + func (c *Basic) Name() string { return authn.ClientBasic } diff --git a/pkg/services/authn/clients/grafana.go b/pkg/services/authn/clients/grafana.go index ee5c6f85b1d..067a1e5c8d1 100644 --- a/pkg/services/authn/clients/grafana.go +++ b/pkg/services/authn/clients/grafana.go @@ -26,6 +26,10 @@ type Grafana struct { userService user.Service } +func (c *Grafana) String() string { + return "grafana" +} + func (c *Grafana) AuthenticateProxy(ctx context.Context, r *authn.Request, username string, additional map[string]string) (*authn.Identity, error) { identity := &authn.Identity{ AuthModule: login.AuthProxyAuthModule, diff --git a/pkg/services/authn/clients/ldap.go b/pkg/services/authn/clients/ldap.go index 66b9c86e2f6..f2f546a96d3 100644 --- a/pkg/services/authn/clients/ldap.go +++ b/pkg/services/authn/clients/ldap.go @@ -27,6 +27,10 @@ type LDAP struct { service ldapService } +func (c *LDAP) String() string { + return "ldap" +} + func (c *LDAP) AuthenticateProxy(ctx context.Context, r *authn.Request, username string, _ map[string]string) (*authn.Identity, error) { info, err := c.service.User(username) if errors.Is(err, multildap.ErrDidNotFindUser) { diff --git a/pkg/services/authn/clients/password.go b/pkg/services/authn/clients/password.go index 50e76b4c35f..226cfdaaac5 100644 --- a/pkg/services/authn/clients/password.go +++ b/pkg/services/authn/clients/password.go @@ -4,6 +4,9 @@ import ( "context" "errors" + "github.com/hashicorp/go-multierror" + + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/authn" "github.com/grafana/grafana/pkg/services/loginattempt" "github.com/grafana/grafana/pkg/util/errutil" @@ -20,12 +23,13 @@ var ( var _ authn.PasswordClient = new(Password) func ProvidePassword(loginAttempts loginattempt.Service, clients ...authn.PasswordClient) *Password { - return &Password{loginAttempts, clients} + return &Password{loginAttempts, clients, log.New("authn.password")} } type Password struct { loginAttempts loginattempt.Service clients []authn.PasswordClient + log log.Logger } func (c *Password) AuthenticatePassword(ctx context.Context, r *authn.Request, username, password string) (*authn.Identity, error) { @@ -43,25 +47,22 @@ func (c *Password) AuthenticatePassword(ctx context.Context, r *authn.Request, u return nil, errEmptyPassword.Errorf("no password provided") } - var clientErr error + var clientErrs error for _, pwClient := range c.clients { - var identity *authn.Identity - identity, clientErr = pwClient.AuthenticatePassword(ctx, r, username, password) + identity, clientErr := pwClient.AuthenticatePassword(ctx, r, username, password) + clientErrs = multierror.Append(clientErrs, clientErr) // for invalid password or if the identity is not found by a client continue to next one - if errors.Is(clientErr, errInvalidPassword) || errors.Is(clientErr, errIdentityNotFound) { - continue - } - if clientErr != nil { - return nil, errPasswordAuthFailed.Errorf("failed to authenticate identity: %w", clientErr) + c.log.Warn("failed to authenticate password identity", "client", pwClient, "error", clientErr) + continue } return identity, nil } - if errors.Is(clientErr, errInvalidPassword) { + if errors.Is(clientErrs, errInvalidPassword) { _ = c.loginAttempts.Add(ctx, username, web.RemoteAddr(r.HTTPRequest)) } - return nil, errPasswordAuthFailed.Errorf("failed to authenticate identity: %w", clientErr) + return nil, errPasswordAuthFailed.Errorf("failed to authenticate identity: %w", clientErrs) }