2018-04-26 15:54:53 -07:00
'use strict' ;
exports = module . exports = {
2020-02-06 14:50:12 +01:00
passwordAuth : passwordAuth ,
tokenAuth : tokenAuth ,
2018-08-03 17:21:24 -07:00
2020-02-06 16:44:46 +01:00
authorize : authorize ,
2018-09-05 23:03:17 -07:00
websocketAuth : websocketAuth
2018-04-26 15:54:53 -07:00
} ;
var accesscontrol = require ( '../accesscontrol.js' ) ,
assert = require ( 'assert' ) ,
2019-10-22 21:16:00 -07:00
BoxError = require ( '../boxerror.js' ) ,
2019-11-20 19:48:40 +01:00
externalLdap = require ( '../externalldap.js' ) ,
2018-04-26 15:54:53 -07:00
HttpError = require ( 'connect-lastmile' ) . HttpError ,
2020-02-06 15:36:14 +01:00
users = require ( '../users.js' ) ,
speakeasy = require ( 'speakeasy' ) ;
2018-06-15 17:31:28 -07:00
2020-02-06 14:50:12 +01:00
function passwordAuth ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
2018-06-15 17:31:28 -07:00
2020-02-06 14:50:12 +01:00
if ( ! req . body . username || typeof req . body . username !== 'string' ) return next ( new HttpError ( 400 , 'A username must be non-empty string' ) ) ;
if ( ! req . body . password || typeof req . body . password !== 'string' ) return next ( new HttpError ( 400 , 'A password must be non-empty string' ) ) ;
const username = req . body . username ;
const password = req . body . password ;
2020-02-06 15:36:14 +01:00
function check2FA ( user ) {
assert . strictEqual ( typeof user , 'object' ) ;
if ( ! user . ghost && ! user . appPassword && user . twoFactorAuthenticationEnabled ) {
if ( ! req . body . totpToken ) return next ( new HttpError ( 401 , 'A totpToken must be provided' ) ) ;
let verified = speakeasy . totp . verify ( { secret : user . twoFactorAuthenticationSecret , encoding : 'base32' , token : req . body . totpToken , window : 2 } ) ;
if ( ! verified ) return next ( new HttpError ( 401 , 'Invalid totpToken' ) ) ;
}
req . user = user ;
next ( ) ;
}
2020-02-06 14:50:12 +01:00
function createAndVerifyUserIfNotExist ( identifier , password ) {
assert . strictEqual ( typeof identifier , 'string' ) ;
assert . strictEqual ( typeof password , 'string' ) ;
externalLdap . createAndVerifyUserIfNotExist ( identifier . toLowerCase ( ) , password , function ( error , result ) {
if ( error && error . reason === BoxError . BAD _STATE ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error && error . reason === BoxError . BAD _FIELD ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error && error . reason === BoxError . CONFLICT ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error && error . reason === BoxError . NOT _FOUND ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error && error . reason === BoxError . INVALID _CREDENTIALS ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2018-06-15 17:31:28 -07:00
2020-02-06 15:36:14 +01:00
check2FA ( result ) ;
2018-06-15 17:31:28 -07:00
} ) ;
2020-02-06 14:50:12 +01:00
}
2018-06-15 17:31:28 -07:00
2020-02-06 14:50:12 +01:00
if ( username . indexOf ( '@' ) === - 1 ) {
users . verifyWithUsername ( username , password , users . AP _WEBADMIN , function ( error , result ) {
if ( error && error . reason === BoxError . NOT _FOUND ) return createAndVerifyUserIfNotExist ( username , password ) ;
if ( error && error . reason === BoxError . INVALID _CREDENTIALS ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
if ( ! result ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2019-11-20 19:48:40 +01:00
2020-02-06 15:36:14 +01:00
check2FA ( result ) ;
2020-02-06 14:50:12 +01:00
} ) ;
} else {
users . verifyWithEmail ( username , password , users . AP _WEBADMIN , function ( error , result ) {
if ( error && error . reason === BoxError . NOT _FOUND ) return createAndVerifyUserIfNotExist ( username , password ) ;
if ( error && error . reason === BoxError . INVALID _CREDENTIALS ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
if ( ! result ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2018-06-15 17:31:28 -07:00
2020-02-06 15:36:14 +01:00
check2FA ( result ) ;
2020-02-06 14:50:12 +01:00
} ) ;
}
2018-06-15 17:31:28 -07:00
}
2020-02-06 14:50:12 +01:00
function tokenAuth ( req , res , next ) {
var token ;
// this determines the priority
if ( req . body && req . body . access _token ) token = req . body . access _token ;
if ( req . query && req . query . access _token ) token = req . query . access _token ;
if ( req . headers && req . headers . authorization ) {
var parts = req . headers . authorization . split ( ' ' ) ;
if ( parts . length == 2 ) {
var scheme = parts [ 0 ] ;
var credentials = parts [ 1 ] ;
2018-06-15 17:31:28 -07:00
2020-02-06 14:50:12 +01:00
if ( /^Bearer$/i . test ( scheme ) ) token = credentials ;
}
}
if ( ! token ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2020-02-06 16:44:46 +01:00
accesscontrol . verifyToken ( token , function ( error , user ) {
if ( error && error . reason === BoxError . INVALID _CREDENTIALS ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2020-02-06 14:50:12 +01:00
if ( error ) return next ( new HttpError ( 500 , error . message ) ) ;
req . user = user ;
next ( ) ;
} ) ;
2018-06-15 17:31:28 -07:00
}
2020-02-21 12:17:06 -08:00
function authorize ( requiredRole ) {
assert . strictEqual ( typeof requiredRole , 'string' ) ;
2018-04-26 15:54:53 -07:00
2020-02-06 14:50:12 +01:00
return function ( req , res , next ) {
2020-02-06 17:29:45 +01:00
assert . strictEqual ( typeof req . user , 'object' ) ;
2018-06-17 15:25:41 -07:00
2020-02-21 12:17:06 -08:00
if ( users . compareRoles ( req . user . role , requiredRole ) < 0 ) return next ( new HttpError ( 403 , ` role ' ${ requiredRole } ' is required but user has only ' ${ req . user . role } ' ` ) ) ;
2018-04-26 15:54:53 -07:00
2020-02-06 14:50:12 +01:00
next ( ) ;
} ;
2018-04-26 15:54:53 -07:00
}
2020-02-06 16:44:46 +01:00
function websocketAuth ( requiredRole , req , res , next ) {
assert . strictEqual ( typeof requiredRole , 'string' ) ;
2018-04-26 15:54:53 -07:00
if ( typeof req . query . access _token !== 'string' ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2020-02-06 16:44:46 +01:00
accesscontrol . verifyToken ( req . query . access _token , function ( error , user ) {
if ( error && error . reason === BoxError . INVALID _CREDENTIALS ) return next ( new HttpError ( 401 , 'Unauthorized' ) ) ;
2018-04-26 15:54:53 -07:00
if ( error ) return next ( new HttpError ( 500 , error . message ) ) ;
req . user = user ;
2020-02-21 12:17:06 -08:00
if ( users . compareRoles ( req . user . role , requiredRole ) < 0 ) return next ( new HttpError ( 403 , ` role ' ${ requiredRole } ' is required but user has only ' ${ user . role } ' ` ) ) ;
2018-04-26 15:54:53 -07:00
next ( ) ;
} ) ;
}