node-adauth
Fork of node-ldapauth-fork targeted towards use with an Active Directory domain.
Usage
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
.
Install
$ npm install adauth
ADAuth
Config Options
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
Configuration
-
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. (user@domain.com) -
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 attributes -
cache
- 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 documentation socketPath
timeout
connectTimeout
idleTimeout
strictDN
queueSize
queueTimeout
queueDisable
How it works
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
express/connect basicAuth example
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))
})
}
License
MIT