Prepped session utils for remember me tokens.

This commit is contained in:
rainbow napkin 2025-10-20 05:15:34 -04:00
parent 5caa679b92
commit 95ed2fa403

View file

@ -41,16 +41,19 @@ const maxAttempts = 200;
* 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.
* 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 {Boolean} useRememberMeToken - Whether or not we're using username/pass or remember-me tokens
* @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
try{
//Grab previous attempts
const attempt = failedAttempts.get(user);
const attempt = failedAttempts.get(identifier);
//If we're proxied use passthrough 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(attempt != null){
if(!useRememberMeToken && attempt != null){
//If we have more failed attempts than allowed
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");
@ -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?
if(req.body.verification == null){
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!", "");
}
}
}
//Authenticate the session
const userDB = await userModel.authenticate(user, pass);
//define/scope empty userDB variable
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
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
userDB.tattooIPRecord(ip);
if(!useRememberMeToken){
//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 userDB.user;
}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
var attempt = failedAttempts.get(user);
var attempt = failedAttempts.get(identifier);
//If this is the first attempt
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
failedAttempts.set(user, attempt);
failedAttempts.set(identifier, attempt);
}
//y33t
throw err;