mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* structure dtos and private methods * add basic LDAP service * use LDAP service in ldap debug API * lower non fatal error * remove unused globals * wip * remove final globals * fix tests to use cfg enabled * restructure errors * remove logger from globals * use ldap service in authn * use ldap service in context handler * fix failed tests * fix ldap middleware provides * fix provides in auth_test.go
115 lines
3.5 KiB
Go
115 lines
3.5 KiB
Go
package login
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/services/ldap"
|
|
"github.com/grafana/grafana/pkg/services/login"
|
|
"github.com/grafana/grafana/pkg/services/loginattempt"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
var (
|
|
ErrEmailNotAllowed = errors.New("required email domain not fulfilled")
|
|
ErrInvalidCredentials = errors.New("invalid username or password")
|
|
ErrNoEmail = errors.New("login provider didn't return an email address")
|
|
ErrProviderDeniedRequest = errors.New("login provider denied login request")
|
|
ErrTooManyLoginAttempts = errors.New("too many consecutive incorrect login attempts for user - login for user temporarily blocked")
|
|
ErrPasswordEmpty = errors.New("no password provided")
|
|
ErrUserDisabled = errors.New("user is disabled")
|
|
ErrAbsoluteRedirectTo = errors.New("absolute URLs are not allowed for redirect_to cookie value")
|
|
ErrInvalidRedirectTo = errors.New("invalid redirect_to cookie value")
|
|
ErrForbiddenRedirectTo = errors.New("forbidden redirect_to cookie value")
|
|
ErrNoAuthProvider = errors.New("enable at least one login provider")
|
|
)
|
|
|
|
var loginLogger = log.New("login")
|
|
|
|
type Authenticator interface {
|
|
AuthenticateUser(context.Context, *login.LoginUserQuery) error
|
|
}
|
|
|
|
type AuthenticatorService struct {
|
|
loginService login.Service
|
|
loginAttemptService loginattempt.Service
|
|
userService user.Service
|
|
cfg *setting.Cfg
|
|
}
|
|
|
|
func ProvideService(store db.DB, loginService login.Service,
|
|
loginAttemptService loginattempt.Service,
|
|
userService user.Service, cfg *setting.Cfg) *AuthenticatorService {
|
|
a := &AuthenticatorService{
|
|
loginService: loginService,
|
|
loginAttemptService: loginAttemptService,
|
|
userService: userService,
|
|
cfg: cfg,
|
|
}
|
|
return a
|
|
}
|
|
|
|
// AuthenticateUser authenticates the user via username & password
|
|
func (a *AuthenticatorService) AuthenticateUser(ctx context.Context, query *login.LoginUserQuery) error {
|
|
ok, err := a.loginAttemptService.Validate(ctx, query.Username)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !ok {
|
|
return ErrTooManyLoginAttempts
|
|
}
|
|
|
|
if err := validatePasswordSet(query.Password); err != nil {
|
|
return err
|
|
}
|
|
|
|
isGrafanaLoginEnabled := !query.Cfg.DisableLogin
|
|
|
|
if isGrafanaLoginEnabled {
|
|
err = loginUsingGrafanaDB(ctx, query, a.userService)
|
|
}
|
|
|
|
if isGrafanaLoginEnabled && (err == nil || (!errors.Is(err, user.ErrUserNotFound) && !errors.Is(err, ErrInvalidCredentials) &&
|
|
!errors.Is(err, ErrUserDisabled))) {
|
|
query.AuthModule = "grafana"
|
|
return err
|
|
}
|
|
|
|
ldapEnabled, ldapErr := loginUsingLDAP(ctx, query, a.loginService, a.cfg)
|
|
if ldapEnabled {
|
|
query.AuthModule = login.LDAPAuthModule
|
|
if ldapErr == nil || !errors.Is(ldapErr, ldap.ErrInvalidCredentials) {
|
|
return ldapErr
|
|
}
|
|
|
|
if !errors.Is(err, ErrUserDisabled) || !errors.Is(ldapErr, ldap.ErrInvalidCredentials) {
|
|
err = ldapErr
|
|
}
|
|
}
|
|
|
|
if errors.Is(err, ErrInvalidCredentials) || errors.Is(err, ldap.ErrInvalidCredentials) {
|
|
if err := a.loginAttemptService.Add(ctx, query.Username, query.IpAddress); err != nil {
|
|
loginLogger.Error("Failed to save invalid login attempt", "err", err)
|
|
}
|
|
|
|
return ErrInvalidCredentials
|
|
}
|
|
|
|
if !isGrafanaLoginEnabled && !ldapEnabled {
|
|
return ErrNoAuthProvider
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func validatePasswordSet(password string) error {
|
|
if len(password) == 0 {
|
|
return ErrPasswordEmpty
|
|
}
|
|
|
|
return nil
|
|
}
|