diff --git a/domain/auth/ldap/ad_test.go b/domain/auth/ldap/ad_test.go index 54254a86..f921e687 100644 --- a/domain/auth/ldap/ad_test.go +++ b/domain/auth/ldap/ad_test.go @@ -219,3 +219,80 @@ func TestADServer_Groups(t *testing.T) { } } } + +func TestADServer_Authenticate(t *testing.T) { + c := lm.LDAPConfig{} + c.ServerHost = "40.117.188.17" + c.ServerPort = 389 + c.EncryptionType = "none" + c.BaseDN = "DC=mycompany,DC=local" + c.BindDN = "CN=ad-admin,CN=Users,DC=mycompany,DC=local" + c.BindPassword = "8B5tNRLvbk8K" + c.UserFilter = "" + c.GroupFilter = "" + + address := fmt.Sprintf("%s:%d", c.ServerHost, c.ServerPort) + t.Log("Connecting to AD server", address) + l, err := ld.Dial("tcp", address) + if err != nil { + t.Error("Error: unable to dial AD server: ", err.Error()) + return + } + defer l.Close() + + if c.EncryptionType == "starttls" { + t.Log("Using StartTLS with AD server") + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Error("Error: unable to startTLS with AD server: ", err.Error()) + return + } + } + + // Authenticate with AD server using admin credentials. + t.Log("Binding AD admin user") + err = l.Bind(c.BindDN, c.BindPassword) + if err != nil { + t.Error("Error: unable to bind specified admin user to AD: ", err.Error()) + return + } + + username := `bob.johnson` + password := "Pass@word1!" + filter := fmt.Sprintf("(sAMAccountName=%s)", username) + + searchRequest := ld.NewSearchRequest( + c.BaseDN, + ld.ScopeWholeSubtree, ld.NeverDerefAliases, 0, 0, false, + filter, + []string{"mail"}, + nil, + ) + + t.Log("AD search filter:", filter) + sr, err := l.Search(searchRequest) + if err != nil { + t.Error("Error: unable to execute directory search: ", err.Error()) + return + } + + if len(sr.Entries) == 0 { + t.Error("Error: user not found") + return + } + if len(sr.Entries) != 1 { + t.Error("Error: too many users found during authentication") + return + } + + userdn := sr.Entries[0].DN + + // Bind as the user to verify their password + err = l.Bind(userdn, password) + if err != nil { + t.Error("Error: invalid credentials", err.Error()) + return + } + + t.Log("Authenticated", username) +} diff --git a/domain/auth/ldap/ldap_test.go b/domain/auth/ldap/ldap_test.go index ee022d1e..61299622 100644 --- a/domain/auth/ldap/ldap_test.go +++ b/domain/auth/ldap/ldap_test.go @@ -21,6 +21,8 @@ import ( ld "gopkg.in/ldap.v2" ) +// Works against https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/ + func TestPublicLDAPServer_UserList(t *testing.T) { c := lm.LDAPConfig{} c.ServerHost = "ldap.forumsys.com" @@ -215,6 +217,83 @@ func TestPublicLDAPServer_Groups(t *testing.T) { } } +func TestPublicLDAP_Authenticate(t *testing.T) { + c := lm.LDAPConfig{} + c.ServerHost = "ldap.forumsys.com" + c.ServerPort = 389 + c.EncryptionType = "none" + c.BaseDN = "dc=example,dc=com" + c.BindDN = "cn=read-only-admin,dc=example,dc=com" + c.BindPassword = "password" + c.UserFilter = "" + c.GroupFilter = "" + + address := fmt.Sprintf("%s:%d", c.ServerHost, c.ServerPort) + t.Log("Connecting to LDAP server", address) + l, err := ld.Dial("tcp", address) + if err != nil { + t.Error("Error: unable to dial AD server: ", err.Error()) + return + } + defer l.Close() + + if c.EncryptionType == "starttls" { + t.Log("Using StartTLS with LDAP server") + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Error("Error: unable to startTLS with LDAP server: ", err.Error()) + return + } + } + + // Authenticate with LDAP server using admin credentials. + t.Log("Binding LDAP admin user") + err = l.Bind(c.BindDN, c.BindPassword) + if err != nil { + t.Error("Error: unable to bind specified admin user to LDAP: ", err.Error()) + return + } + + username := "newton" + password := "password" + filter := fmt.Sprintf("(uid=%s)", username) + + searchRequest := ld.NewSearchRequest( + c.BaseDN, + ld.ScopeWholeSubtree, ld.NeverDerefAliases, 0, 0, false, + filter, + []string{"mail"}, + nil, + ) + + t.Log("LDAP search filter:", filter) + sr, err := l.Search(searchRequest) + if err != nil { + t.Error("Error: unable to execute directory search: ", err.Error()) + return + } + + if len(sr.Entries) == 0 { + t.Error("Error: user not found") + return + } + if len(sr.Entries) != 1 { + t.Error("Error: too many users found during authentication") + return + } + + userdn := sr.Entries[0].DN + + // Bind as the user to verify their password + err = l.Bind(userdn, password) + if err != nil { + t.Error("Error: invalid credentials", err.Error()) + return + } + + t.Log("Authenticated", username) +} + func TestLocalLDAPServer_AllUsers(t *testing.T) { c := lm.LDAPConfig{} c.ServerHost = "127.0.0.1"