diff --git a/connector/ldap/ldap.go b/connector/ldap/ldap.go index 4f58ab49..a7aa6c4f 100644 --- a/connector/ldap/ldap.go +++ b/connector/ldap/ldap.go @@ -107,6 +107,10 @@ type Config struct { IDAttr string `json:"idAttr"` // Defaults to "uid" EmailAttr string `json:"emailAttr"` // Defaults to "mail" NameAttr string `json:"nameAttr"` // No default. + + // If this is set, the email claim of the id token will be constructed from the idAttr and + // value of emailSuffix. This should not include the @ character. + EmailSuffix string `json:"emailSuffix"` // No default. } `json:"userSearch"` // Group search configuration. @@ -331,11 +335,6 @@ func (c *ldapConnector) identityFromEntry(user ldap.Entry) (ident connector.Iden if ident.UserID = getAttr(user, c.UserSearch.IDAttr); ident.UserID == "" { missing = append(missing, c.UserSearch.IDAttr) } - if ident.Email = getAttr(user, c.UserSearch.EmailAttr); ident.Email == "" { - missing = append(missing, c.UserSearch.EmailAttr) - } - // TODO(ericchiang): Let this value be set from an attribute. - ident.EmailVerified = true if c.UserSearch.NameAttr != "" { if ident.Username = getAttr(user, c.UserSearch.NameAttr); ident.Username == "" { @@ -343,6 +342,14 @@ func (c *ldapConnector) identityFromEntry(user ldap.Entry) (ident connector.Iden } } + if c.UserSearch.EmailSuffix != "" { + ident.Email = ident.Username + "@" + c.UserSearch.EmailSuffix + } else if ident.Email = getAttr(user, c.UserSearch.EmailAttr); ident.Email == "" { + missing = append(missing, c.UserSearch.EmailAttr) + } + // TODO(ericchiang): Let this value be set from an attribute. + ident.EmailVerified = true + if len(missing) != 0 { err := fmt.Errorf("ldap: entry %q missing following required attribute(s): %q", user.DN, missing) return connector.Identity{}, err diff --git a/connector/ldap/ldap_test.go b/connector/ldap/ldap_test.go index 95c2e0b3..6cbff68c 100644 --- a/connector/ldap/ldap_test.go +++ b/connector/ldap/ldap_test.go @@ -123,6 +123,68 @@ userpassword: bar runTests(t, schema, connectLDAP, c, tests) } +func TestQueryWithEmailSuffix(t *testing.T) { + schema := ` +dn: dc=example,dc=org +objectClass: dcObject +objectClass: organization +o: Example Company +dc: example + +dn: ou=People,dc=example,dc=org +objectClass: organizationalUnit +ou: People + +dn: cn=jane,ou=People,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +sn: doe +cn: jane +mail: janedoe@example.com +userpassword: foo + +dn: cn=john,ou=People,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +sn: doe +cn: john +userpassword: bar +` + c := &Config{} + c.UserSearch.BaseDN = "ou=People,dc=example,dc=org" + c.UserSearch.NameAttr = "cn" + c.UserSearch.EmailSuffix = "test.example.com" + c.UserSearch.IDAttr = "DN" + c.UserSearch.Username = "cn" + + tests := []subtest{ + { + name: "ignoremailattr", + username: "jane", + password: "foo", + want: connector.Identity{ + UserID: "cn=jane,ou=People,dc=example,dc=org", + Username: "jane", + Email: "jane@test.example.com", + EmailVerified: true, + }, + }, + { + name: "nomailattr", + username: "john", + password: "bar", + want: connector.Identity{ + UserID: "cn=john,ou=People,dc=example,dc=org", + Username: "john", + Email: "john@test.example.com", + EmailVerified: true, + }, + }, + } + + runTests(t, schema, connectLDAP, c, tests) +} + func TestGroupQuery(t *testing.T) { schema := ` dn: dc=example,dc=org