Prepped session utils for remember me tokens.
This commit is contained in:
parent
5caa679b92
commit
95ed2fa403
|
|
@ -41,16 +41,19 @@ const maxAttempts = 200;
|
||||||
* Sole and Singular Session Authentication method.
|
* Sole and Singular Session Authentication method.
|
||||||
* All logins should happen through here, all other site-wide authentication should happen by sessions authenticated by this model.
|
* All logins should happen through here, all other site-wide authentication should happen by sessions authenticated by this model.
|
||||||
* This is important, as reducing authentication endpoints reduces attack surface.
|
* This is important, as reducing authentication endpoints reduces attack surface.
|
||||||
* @param {String} user - Username to login as
|
*
|
||||||
* @param {String} pass - Password to authenticat session with
|
* Ended up not splitting this in two/three for remember-me tokens. Kind of fucked up it was actually easier this way...
|
||||||
|
* @param {String} identifier - Identifer used to identify account, either username or token UUID
|
||||||
|
* @param {String} secret - Secret to authenticate session with, either password or token secret
|
||||||
* @param {express.Request} req - Express request object w/ session to authenticate
|
* @param {express.Request} req - Express request object w/ session to authenticate
|
||||||
|
* @param {Boolean} useRememberMeToken - Whether or not we're using username/pass or remember-me tokens
|
||||||
* @returns Username of authticated user upon success
|
* @returns Username of authticated user upon success
|
||||||
*/
|
*/
|
||||||
module.exports.authenticateSession = async function(user, pass, req){
|
module.exports.authenticateSession = async function(identifier, secret, req, useRememberMeToken = false){
|
||||||
//Fuck you yoda
|
//Fuck you yoda
|
||||||
try{
|
try{
|
||||||
//Grab previous attempts
|
//Grab previous attempts
|
||||||
const attempt = failedAttempts.get(user);
|
const attempt = failedAttempts.get(identifier);
|
||||||
|
|
||||||
//If we're proxied use passthrough IP
|
//If we're proxied use passthrough IP
|
||||||
const ip = config.proxied ? req.headers['x-forwarded-for'] : req.ip;
|
const ip = config.proxied ? req.headers['x-forwarded-for'] : req.ip;
|
||||||
|
|
@ -74,7 +77,7 @@ module.exports.authenticateSession = async function(user, pass, req){
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we have failed attempts
|
//If we have failed attempts
|
||||||
if(attempt != null){
|
if(!useRememberMeToken && attempt != null){
|
||||||
//If we have more failed attempts than allowed
|
//If we have more failed attempts than allowed
|
||||||
if(attempt.count > maxAttempts){
|
if(attempt.count > maxAttempts){
|
||||||
throw loggerUtils.exceptionSmith("This account has been locked for at 24 hours due to a large amount of failed log-in attempts", "unauthorized");
|
throw loggerUtils.exceptionSmith("This account has been locked for at 24 hours due to a large amount of failed log-in attempts", "unauthorized");
|
||||||
|
|
@ -86,14 +89,23 @@ module.exports.authenticateSession = async function(user, pass, req){
|
||||||
//Since we've already got access to the request and dont need to import anything, why bother getting it from a parameter?
|
//Since we've already got access to the request and dont need to import anything, why bother getting it from a parameter?
|
||||||
if(req.body.verification == null){
|
if(req.body.verification == null){
|
||||||
throw loggerUtils.exceptionSmith("Verification failed!", "unauthorized");
|
throw loggerUtils.exceptionSmith("Verification failed!", "unauthorized");
|
||||||
}else if(!altchaUtils.verify(req.body.verification, user)){
|
}else if(!altchaUtils.verify(req.body.verification, identifier)){
|
||||||
throw loggerUtils.exceptionSmith("Verification failed!", "");
|
throw loggerUtils.exceptionSmith("Verification failed!", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Authenticate the session
|
//define/scope empty userDB variable
|
||||||
const userDB = await userModel.authenticate(user, pass);
|
let userDB = null;
|
||||||
|
|
||||||
|
//If we're using remember me tokens
|
||||||
|
if(useRememberMeToken){
|
||||||
|
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//Fallback on to username/password authentication
|
||||||
|
userDB = await userModel.authenticate(identifier, secret);
|
||||||
|
}
|
||||||
|
|
||||||
//Check for user ban
|
//Check for user ban
|
||||||
const userBanDB = await userBanModel.checkBanByUserDoc(userDB);
|
const userBanDB = await userBanModel.checkBanByUserDoc(userDB);
|
||||||
|
|
@ -123,14 +135,20 @@ module.exports.authenticateSession = async function(user, pass, req){
|
||||||
//Tattoo hashed IP address to user account for seven days
|
//Tattoo hashed IP address to user account for seven days
|
||||||
userDB.tattooIPRecord(ip);
|
userDB.tattooIPRecord(ip);
|
||||||
|
|
||||||
|
if(!useRememberMeToken){
|
||||||
//If we got to here then the log-in was successful. We should clear-out any failed attempts.
|
//If we got to here then the log-in was successful. We should clear-out any failed attempts.
|
||||||
failedAttempts.delete(user);
|
failedAttempts.delete(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
//return user
|
//return user
|
||||||
return userDB.user;
|
return userDB.user;
|
||||||
}catch(err){
|
}catch(err){
|
||||||
|
//Failed attempts at good tokens are handled by the token schema by dropping the users effected tokens and screaming bloody murder
|
||||||
|
//Failed attempts with bad tokens don't need to be handled as it's not like attacking a bad UUID is going to get you anywhere anywho
|
||||||
|
//This also makes it way easier to re-use parts of this function
|
||||||
|
if(!useRememberMeToken){
|
||||||
//Look for previous failed attempts
|
//Look for previous failed attempts
|
||||||
var attempt = failedAttempts.get(user);
|
var attempt = failedAttempts.get(identifier);
|
||||||
|
|
||||||
//If this is the first attempt
|
//If this is the first attempt
|
||||||
if(attempt == null){
|
if(attempt == null){
|
||||||
|
|
@ -148,7 +166,8 @@ module.exports.authenticateSession = async function(user, pass, req){
|
||||||
}
|
}
|
||||||
|
|
||||||
//Commit the failed attempt to the failed sign-in cache
|
//Commit the failed attempt to the failed sign-in cache
|
||||||
failedAttempts.set(user, attempt);
|
failedAttempts.set(identifier, attempt);
|
||||||
|
}
|
||||||
|
|
||||||
//y33t
|
//y33t
|
||||||
throw err;
|
throw err;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue