Fork of node-ldapauth-fork targeted towards use with an Active Directory domain.
import ADAuth from 'adauth'
const options = {
url: 'ldaps://corp.example.com:636',
domainDN: 'dc=example,dc=com',
}
const auth = await ADAuth.create(options)
// or
const auth = new ADAuth(options)
await auth.initialise()
try {
const user = await auth.authenticate(username, password)
} catch (error) {
console.error('Authentication failed: ', error)
}
await auth.dispose()
ADAuth
inherits from EventEmitter
.
$ npm install adauth
Required client options:
url
- LLDAP url for the AD domain controller, e.g.ldaps://corp.example.com:636
domainDN
- The root DN of the AD domain, e.g.dc=corp,dc=example,dc=com
searchBase
- The base DN from which to search for users by username. E.g.ou=users,dc=example,dc=com
searchFilterByDN
- Optional, default(&(objectCategory=user)(objectClass=user)(distinguishedName={{dn}}))
. Search filter with which to find a user by FQDN.searchFilterByUPN
- Optional, default(&(objectCategory=user)(objectClass=user)(userPrincipalName={{upn}}))
. Search filter with which to find a user by UPN. ([email protected])searchFilterBySAN
- Optional, default(&(objectCategory=user)(objectClass=user)(samAccountName={{username}}))
. Search filter with which to find a user by their old-format Windows username.searchAttributes
- Optional, default all. Array of attributes to fetch from LDAP server.bindProperty
- Optional, defaultdn
. Property of the LDAP user object to use when binding to verify the password. E.g.name
,email
searchScope
- Optional, defaultsub
. Scope of the search, one ofbase
,one
, orsub
.
adauth can look for valid user groups too. Related options:
groupSearchBase
- Optional. The base DN from which to search for groups. If defined, alsogroupSearchFilter
must be defined for the search to work.groupSearchFilter
- Optional. LDAP search filter for groups. Place literal{{dn}}
in the filter to have it replaced by the property defined withgroupDnProperty
of the found user object.{{username}}
is also available and will be replaced with theuid
of the found user. This is useful for example to filter PosixGroups bymemberUid
. Optionally you can also assign a function instead. The found user is passed to the function and it should return a valid search filter for the group search.groupSearchAttributes
- Optional, default all. Array of attributes to fetch from LDAP server.groupDnProperty
- Optional, defaultdn
. The property of user object to use in{{dn}}
interpolation ofgroupSearchFilter
.groupSearchScope
- Optional, defaultsub
.
Other adauth options:
includeRaw
- Optional, default false. Set to true to add property_raw
containing the original buffers to the returned user object. Useful when you need to handle binary attributescache
- Optional, default false. If true, then up to 100 credentials at a time will be cached for 5 minutes.log
- Bunyan logger instance, optional. If given this will result in TRACE-level error logging for component:ldapauth. The logger is also passed forward to ldapjs.
Optional ldapjs options, see ldapjs documentation:
tlsOptions
- Needed for TLS connection. See Node.js documentationsocketPath
timeout
connectTimeout
idleTimeout
strictDN
queueSize
queueTimeout
queueDisable
The AD authentication flow is usually:
- Bind the client using the given username and credentials to verify the given password
- Use the client to search for the user by substituting
{{username}}
from the appropriatesearchFilter
- Search for the groups of the user
import basicAuth from 'basic-auth'
import ADAuth from 'adauth'
const ad = await ADAuth.create({
url: "ldaps://corp.example.com:636",
domainDN: "DC=example,DC=com",
searchBase: "OU=Users,OU=MyBusiness,DC=example,DC=com",
tlsOptions: {
ca: "./example-ca.cer",
},
reconnect: true,
})
const rejectBasicAuth = res => {
res.statusCode = 401
res.setHeader('WWW-Authenticate', 'Basic realm="Example"')
res.end('Access denied')
}
const basicAuthMiddleware = (req, res, next) => {
const credentials = basicAuth(req)
if (!credentials) {
return rejectBasicAuth(res)
}
ad.authenticate(credentials.name, credentials.pass)
.then(user => {
req.user = user
next()
})
.catch(error => rejectBasicAuth(res))
})
}
MIT