Skip to content

jtblin/go-ldap-client

Repository files navigation

go-ldap-client

Go Reference Go Report Card CI codecov License: MIT GitHub release

Simple LDAP client for Go to authenticate users, retrieve basic information, and fetch groups.

Features

  • Modern Go: Supports Go modules and context.Context.
  • Security: Fixes unauthenticated bind (anonymous bind) vulnerabilities with empty passwords.
  • Resiliency: Supports multiple LDAP hosts with automatic failover.
  • Flexibility: Support for multi-valued attributes (e.g., memberOf).
  • Customization: Easily provide custom TLS configurations, Root CAs, or client certificates.
  • Testable: Extracting an interface for the LDAP connection for easy mocking in your applications.

Installation

go get github.com/jtblin/go-ldap-client/v2

Usage

Simple Authentication

package main

import (
	"log"

	"github.com/jtblin/go-ldap-client/v2"
)

func main() {
	client := &ldap.Client{
		Base:         "dc=example,dc=com",
		Host:         "ldap.example.com",
		Port:         389,
		UseSSL:       false,
		BindDN:       "uid=readonlyuser,ou=People,dc=example,dc=com",
		BindPassword: "readonlypassword",
		UserFilter:   "(uid=%s)",
		GroupFilter:  "(memberUid=%s)",
		Attributes:   []string{"givenName", "sn", "mail", "uid"},
	}
	// It is the responsibility of the caller to close the connection
	defer client.Close()

	ctx := context.Background()
	ok, user, err := client.Authenticate(ctx, "username", "password")
	if err != nil {
		log.Fatalf("Error authenticating user %s: %+v", "username", err)
	}
	if !ok {
		log.Fatalf("Authenticating failed for user %s", "username")
	}
	// User struct contains DN and Attributes
	log.Printf("User DN: %s", user.DN)
	log.Printf("User Attributes: %+v", user.Attributes)
	
	groups, err := client.GetGroupsOfUser(ctx, "username")
	if err != nil {
		log.Fatalf("Error getting groups for user %s: %+v", "username", err)
	}
	log.Printf("Groups: %+v", groups) 
}

Context Support & Multiple Hosts

All methods in v2.0.0+ require a context.Context as the first argument.

client := &ldap.Client{
    Base:               "dc=example,dc=com",
    Hosts:              []string{"ldap1.example.com", "ldap2.example.com"},
    Port:               636,
    UseSSL:             true,
    InsecureSkipVerify: false,
    ServerName:         "ldap.example.com",
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

ok, user, err := client.Authenticate(ctx, "username", "password")

Getting User Information (Search without password)

If you only need to retrieve user information or their DN without verifying a password:

user, err := client.GetUser(ctx, "username")
if err != nil {
    log.Fatal(err)
}
log.Printf("Found DN: %s", user.DN)

Custom TLS Configuration

tlsConfig := &tls.Config{
    RootCAs: myRootCAs,
}
client := &ldap.Client{
    // ...
    TLSConfig: tlsConfig,
}

Active Directory Configuration

For Active Directory, you typically need to use the user's sAMAccountName for searching and the full DN for group membership checks:

client := &ldap.Client{
    Base:         "dc=example,dc=org",
    Host:         "ad.example.org",
    Port:         389,
    BindDN:       "cn=readonly,ou=ServiceAccounts,dc=example,dc=org",
    BindPassword: "password",
    UserFilter:   "(sAMAccountName=%s)",
    // In v2.1.0+, you can use {dn} or {username} tokens in the GroupFilter.
    // For AD, you typically need the user's full DN.
    GroupFilter:  "(member={dn})", 
    Attributes:   []string{"sAMAccountName", "mail", "cn"},
}

Development

Prerequisites

  • Go 1.26+
  • Docker (for integration tests)

Commands

make setup  # Install development tools
make build  # Build the project
make test   # Run unit tests
make lint   # Run linters

Integration tests use Testcontainers to run a real LDAP server.

make test-integration

Documentation

Full documentation can be found on pkg.go.dev.

License

MIT

About

Simple ldap client to authenticate, retrieve basic information and groups for a user.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors