Disallow LDAP bind if trap is set; support setting trap from user form

This commit is contained in:
garrettmills 2020-05-22 09:47:01 -05:00
parent 64356d42d0
commit decb83bdbb
No known key found for this signature in database
GPG Key ID: 6ACD58D6ADACFC6E
9 changed files with 77 additions and 4 deletions

View File

@ -2,7 +2,4 @@
- Forgot password handling
- Admin password reset mechanism -> flag users as needing PW resets
- OAuth2 -> support refresh tokens
- Traps
- Allow setting user trap from web UI
- Don't allow external logins if trap is set
- Trust token page -> force username of current user

View File

@ -0,0 +1,13 @@
import CRUDBase from '../CRUDBase.js'
class TrapResource extends CRUDBase {
endpoint = '/api/v1/auth/traps'
required_fields = ['name', 'trap', 'redirect_to']
permission_base = 'v1:auth:traps'
item = 'Trap'
plural = 'Traps'
}
const auth_trap = new TrapResource()
export { auth_trap }

View File

@ -99,6 +99,16 @@ class UserResource extends CRUDBase {
placeholder: 'Password',
required: ['insert'],
},
{
name: 'Trap',
field: 'trap',
type: 'select.dynamic',
options: {
resource: 'auth/Trap',
display: 'name',
value: 'trap',
},
},
],
}
}

View File

@ -7,6 +7,24 @@ class AuthController extends Controller {
return [...super.services, 'models', 'auth', 'MFA', 'output', 'configs', 'utility']
}
async get_traps(req, res, next) {
const trap_config = this.configs.get('traps')
const data = [{ name: '(None)', trap: '', redirect_to: '/' }]
for ( const name in trap_config.types ) {
if ( !trap_config.types.hasOwnProperty(name) ) continue
data.push({
name: name.replace(/_/g, ' ')
.split(' ')
.map(x => x.charAt(0).toUpperCase() + x.substr(1))
.join(' '),
trap: name,
redirect_to: trap_config.types[name].redirect_to
})
}
return res.api(data)
}
async registration(req, res, next) {
const User = this.models.get('auth:User')
const required_fields = ['first_name', 'last_name', 'uid', 'email']
@ -230,6 +248,15 @@ class AuthController extends Controller {
if ( req.body.tagline )
user.tagline = req.body.tagline
if ( req.body.trap ) {
if ( !req.trap.trap_exists(req.body.trap) )
return res.status(400)
.message('Invalid trap type.')
.api()
user.trap = req.body.trap
}
await user.reset_password(req.body.password, 'create')
await user.save()
return res.api(await user.to_api())
@ -340,6 +367,16 @@ class AuthController extends Controller {
else
user.tagline = ''
if ( req.body.trap ) {
if ( !req.trap.trap_exists(req.body.trap) )
return res.status(400)
.message('Invalid trap type.')
.api()
user.trap = req.body.trap
} else
user.trap = ''
await user.save()
return res.api()
}

View File

@ -90,6 +90,11 @@ class LDAPController extends Injectable {
return next(new LDAP.InvalidCredentialsError())
}
// Check if the resource has a trap. If so, deny access.
if ( item.trap ) {
return next(new LDAP.InvalidCredentialsError('This resource currently has a login trap set. Please visit the web UI to release.'))
}
this.output.info(`Successfully bound resource as DN: ${req.dn.format(this.configs.get('ldap:server.format'))}.`)
res.end()
return next()

View File

@ -77,6 +77,7 @@ class User extends AuthUser {
last_name: this.last_name,
email: this.email,
tagline: this.tagline,
trap: this.trap,
group_ids: (await this.groups()).map(x => x.id),
}
}

View File

@ -10,8 +10,8 @@
*/
const Middleware = [
"auth:Utility",
"Traps",
"auth:TrustTokenUtility",
"Traps",
"SAMLUtility",
// 'MiddlewareName',

View File

@ -48,6 +48,10 @@ class TrapUtility {
else if ( this.user ) return this.user.trap
}
trap_exists(name) {
return !!this.configs[name]
}
config() {
return this.configs[this.get_trap()]
}

View File

@ -8,6 +8,12 @@ const auth_routes = {
get: {
'/mfa/enable/date': ['middleware::auth:UserOnly', 'controller::api:v1:Auth.get_mfa_enable_date'],
'/traps': [
'middleware::auth:APIRoute',
['middleware::api:Permission', { check: 'v1:auth:traps:list'}],
'controller::api:v1:Auth.get_traps',
],
'/roles': [
'middleware::auth:APIRoute',
['middleware::api:Permission', { check: 'v1:auth:roles:list' }],