It should be possible to install ldap-client from Hackage:
$ cabal install ldap-client
or git:
$ git clone https://github.com/supki/ldap-client $ cabal install ldap-client/ldap-client.cabal
if you use GHC 7.6.1 or a newer version.
To get a feeling of ldap-client we will try and
log in into LDAP and change our password.
Before all that, though, here's the obligatory module header describing the language extensions and imports used later, so that you can follow along:
{-# LANGUAGE OverloadedStrings #-}
module Example where
import Ldap.Client as Ldap
The typical LDAP authentication routine has three steps:
We will encapsulate the first two steps in a separate function as it's a fairly self-contained operation:
findUser :: Ldap -> (Dn, Password) -> AttrValue -> IO (Maybe Dn)
findUser l (managerDn, managerPassword) userName = do
Ldap.bind l managerDn managerPassword
users <- Ldap.search l (Dn "dc=com,dc=example")
(typesOnly True)
(Attr "uid" := userName)
[]
case users of
SearchEntry userDn _ : _ -> return (Just userDn)
_ -> return Nothing
The third step uses the Dn we've got from findUser; we will
pass it through since it will be useful to changePassword.
login :: Ldap -> (Dn, Password) -> (AttrValue, Password) -> IO Dn
login l (managerDn, managerPassword) (userName, userPassword) = do
maybeUserDn <- findUser l (managerDn, managerPassword) userName
case maybeUserDn of
Nothing -> error "User not found!"
Just userDn -> do Ldap.bind l userDn userPassword
return userDn
Because we have been already bound as userName, we can simply modify
the relevant attribute in the Directory to change the password.
changePassword :: Ldap -> Dn -> AttrValue -> IO ()
changePassword l userDn userNewPassword =
Ldap.modify l userDn [Replace (Attr "userPassword") [userNewPassword]]
The only remaining task is to wrap login and
changePassword in Ldap.with.
loginAndChangePassword
:: (Dn, Password)
-> (AttrValue, Password, AttrValue)
-> IO (Either LdapError ())
loginAndChangePassword (managerDn, managerPassword)
(userName, userPassword, userNewPassword) =
Ldap.with (Secure "ldap.example.com") 636 $ \l -> do
dn <- login l (managerDn, managerPassword) (userName, userPassword)
changePassword l dn userNewPassword