Files
go-hauk/auth/ldap.go
Arkadiy Kukarkin 725a673fb0 add auth layer
2025-12-23 12:23:32 +01:00

81 lines
1.5 KiB
Go

package auth
import (
"fmt"
"strings"
"github.com/go-ldap/ldap/v3"
)
type LDAPAuth struct {
uri string
baseDN string
bindDN string
bindPass string
userFilter string
startTLS bool
}
func NewLDAPAuth(uri, baseDN, bindDN, bindPass, userFilter string, startTLS bool) *LDAPAuth {
return &LDAPAuth{
uri: uri,
baseDN: baseDN,
bindDN: bindDN,
bindPass: bindPass,
userFilter: userFilter,
startTLS: startTLS,
}
}
func (l *LDAPAuth) Authenticate(user, pass string) error {
if pass == "" {
return ErrAuthFailed
}
conn, err := ldap.DialURL(l.uri)
if err != nil {
return fmt.Errorf("ldap connect: %w", err)
}
defer conn.Close()
if l.startTLS {
if err := conn.StartTLS(nil); err != nil {
return fmt.Errorf("ldap starttls: %w", err)
}
}
if err := conn.Bind(l.bindDN, l.bindPass); err != nil {
return fmt.Errorf("ldap admin bind: %w", err)
}
filter := strings.Replace(l.userFilter, "%s", ldap.EscapeFilter(user), 1)
req := ldap.NewSearchRequest(
l.baseDN,
ldap.ScopeWholeSubtree,
ldap.NeverDerefAliases,
0, 0, false,
filter,
[]string{"dn"},
nil,
)
res, err := conn.Search(req)
if err != nil {
return fmt.Errorf("ldap search: %w", err)
}
if len(res.Entries) == 0 {
return ErrAuthFailed
}
if len(res.Entries) > 1 {
return fmt.Errorf("ldap: ambiguous user filter matched %d users", len(res.Entries))
}
userDN := res.Entries[0].DN
if err := conn.Bind(userDN, pass); err != nil {
return ErrAuthFailed
}
return nil
}