Shinobi/libs/auth.js

280 lines
11 KiB
JavaScript
Raw Normal View History

2018-10-03 22:06:08 +00:00
var fs = require('fs');
2018-09-28 05:37:08 +00:00
module.exports = function(s,config,lang){
//Authenticator functions
s.api = {}
2018-10-06 04:33:51 +00:00
s.superUsersApi = {}
s.factorAuth = {}
2018-09-28 05:37:08 +00:00
s.failedLoginAttempts = {}
2019-07-08 03:40:02 +00:00
//
2019-07-08 04:02:08 +00:00
var getUserByUid = function(params,columns,callback){
2019-07-08 03:01:16 +00:00
if(!columns)columns = '*'
s.sqlQuery(`SELECT ${columns} FROM Users WHERE uid=? AND ke=?`,[params.uid,params.ke],function(err,r){
if(!r)r = []
var user = r[0]
callback(err,user)
})
}
var getUserBySessionKey = function(params,callback){
s.sqlQuery('SELECT * FROM Users WHERE auth=? AND ke=?',[params.auth,params.ke],function(err,r){
if(!r)r = []
var user = r[0]
callback(err,user)
})
}
var loginWithUsernameAndPassword = function(params,columns,callback){
if(!columns)columns = '*'
s.sqlQuery(`SELECT ${columns} FROM Users WHERE mail=? AND (pass=? OR pass=?) LIMIT 1`,[params.username,params.password,s.createHash(params.password)],function(err,r){
if(!r)r = []
var user = r[0]
callback(err,user)
})
}
var getApiKey = function(params,columns,callback){
if(!columns)columns = '*'
s.sqlQuery(`SELECT ${columns} FROM API WHERE code=? AND ke=?`,[params.auth,params.ke],function(err,r){
if(!r)r = []
var apiKey = r[0]
callback(err,apiKey)
})
}
var loginWithApiKey = function(params,callback){
getApiKey(params,'*',function(err,apiKey){
var isSessionKey = false
if(apiKey){
2019-07-08 04:27:30 +00:00
var sessionKey = createSession(apiKey,{
2019-07-08 03:01:16 +00:00
auth: params.auth,
permissions: s.parseJSON(apiKey.details),
2019-07-08 03:01:16 +00:00
details: {}
})
getUserByUid(apiKey,'mail,details',function(err,user){
if(user){
try{
2019-07-08 04:27:30 +00:00
editSession({
auth: sessionKey
},{
2019-07-08 03:01:16 +00:00
mail: user.mail,
details: s.parseJSON(user.details),
2019-07-08 04:08:52 +00:00
lang: s.getLanguageFile(user.details.lang)
2019-07-08 03:01:16 +00:00
})
}catch(er){
console.log(er)
}
}
callback(err,s.api[params.auth])
})
}else{
getUserBySessionKey(params,function(err,user){
if(user){
isSessionKey = true
createSession(apiKey,{
2019-07-08 03:58:33 +00:00
details: JSON.parse(user.details),
2019-07-08 03:01:16 +00:00
permissions: {}
})
callback(err,user,isSessionKey)
}
})
}
})
}
var createSession = function(user,additionalData){
if(user){
2019-07-08 04:27:30 +00:00
var generatedId = s.gid(20)
2019-07-08 03:01:16 +00:00
if(!additionalData)additionalData = {}
if(!user.ip)user.ip = '0.0.0.0'
if(!user.auth)user.auth = generatedId
2019-07-08 03:01:16 +00:00
user.details = JSON.parse(user.details)
user.permissions = {}
s.api[user.auth] = Object.assign(user,additionalData)
2019-07-08 04:27:30 +00:00
return generatedId
2019-07-08 03:01:16 +00:00
}
}
var editSession = function(user,additionalData){
if(user){
if(!additionalData)additionalData = {}
Object.keys(additionalData).forEach(function(value,key){
s.api[user.auth][key] = value
})
}
}
var failHttpAuthentication = function(res,req,message){
if(!message)message = lang['Not Authorized']
res.end(s.prettyPrint({
ok: false,
2019-07-08 04:05:02 +00:00
msg: message
2019-07-08 03:01:16 +00:00
}))
}
var resetActiveSessionTimer = function(activeSession){
if(activeSession){
clearTimeout(activeSession.timeout)
activeSession.timeout = setTimeout(function(){
delete(activeSession)
},1000 * 60 * 5)
}
2019-07-08 03:01:16 +00:00
}
s.auth = function(params,onSuccessComplete,res,req){
2018-09-28 05:37:08 +00:00
if(req){
//express (http server) use of auth function
2019-07-08 03:01:16 +00:00
params.ip = req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress
var onFail = function(message){
failHttpAuthentication(res,req,message)
2018-09-28 05:37:08 +00:00
}
}else{
//socket.io use of auth function
2019-07-08 03:01:16 +00:00
var onFail = function(){
2018-09-28 05:37:08 +00:00
//maybe log
}
}
2019-07-08 03:01:16 +00:00
var onSuccess = function(user){
var activeSession = s.api[params.auth]
if(
activeSession &&
(
activeSession.ip.indexOf('0.0.0.0') > -1 ||
activeSession.ip.indexOf(params.ip) > -1
)
2019-07-08 03:01:16 +00:00
){
if(!user.lang){
var details = s.parseJSON(user.details).lang
user.lang = s.getDefinitonFile(user.details.lang) || s.copySystemDefaultLanguage()
}
2019-07-08 03:01:16 +00:00
onSuccessComplete(user)
2018-09-28 05:37:08 +00:00
}else{
2019-07-08 03:01:16 +00:00
onFail()
2018-09-28 05:37:08 +00:00
}
}
2019-07-08 03:01:16 +00:00
if(s.group[params.ke] && s.group[params.ke].users && s.group[params.ke].users[params.auth]){
var activeSession = s.group[params.ke].users[params.auth]
activeSession.permissions = {}
if(!activeSession.lang){
activeSession.lang = s.copySystemDefaultLanguage()
}
2019-07-08 03:01:16 +00:00
onSuccessComplete(activeSession)
2018-09-28 05:37:08 +00:00
}else{
2019-07-08 03:01:16 +00:00
if(s.api[params.auth] && s.api[params.auth].details){
var activeSession = s.api[params.auth]
onSuccess(activeSession)
if(activeSession.timeout){
resetActiveSessionTimer(activeSession)
2018-09-28 05:37:08 +00:00
}
}else{
2019-07-08 03:01:16 +00:00
if(params.username && params.username !== '' && params.password && params.password !== ''){
loginWithUsernameAndPassword(params,'*',function(err,user){
if(user){
params.auth = user.auth
createSession(user)
2019-07-08 03:01:16 +00:00
resetActiveSessionTimer(s.api[params.auth])
onSuccess(user)
2018-09-28 05:37:08 +00:00
}else{
2019-07-08 03:01:16 +00:00
onFail()
2018-09-28 05:37:08 +00:00
}
})
}else{
2019-07-08 03:01:16 +00:00
loginWithApiKey(params,function(err,user,isSessionKey){
if(isSessionKey)resetActiveSessionTimer(s.api[params.auth])
if(user){
onSuccess(s.api[params.auth])
2018-09-28 05:37:08 +00:00
}else{
2019-07-08 03:01:16 +00:00
onFail()
2018-09-28 05:37:08 +00:00
}
})
}
}
}
}
//super user authentication handler
2018-10-05 21:19:29 +00:00
s.superAuth = function(params,callback,res,req){
2018-10-03 22:06:08 +00:00
var userFound = false
2018-10-05 21:19:29 +00:00
var userSelected = false
var adminUsersSelected = null
2018-10-03 22:06:08 +00:00
try{
var success = function(){
var chosenConfig = config
if(req && res){
chosenConfig = s.getConfigWithBranding(req.hostname)
2019-07-08 03:01:16 +00:00
res.setHeader('Content-Type', 'application/json')
var ip = req.headers['cf-connecting-ip']||req.headers["CF-Connecting-IP"]||req.headers["'x-forwarded-for"]||req.connection.remoteAddress;
var resp = {
ok: userFound,
ip: ip
}
if(userFound === false){
resp.msg = lang['Not Authorized']
res.end(s.prettyPrint(resp))
}
if(userSelected){
resp.$user = userSelected
}
if(adminUsersSelected){
resp.users = adminUsersSelected
}
}
callback({
ip : ip,
2019-07-08 03:40:02 +00:00
$user: userSelected,
users: adminUsersSelected,
config: chosenConfig,
lang:lang
})
}
2018-10-06 04:33:51 +00:00
var foundUser = function(){
if(params.users === true){
s.sqlQuery('SELECT * FROM Users WHERE details NOT LIKE ?',['%"sub"%'],function(err,r) {
adminUsersSelected = r
success()
2018-10-06 04:33:51 +00:00
})
}else{
success()
2018-09-28 05:37:08 +00:00
}
2018-10-06 04:33:51 +00:00
}
if(params.auth && s.superUsersApi[params.auth]){
userFound = true
userSelected = s.superUsersApi[params.auth].$user
foundUser()
}else{
var superUserList = JSON.parse(fs.readFileSync(s.location.super))
superUserList.forEach(function(superUser,n){
if(
userFound === false &&
(
params.auth && superUser.tokens && superUser.tokens[params.auth] || //using API key (object)
params.auth && superUser.tokens && superUser.tokens.indexOf && superUser.tokens.indexOf(params.auth) > -1 || //using API key (array)
(
params.mail && params.mail.toLowerCase() === superUser.mail.toLowerCase() && //email matches
2018-10-06 04:33:51 +00:00
(
params.pass === superUser.pass || //user give it already hashed
superUser.pass === s.createHash(params.pass) || //hash and check it
superUser.pass.toLowerCase() === s.md5(params.pass).toLowerCase() //check if still using md5
)
)
)
){
userFound = true
userSelected = superUser
foundUser()
}
})
}
2018-10-03 22:06:08 +00:00
}catch(err){
2018-10-05 21:19:29 +00:00
console.log('The following error may mean your super.json is not formatted correctly.')
2018-10-03 22:06:08 +00:00
console.log(err)
}
if(userFound === true){
return true
2018-09-28 05:37:08 +00:00
}else{
if(res)res.end(s.prettyPrint({
ok: false,
msg: lang['Not Authorized']
}))
2018-10-03 22:06:08 +00:00
return false
2018-09-28 05:37:08 +00:00
}
}
s.basicOrApiAuthentication = function(username,password,callback){
var splitUsername = username.split('@')
if(splitUsername[1] && splitUsername[1].toLowerCase().indexOf('shinobi') > -1){
2019-07-08 03:01:16 +00:00
getApiKey(params,'ke,uid',callback)
}else{
2019-07-08 03:01:16 +00:00
loginWithUsernameAndPassword(params,'ke,uid',callback)
}
}
2018-09-28 05:37:08 +00:00
}