SAML; Dashboard

This commit is contained in:
garrettmills
2020-05-03 20:16:54 -05:00
parent e3ecfb0d37
commit c389e151b5
1778 changed files with 148410 additions and 82 deletions

View File

@@ -9,7 +9,7 @@ class LDAPController extends Injectable {
check_attribute = 'ldap_visible' // or false
static get services() {
return [...super.services, 'ldap_server', 'ldap_dn_format']
return [...super.services, 'ldap_server', 'configs']
}
async compare(req, res, next) {
@@ -24,7 +24,7 @@ class LDAPController extends Injectable {
}
// Make sure it has the requested attribute
const value = item.to_ldap()[req.attribute]
const value = (await item.to_ldap())[req.attribute]
if ( typeof value === 'undefined' ) {
return next(new LDAP.NoSuchAttributeError())
}
@@ -42,26 +42,55 @@ class LDAPController extends Injectable {
// Make sure the DN is valid
if ( !req.dn.childOf(auth_dn) ) {
this.output.debug(`Bind failure: ${req.dn} not in ${auth_dn}`)
return next(new LDAP.InvalidCredentialsError('Cannot bind to DN outsize of the authentication base.'))
}
// Get the item
const item = await this.get_resource_from_dn(req.dn)
if ( !item ) {
this.output.debug(`Bind failure: ${req.dn} not found`)
return next(new LDAP.NoSuchObject())
}
// If the object is can-able, make sure it can bind
if ( typeof item.can === 'function' && !item.can('ldap:bind') ) {
this.output.debug(`Bind failure: User not allowed to bind`)
return next(new LDAP.InsufficientAccessRightsError())
}
// Make sure the password matches the resource record
if ( !await item.check_password(req.credentials) ) {
// Check if the credentials are an app_password
const app_password_verified = Array.isArray(item.app_passwords)
&& item.app_passwords.length > 0
&& await item.check_app_password(req.credentials)
// Check if the user has MFA enabled.
// If so, split the incoming password to fetch the MFA code
// e.g. normalPassword:123456
if ( !app_password_verified && item.mfa_enabled ) {
const parts = req.credentials.split(':')
const mfa_code = parts.pop()
const actual_password = parts.join(':')
// Check the credentials
if ( !await item.check_password(actual_password) ) {
this.output.debug(`Bind failure: user w/ MFA provided invalid credentials`)
return next(new LDAP.InvalidCredentialsError('Invalid credentials. Make sure MFA code is included at the end of your password (e.g. password:123456)'))
}
// Now, check the MFA code
if ( !item.mfa_token.verify(mfa_code) ) {
this.output.debug(`Bind failure: user w/ MFA provided invalid MFA token`)
return next(new LDAP.InvalidCredentialsError('Invalid credentials. Verification of the MFA token failed.'))
}
// If not MFA, just check the credentials
} else if (!app_password_verified && !await item.check_password(req.credentials)) {
this.output.debug(`Bind failure: user w/ simple auth provided invalid credentials`)
return next(new LDAP.InvalidCredentialsError())
}
this.output.success(`Successfully bound resource as DN: ${req.dn.format(this.ldap_dn_format)}.`)
this.output.info(`Successfully bound resource as DN: ${req.dn.format(this.configs.get('ldap:server.format'))}.`)
res.end()
return next()
}
@@ -76,8 +105,8 @@ class LDAPController extends Injectable {
// Make sure it's a parent of the request DN
if ( !base_dn.parentOf(req.dn) ) {
this.output.warn(`Attempted to perform resource deletion on invalid DN: ${req.dn.format(this.ldap_dn_format)}`)
return next(new LDAP.InsufficientAccessRightsError(`Target DN must be a member of the base DN: ${base_dn.format(this.ldap_dn_format)}.`))
this.output.warn(`Attempted to perform resource deletion on invalid DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
return next(new LDAP.InsufficientAccessRightsError(`Target DN must be a member of the base DN: ${base_dn.format(this.configs.get('ldap:server.format'))}.`))
}
// Fetch the resource (error if not found)