diff --git a/connector/ldap/ldap.go b/connector/ldap/ldap.go
index 22b033aef77c54eb471d9b8ef98d40233363af4d..0558862625ccdbfb4f11df1ac226d901a6ca000c 100644
--- a/connector/ldap/ldap.go
+++ b/connector/ldap/ldap.go
@@ -2,17 +2,13 @@
 package ldap
 
 import (
-	"bytes"
 	"crypto/tls"
 	"crypto/x509"
-	"encoding/hex"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
 	"log"
 	"net"
-	"strings"
-	"unicode"
 
 	"gopkg.in/ldap.v2"
 
@@ -134,43 +130,6 @@ func parseScope(s string) (int, bool) {
 	return 0, false
 }
 
-// escapeRune maps a rune to a hex encoded value. For example 'é' would become '\\c3\\a9'
-func escapeRune(buff *bytes.Buffer, r rune) {
-	// Really inefficient, but it seems correct.
-	for _, b := range []byte(string(r)) {
-		buff.WriteString("\\")
-		buff.WriteString(hex.EncodeToString([]byte{b}))
-	}
-}
-
-// NOTE(ericchiang): There are no good documents on how to escape an LDAP string.
-// This implementation is inspired by an Oracle document, and is purposefully
-// extremely restrictive.
-//
-// See: https://docs.oracle.com/cd/E19424-01/820-4811/gdxpo/index.html
-func escapeFilter(s string) string {
-	r := strings.NewReader(s)
-	buff := new(bytes.Buffer)
-	for {
-		ru, _, err := r.ReadRune()
-		if err != nil {
-			// ignore decoding issues
-			return buff.String()
-		}
-
-		switch {
-		case ru > unicode.MaxASCII: // Not ASCII
-			escapeRune(buff, ru)
-		case !unicode.IsPrint(ru): // Not printable
-			escapeRune(buff, ru)
-		case strings.ContainsRune(`*\()`, ru): // Reserved characters
-			escapeRune(buff, ru)
-		default:
-			buff.WriteRune(ru)
-		}
-	}
-}
-
 // Open returns an authentication strategy using LDAP.
 func (c *Config) Open() (connector.Connector, error) {
 	conn, err := c.OpenConnector()
@@ -302,7 +261,7 @@ func (c *ldapConnector) Login(username, password string) (ident connector.Identi
 		user          ldap.Entry
 	)
 
-	filter := fmt.Sprintf("(%s=%s)", c.UserSearch.Username, escapeFilter(username))
+	filter := fmt.Sprintf("(%s=%s)", c.UserSearch.Username, ldap.EscapeFilter(username))
 	if c.UserSearch.Filter != "" {
 		filter = fmt.Sprintf("(&%s%s)", c.UserSearch.Filter, filter)
 	}
@@ -402,7 +361,7 @@ func (c *ldapConnector) Groups(ident connector.Identity) ([]string, error) {
 		return nil, fmt.Errorf("ldap: failed to unmarshal connector data: %v", err)
 	}
 
-	filter := fmt.Sprintf("(%s=%s)", c.GroupSearch.GroupAttr, escapeFilter(getAttr(user, c.GroupSearch.UserAttr)))
+	filter := fmt.Sprintf("(%s=%s)", c.GroupSearch.GroupAttr, ldap.EscapeFilter(getAttr(user, c.GroupSearch.UserAttr)))
 	if c.GroupSearch.Filter != "" {
 		filter = fmt.Sprintf("(&%s%s)", c.GroupSearch.Filter, filter)
 	}
diff --git a/connector/ldap/ldap_test.go b/connector/ldap/ldap_test.go
deleted file mode 100644
index 2a93e316687fe4ed2bef69c9d3143a152ced85ac..0000000000000000000000000000000000000000
--- a/connector/ldap/ldap_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package ldap
-
-import "testing"
-
-func TestEscapeFilter(t *testing.T) {
-	tests := []struct {
-		val  string
-		want string
-	}{
-		{"Five*Star", "Five\\2aStar"},
-		{"c:\\File", "c:\\5cFile"},
-		{"John (2nd)", "John \\282nd\\29"},
-		{string([]byte{0, 0, 0, 4}), "\\00\\00\\00\\04"},
-		{"Chloé", "Chlo\\c3\\a9"},
-	}
-
-	for _, tc := range tests {
-		got := escapeFilter(tc.val)
-		if tc.want != got {
-			t.Errorf("value %q want=%q, got=%q", tc.val, tc.want, got)
-		}
-	}
-}