Disallow LDAP bind if trap is set; support setting trap from user form
This commit is contained in:
parent
64356d42d0
commit
decb83bdbb
@ -2,7 +2,4 @@
|
|||||||
- Forgot password handling
|
- Forgot password handling
|
||||||
- Admin password reset mechanism -> flag users as needing PW resets
|
- Admin password reset mechanism -> flag users as needing PW resets
|
||||||
- OAuth2 -> support refresh tokens
|
- 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
|
- Trust token page -> force username of current user
|
||||||
|
13
app/assets/app/resource/auth/Trap.resource.js
Normal file
13
app/assets/app/resource/auth/Trap.resource.js
Normal 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 }
|
@ -99,6 +99,16 @@ class UserResource extends CRUDBase {
|
|||||||
placeholder: 'Password',
|
placeholder: 'Password',
|
||||||
required: ['insert'],
|
required: ['insert'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Trap',
|
||||||
|
field: 'trap',
|
||||||
|
type: 'select.dynamic',
|
||||||
|
options: {
|
||||||
|
resource: 'auth/Trap',
|
||||||
|
display: 'name',
|
||||||
|
value: 'trap',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,24 @@ class AuthController extends Controller {
|
|||||||
return [...super.services, 'models', 'auth', 'MFA', 'output', 'configs', 'utility']
|
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) {
|
async registration(req, res, next) {
|
||||||
const User = this.models.get('auth:User')
|
const User = this.models.get('auth:User')
|
||||||
const required_fields = ['first_name', 'last_name', 'uid', 'email']
|
const required_fields = ['first_name', 'last_name', 'uid', 'email']
|
||||||
@ -230,6 +248,15 @@ class AuthController extends Controller {
|
|||||||
if ( req.body.tagline )
|
if ( req.body.tagline )
|
||||||
user.tagline = 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.reset_password(req.body.password, 'create')
|
||||||
await user.save()
|
await user.save()
|
||||||
return res.api(await user.to_api())
|
return res.api(await user.to_api())
|
||||||
@ -340,6 +367,16 @@ class AuthController extends Controller {
|
|||||||
else
|
else
|
||||||
user.tagline = ''
|
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()
|
await user.save()
|
||||||
return res.api()
|
return res.api()
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,11 @@ class LDAPController extends Injectable {
|
|||||||
return next(new LDAP.InvalidCredentialsError())
|
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'))}.`)
|
this.output.info(`Successfully bound resource as DN: ${req.dn.format(this.configs.get('ldap:server.format'))}.`)
|
||||||
res.end()
|
res.end()
|
||||||
return next()
|
return next()
|
||||||
|
@ -77,6 +77,7 @@ class User extends AuthUser {
|
|||||||
last_name: this.last_name,
|
last_name: this.last_name,
|
||||||
email: this.email,
|
email: this.email,
|
||||||
tagline: this.tagline,
|
tagline: this.tagline,
|
||||||
|
trap: this.trap,
|
||||||
group_ids: (await this.groups()).map(x => x.id),
|
group_ids: (await this.groups()).map(x => x.id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
*/
|
*/
|
||||||
const Middleware = [
|
const Middleware = [
|
||||||
"auth:Utility",
|
"auth:Utility",
|
||||||
"Traps",
|
|
||||||
"auth:TrustTokenUtility",
|
"auth:TrustTokenUtility",
|
||||||
|
"Traps",
|
||||||
"SAMLUtility",
|
"SAMLUtility",
|
||||||
|
|
||||||
// 'MiddlewareName',
|
// 'MiddlewareName',
|
||||||
|
@ -48,6 +48,10 @@ class TrapUtility {
|
|||||||
else if ( this.user ) return this.user.trap
|
else if ( this.user ) return this.user.trap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trap_exists(name) {
|
||||||
|
return !!this.configs[name]
|
||||||
|
}
|
||||||
|
|
||||||
config() {
|
config() {
|
||||||
return this.configs[this.get_trap()]
|
return this.configs[this.get_trap()]
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,12 @@ const auth_routes = {
|
|||||||
get: {
|
get: {
|
||||||
'/mfa/enable/date': ['middleware::auth:UserOnly', 'controller::api:v1:Auth.get_mfa_enable_date'],
|
'/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': [
|
'/roles': [
|
||||||
'middleware::auth:APIRoute',
|
'middleware::auth:APIRoute',
|
||||||
['middleware::api:Permission', { check: 'v1:auth:roles:list' }],
|
['middleware::api:Permission', { check: 'v1:auth:roles:list' }],
|
||||||
|
Loading…
Reference in New Issue
Block a user