mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 11:34:26 +00:00
586495a0be
Add management functionality for LDAP idps with templates and the basic functionality for the LDAP provider, which can then be used with a separate login page in the future. --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
99 lines
2.5 KiB
Go
99 lines
2.5 KiB
Go
package ldap
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/go-ldap/ldap/v3"
|
|
"golang.org/x/text/language"
|
|
|
|
"github.com/zitadel/zitadel/internal/idp"
|
|
)
|
|
|
|
var ErrNoSingleUser = errors.New("user does not exist or too many entries returned")
|
|
|
|
var _ idp.Session = (*Session)(nil)
|
|
|
|
type Session struct {
|
|
Provider *Provider
|
|
loginUrl string
|
|
user string
|
|
password string
|
|
}
|
|
|
|
func (s *Session) GetAuthURL() string {
|
|
return s.loginUrl
|
|
}
|
|
func (s *Session) FetchUser(_ context.Context) (idp.User, error) {
|
|
l, err := ldap.DialURL("ldap://" + s.Provider.host + ":" + s.Provider.port)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer l.Close()
|
|
|
|
if s.Provider.tls {
|
|
err = l.StartTLS(&tls.Config{ServerName: s.Provider.host})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// Bind as the admin to search for user
|
|
err = l.Bind("cn="+s.Provider.admin+","+s.Provider.baseDN, s.Provider.password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Search for user with the unique attribute for the userDN
|
|
searchRequest := ldap.NewSearchRequest(
|
|
s.Provider.baseDN,
|
|
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
|
fmt.Sprintf("(&(objectClass="+s.Provider.userObjectClass+")("+s.Provider.userUniqueAttribute+"=%s))", ldap.EscapeFilter(s.user)),
|
|
[]string{"dn"},
|
|
nil,
|
|
)
|
|
|
|
sr, err := l.Search(searchRequest)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(sr.Entries) != 1 {
|
|
return nil, ErrNoSingleUser
|
|
}
|
|
|
|
user := sr.Entries[0]
|
|
// Bind as the user to verify their password
|
|
err = l.Bind(user.DN, s.password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
emailVerified, err := strconv.ParseBool(user.GetAttributeValue(s.Provider.emailVerifiedAttribute))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
phoneVerified, err := strconv.ParseBool(user.GetAttributeValue(s.Provider.phoneVerifiedAttribute))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return NewUser(
|
|
user.GetAttributeValue(s.Provider.idAttribute),
|
|
user.GetAttributeValue(s.Provider.firstNameAttribute),
|
|
user.GetAttributeValue(s.Provider.lastNameAttribute),
|
|
user.GetAttributeValue(s.Provider.displayNameAttribute),
|
|
user.GetAttributeValue(s.Provider.nickNameAttribute),
|
|
user.GetAttributeValue(s.Provider.preferredUsernameAttribute),
|
|
user.GetAttributeValue(s.Provider.emailAttribute),
|
|
emailVerified,
|
|
user.GetAttributeValue(s.Provider.phoneAttribute),
|
|
phoneVerified,
|
|
language.Make(user.GetAttributeValue(s.Provider.preferredLanguageAttribute)),
|
|
user.GetAttributeValue(s.Provider.avatarURLAttribute),
|
|
user.GetAttributeValue(s.Provider.profileAttribute),
|
|
), nil
|
|
}
|