added more support
This commit is contained in:
Vendored
+6
-3
@@ -7,12 +7,15 @@ export default class JwtAuth {
|
||||
[key: string]: any;
|
||||
}, settings?: jwt.SignOptions, secretKey?: string): string;
|
||||
verifyJWT(token: string, secretKey?: string): jwt.JwtPayload | undefined;
|
||||
decodeJWT(token: string): string | jwt.JwtPayload | null;
|
||||
getJWTExpirationDate(token: string): any;
|
||||
isJWTExpired(token: string): boolean | {
|
||||
decodeJWT(token: string): jwt.JwtPayload;
|
||||
getJWTExpirationDate(token: string): number | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
isJWTExpired(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
} | boolean;
|
||||
refreshJWT(token: string, settings?: jwt.SignOptions, secretKey?: string): string | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
Vendored
+11
-3
@@ -38,7 +38,7 @@ class JwtAuth {
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const vertoken = jwt.verify(token, secretKey);
|
||||
if (vertoken instanceof Object) {
|
||||
return vertoken;
|
||||
return (vertoken);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
@@ -51,7 +51,13 @@ class JwtAuth {
|
||||
decodeJWT(token) {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
return jwt.decode(token);
|
||||
const decoded = jwt.decode(token);
|
||||
if (decoded instanceof Object) {
|
||||
return decoded;
|
||||
}
|
||||
else {
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
}
|
||||
}
|
||||
getJWTExpirationDate(token) {
|
||||
if (this.blacklist.includes(token))
|
||||
@@ -63,7 +69,9 @@ class JwtAuth {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const expirationDate = this.getJWTExpirationDate(token);
|
||||
return expirationDate < Date.now();
|
||||
if (expirationDate instanceof Object)
|
||||
return expirationDate;
|
||||
return expirationDate < (Date.now() / 1000);
|
||||
}
|
||||
refreshJWT(token, settings = {}, secretKey = this.JWTSecretKey) {
|
||||
if (this.blacklist.includes(token))
|
||||
+2
-8
@@ -11,16 +11,10 @@ export default class PassPolicy {
|
||||
});
|
||||
validate(password: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
} | {
|
||||
valid: boolean;
|
||||
message?: undefined;
|
||||
message?: string;
|
||||
};
|
||||
CheckDifference(newPassword: string, oldPassword: string, neededDifference?: number): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
} | {
|
||||
valid: boolean;
|
||||
message?: undefined;
|
||||
message?: string;
|
||||
};
|
||||
}
|
||||
+2
-2
@@ -21,14 +21,14 @@ class PassCheck {
|
||||
}
|
||||
verifyPassword(password, hash) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return yield bcrypt_1.default.compare(password, hash);
|
||||
return Promise.resolve(yield bcrypt_1.default.compare(password, hash));
|
||||
});
|
||||
}
|
||||
hashPassword(password) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const salt = yield bcrypt_1.default.genSalt(this.BcryptSaltRounds);
|
||||
const hash = yield bcrypt_1.default.hash(password, salt);
|
||||
return hash;
|
||||
return Promise.resolve(hash);
|
||||
});
|
||||
}
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import PassCheck from "./passwordcheck";
|
||||
import JwtAuth from "./jwt";
|
||||
import PassPolicy from "./passpolicy";
|
||||
import RateLimit from "./ratelimit";
|
||||
import PasswordGenerator from "./passgen";
|
||||
export { PassCheck, JwtAuth, PassPolicy, RateLimit, PasswordGenerator };
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import PassCheck from "./passwordcheck";
|
||||
import JwtAuth from "./jwt";
|
||||
import PassPolicy from "./passpolicy";
|
||||
import RateLimit from "./ratelimit";
|
||||
import PasswordGenerator from "./passgen";
|
||||
export { PassCheck, JwtAuth, PassPolicy, RateLimit, PasswordGenerator };
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
export default class JwtAuth {
|
||||
private JWTSecretKey;
|
||||
private blacklist;
|
||||
constructor(JWTSecretKey: string);
|
||||
generateJWT(payload: {
|
||||
[key: string]: any;
|
||||
}, settings?: jwt.SignOptions, secretKey?: string): string;
|
||||
verifyJWT(token: string, secretKey?: string): jwt.JwtPayload | undefined;
|
||||
decodeJWT(token: string): jwt.JwtPayload;
|
||||
getJWTExpirationDate(token: string): number | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
isJWTExpired(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
} | boolean;
|
||||
refreshJWT(token: string, settings?: jwt.SignOptions, secretKey?: string): string | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
BlackListJWT(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
ClearBlackList(): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
GetBlackList(): string[];
|
||||
RemoveFromBlackList(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
IsBlackListed(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
export default class JwtAuth {
|
||||
constructor(JWTSecretKey) {
|
||||
this.JWTSecretKey = JWTSecretKey;
|
||||
this.blacklist = [];
|
||||
}
|
||||
generateJWT(payload, settings = {}, secretKey = this.JWTSecretKey) {
|
||||
return jwt.sign(payload, secretKey, settings);
|
||||
}
|
||||
verifyJWT(token, secretKey = this.JWTSecretKey) {
|
||||
try {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const vertoken = jwt.verify(token, secretKey);
|
||||
if (vertoken instanceof Object) {
|
||||
return (vertoken);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
}
|
||||
}
|
||||
decodeJWT(token) {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const decoded = jwt.decode(token);
|
||||
if (decoded instanceof Object) {
|
||||
return decoded;
|
||||
}
|
||||
else {
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
}
|
||||
}
|
||||
getJWTExpirationDate(token) {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const decoded = this.decodeJWT(token);
|
||||
return decoded.exp;
|
||||
}
|
||||
isJWTExpired(token) {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const expirationDate = this.getJWTExpirationDate(token);
|
||||
if (expirationDate instanceof Object)
|
||||
return expirationDate;
|
||||
return expirationDate < (Date.now() / 1000);
|
||||
}
|
||||
refreshJWT(token, settings = {}, secretKey = this.JWTSecretKey) {
|
||||
if (this.blacklist.includes(token))
|
||||
return { valid: false, message: "Token is blacklisted." };
|
||||
const decoded = this.verifyJWT(token, secretKey);
|
||||
if (decoded instanceof Object) {
|
||||
if (decoded.valid == false)
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
let payLoadArray = {};
|
||||
if (decoded instanceof Object) {
|
||||
payLoadArray = decoded;
|
||||
}
|
||||
else {
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
}
|
||||
const newToken = this.generateJWT(payLoadArray, settings, secretKey);
|
||||
return newToken;
|
||||
}
|
||||
return { valid: false, message: "Token is invalid." };
|
||||
}
|
||||
BlackListJWT(token) {
|
||||
//check if token is already blacklisted
|
||||
if (this.blacklist.includes(token)) {
|
||||
return { valid: false, message: "Token is already blacklisted." };
|
||||
}
|
||||
//add token to blacklist
|
||||
this.blacklist.push(token);
|
||||
return { valid: true, message: "Token successfully blacklisted." };
|
||||
}
|
||||
ClearBlackList() {
|
||||
//clear blacklist
|
||||
this.blacklist = [];
|
||||
return { valid: true, message: "Blacklist successfully cleared." };
|
||||
}
|
||||
GetBlackList() {
|
||||
//return blacklist
|
||||
return this.blacklist;
|
||||
}
|
||||
RemoveFromBlackList(token) {
|
||||
//remove token from blacklist
|
||||
if (this.blacklist.includes(token)) {
|
||||
this.blacklist = this.blacklist.filter((item) => item !== token);
|
||||
return { valid: true, message: "Token successfully removed from blacklist." };
|
||||
}
|
||||
return { valid: false, message: "Token is not blacklisted." };
|
||||
}
|
||||
IsBlackListed(token) {
|
||||
//check if token is blacklisted
|
||||
if (this.blacklist.includes(token)) {
|
||||
return { valid: true, message: "Token is blacklisted." };
|
||||
}
|
||||
return { valid: false, message: "Token is not blacklisted." };
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"type": "module"}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
export default class PasswordGenerator {
|
||||
private options;
|
||||
constructor(options: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
Generate(length?: number): string;
|
||||
}
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
export default class PasswordGenerator {
|
||||
constructor(options) {
|
||||
const defaultOptions = {
|
||||
minLength: 6,
|
||||
maxLength: 32,
|
||||
minLower: 2,
|
||||
minUpper: 2,
|
||||
minNum: 2,
|
||||
minSpecial: 3,
|
||||
specialChars: "!@#$%^&*()_+~`|}{[]:;?><,./-=",
|
||||
};
|
||||
this.options = Object.assign(Object.assign({}, defaultOptions), options);
|
||||
}
|
||||
Generate(length = 0) {
|
||||
// Generate random password that complies with the options
|
||||
const { minLength, maxLength, minLower, minUpper, minNum, minSpecial, specialChars } = this.options;
|
||||
let pass = "";
|
||||
let lowerRegex = 'abcdefghijklmnopqrstuvwxyz';
|
||||
let upperRegex = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
let numRegex = '0123456789';
|
||||
// Generate password
|
||||
//generate random length
|
||||
if (length === undefined || length < minLength || length > maxLength || length === 0) {
|
||||
length = Math.floor(Math.random() * (maxLength - minLength + 1) + minLength);
|
||||
}
|
||||
//generate random length for each character type
|
||||
let lowerLength = Math.floor(Math.random() * (length - minLower - minUpper - minNum - minSpecial + 1) + minLower);
|
||||
let upperLength = Math.floor(Math.random() * (length - lowerLength - minUpper - minNum - minSpecial + 1) + minUpper);
|
||||
let numLength = Math.floor(Math.random() * (length - lowerLength - upperLength - minNum - minSpecial + 1) + minNum);
|
||||
let specialLength = Math.floor(Math.random() * (length - lowerLength - upperLength - numLength - minSpecial + 1) + minSpecial);
|
||||
//generate random characters
|
||||
for (let i = 0; i < lowerLength; i++) {
|
||||
pass += lowerRegex[Math.floor(Math.random() * lowerRegex.length)];
|
||||
}
|
||||
for (let i = 0; i < upperLength; i++) {
|
||||
pass += upperRegex[Math.floor(Math.random() * upperRegex.length)];
|
||||
}
|
||||
for (let i = 0; i < numLength; i++) {
|
||||
pass += numRegex[Math.floor(Math.random() * numRegex.length)];
|
||||
}
|
||||
for (let i = 0; i < specialLength; i++) {
|
||||
pass += specialChars[Math.floor(Math.random() * specialChars.length)];
|
||||
}
|
||||
//shuffle password
|
||||
pass = pass.split('').sort(function () { return 0.5 - Math.random(); }).join('');
|
||||
return pass;
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
export default class PassPolicy {
|
||||
private options;
|
||||
constructor(options: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
validate(password: string): {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
};
|
||||
CheckDifference(newPassword: string, oldPassword: string, neededDifference?: number): {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
};
|
||||
}
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
export default class PassPolicy {
|
||||
constructor(options) {
|
||||
const defaultOptions = {
|
||||
minLength: 6,
|
||||
maxLength: 32,
|
||||
minLower: 2,
|
||||
minUpper: 2,
|
||||
minNum: 2,
|
||||
minSpecial: 3,
|
||||
specialChars: "!@#$%^&*()_+~`|}{[]:;?><,./-=",
|
||||
};
|
||||
this.options = Object.assign(Object.assign({}, defaultOptions), options);
|
||||
}
|
||||
validate(password) {
|
||||
const { minLength, maxLength, minLower, minUpper, minNum, minSpecial, specialChars } = this.options;
|
||||
if (password.length < minLength || password.length > maxLength) {
|
||||
return { valid: false, message: "Password length does not meet requirements." };
|
||||
}
|
||||
const lowerRegex = /[a-z]/g;
|
||||
const upperRegex = /[A-Z]/g;
|
||||
const numRegex = /[0-9]/g;
|
||||
const specialRegex = new RegExp(`[${specialChars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")}]`, "g");
|
||||
const lowerCount = (password.match(lowerRegex) || []).length;
|
||||
const upperCount = (password.match(upperRegex) || []).length;
|
||||
const numCount = (password.match(numRegex) || []).length;
|
||||
const specialCount = (password.match(specialRegex) || []).length;
|
||||
if (lowerCount < minLower) {
|
||||
return { valid: false, message: "Password must contain at least " + minLower + " lowercase letter(s)." };
|
||||
}
|
||||
if (upperCount < minUpper) {
|
||||
return { valid: false, message: "Password must contain at least " + minUpper + " uppercase letter(s)." };
|
||||
}
|
||||
if (numCount < minNum) {
|
||||
return { valid: false, message: "Password must contain at least " + minNum + " digit(s)." };
|
||||
}
|
||||
if (specialCount < minSpecial) {
|
||||
return { valid: false, message: "Password must contain at least " + minSpecial + " special character(s)." };
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
CheckDifference(newPassword, oldPassword, neededDifference = 3) {
|
||||
//check if new password is different from old password
|
||||
if (newPassword === oldPassword) {
|
||||
return { valid: false, message: "New password must be different from old password." };
|
||||
}
|
||||
//check how many characters are different
|
||||
let diffCount = 0;
|
||||
//check if new password is longer than old password
|
||||
if (newPassword.length > oldPassword.length) {
|
||||
for (let i = 0; i < oldPassword.length; i++) {
|
||||
if (newPassword[i] != oldPassword[i]) {
|
||||
diffCount++;
|
||||
}
|
||||
}
|
||||
diffCount += newPassword.length - oldPassword.length;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < newPassword.length; i++) {
|
||||
if (newPassword[i] != oldPassword[i]) {
|
||||
diffCount++;
|
||||
}
|
||||
}
|
||||
diffCount += oldPassword.length - newPassword.length;
|
||||
}
|
||||
//check if difference is enough
|
||||
if (diffCount < neededDifference) {
|
||||
return { valid: false, message: "New password must be different from old password by at least " + neededDifference + " characters." };
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
export default class PassCheck {
|
||||
private BcryptSaltRounds;
|
||||
private PassPolicy;
|
||||
constructor(BcryptSaltRounds: number, PassPolicyOptions: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
verifyPassword(password: string, hash: string): Promise<boolean>;
|
||||
hashPassword(password: string): Promise<string>;
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
import bcrypt from 'bcrypt';
|
||||
import PassPolicy from './passpolicy';
|
||||
export default class PassCheck {
|
||||
constructor(BcryptSaltRounds, PassPolicyOptions) {
|
||||
this.BcryptSaltRounds = BcryptSaltRounds;
|
||||
this.PassPolicy = new PassPolicy(PassPolicyOptions);
|
||||
}
|
||||
verifyPassword(password, hash) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return Promise.resolve(yield bcrypt.compare(password, hash));
|
||||
});
|
||||
}
|
||||
hashPassword(password) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const salt = yield bcrypt.genSalt(this.BcryptSaltRounds);
|
||||
const hash = yield bcrypt.hash(password, salt);
|
||||
return Promise.resolve(hash);
|
||||
});
|
||||
}
|
||||
}
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
type Event = {
|
||||
name: string;
|
||||
cooldown: number;
|
||||
maxAttempts: number;
|
||||
lastAttempt?: number;
|
||||
attempts?: number[];
|
||||
};
|
||||
type user = {
|
||||
token: string;
|
||||
events: {
|
||||
[name: string]: Event;
|
||||
};
|
||||
};
|
||||
export default class RateLimit {
|
||||
users: {
|
||||
[token: string]: user;
|
||||
};
|
||||
events: {
|
||||
[name: string]: Event;
|
||||
};
|
||||
constructor(users?: {
|
||||
[token: string]: user;
|
||||
}, events?: {
|
||||
[name: string]: Event;
|
||||
});
|
||||
addEvent(event: Event): boolean;
|
||||
removeEvent(name: string): boolean;
|
||||
addUser(token: string): boolean;
|
||||
removeUser(token: string): boolean;
|
||||
attempt(token: string, name: string): boolean;
|
||||
getEvents(): {
|
||||
[name: string]: Event;
|
||||
};
|
||||
getUsers(): {
|
||||
[token: string]: user;
|
||||
};
|
||||
getEvent(name: string): Event;
|
||||
getUser(token: string): user;
|
||||
remainingAttempts(token: string, name: string): number;
|
||||
resetAttempts(token: string, name: string): boolean;
|
||||
resetAllAttempts(token: string): boolean;
|
||||
resetAllUsers(): boolean;
|
||||
resetEvent(name: string): boolean;
|
||||
resetUser(token: string): boolean;
|
||||
}
|
||||
export {};
|
||||
Vendored
+163
@@ -0,0 +1,163 @@
|
||||
export default class RateLimit {
|
||||
constructor(users = {}, events = {}) {
|
||||
this.users = users;
|
||||
this.events = events;
|
||||
this.users = users;
|
||||
this.events = events;
|
||||
}
|
||||
addEvent(event) {
|
||||
try {
|
||||
this.events[event.name] = event;
|
||||
//add event to all users
|
||||
for (const token in this.users) {
|
||||
this.users[token].events[event.name] = event;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
removeEvent(name) {
|
||||
try {
|
||||
delete this.events[name];
|
||||
//remove event from all users
|
||||
for (const token in this.users) {
|
||||
delete this.users[token].events[name];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
addUser(token) {
|
||||
try {
|
||||
this.users[token] = { token, events: this.events };
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
removeUser(token) {
|
||||
try {
|
||||
delete this.users[token];
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
attempt(token, name) {
|
||||
try {
|
||||
if (!this.users[token] || !this.users[token].events[name]) {
|
||||
return false;
|
||||
}
|
||||
const event = this.users[token].events[name];
|
||||
if (event.attempts === undefined) {
|
||||
event.attempts = [];
|
||||
}
|
||||
const now = Date.now();
|
||||
if (event.lastAttempt && now - event.lastAttempt < event.cooldown) {
|
||||
return false;
|
||||
}
|
||||
event.lastAttempt = now;
|
||||
event.attempts.push(now);
|
||||
if (event.attempts.length > event.maxAttempts) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
getEvents() {
|
||||
return this.events;
|
||||
}
|
||||
getUsers() {
|
||||
return this.users;
|
||||
}
|
||||
getEvent(name) {
|
||||
return this.events[name];
|
||||
}
|
||||
getUser(token) {
|
||||
return this.users[token];
|
||||
}
|
||||
remainingAttempts(token, name) {
|
||||
try {
|
||||
if (!this.users[token] || !this.users[token].events[name]) {
|
||||
return -1;
|
||||
}
|
||||
const event = this.users[token].events[name];
|
||||
if (event.attempts === undefined) {
|
||||
event.attempts = [];
|
||||
}
|
||||
return event.maxAttempts - event.attempts.length;
|
||||
}
|
||||
catch (error) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
resetAttempts(token, name) {
|
||||
try {
|
||||
if (!this.users[token] || !this.users[token].events[name]) {
|
||||
return false;
|
||||
}
|
||||
const event = this.users[token].events[name];
|
||||
event.attempts = [];
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
resetAllAttempts(token) {
|
||||
try {
|
||||
if (!this.users[token]) {
|
||||
return false;
|
||||
}
|
||||
for (const name in this.users[token].events) {
|
||||
this.resetAttempts(token, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
resetAllUsers() {
|
||||
try {
|
||||
for (const token in this.users) {
|
||||
this.resetAllAttempts(token);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
resetEvent(name) {
|
||||
try {
|
||||
for (const token in this.users) {
|
||||
this.resetAttempts(token, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
resetUser(token) {
|
||||
try {
|
||||
for (const name in this.users[token].events) {
|
||||
this.resetAttempts(token, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import PassCheck from "./passwordcheck";
|
||||
import JwtAuth from "./jwt";
|
||||
import PassPolicy from "./passpolicy";
|
||||
import RateLimit from "./ratelimit";
|
||||
import PasswordGenerator from "./passgen";
|
||||
export { PassCheck, JwtAuth, PassPolicy, RateLimit, PasswordGenerator };
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
export default class JwtAuth {
|
||||
private JWTSecretKey;
|
||||
private blacklist;
|
||||
constructor(JWTSecretKey: string);
|
||||
generateJWT(payload: {
|
||||
[key: string]: any;
|
||||
}, settings?: jwt.SignOptions, secretKey?: string): string;
|
||||
verifyJWT(token: string, secretKey?: string): jwt.JwtPayload | undefined;
|
||||
decodeJWT(token: string): jwt.JwtPayload;
|
||||
getJWTExpirationDate(token: string): number | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
isJWTExpired(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
} | boolean;
|
||||
refreshJWT(token: string, settings?: jwt.SignOptions, secretKey?: string): string | {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
BlackListJWT(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
ClearBlackList(): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
GetBlackList(): string[];
|
||||
RemoveFromBlackList(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
IsBlackListed(token: string): {
|
||||
valid: boolean;
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
export default class PasswordGenerator {
|
||||
private options;
|
||||
constructor(options: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
Generate(length?: number): string;
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
export default class PassPolicy {
|
||||
private options;
|
||||
constructor(options: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
validate(password: string): {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
};
|
||||
CheckDifference(newPassword: string, oldPassword: string, neededDifference?: number): {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
};
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
export default class PassCheck {
|
||||
private BcryptSaltRounds;
|
||||
private PassPolicy;
|
||||
constructor(BcryptSaltRounds: number, PassPolicyOptions: {
|
||||
minLength: number;
|
||||
maxLength: number;
|
||||
minLower: number;
|
||||
minUpper: number;
|
||||
minNum: number;
|
||||
minSpecial: number;
|
||||
specialChars: string;
|
||||
});
|
||||
verifyPassword(password: string, hash: string): Promise<boolean>;
|
||||
hashPassword(password: string): Promise<string>;
|
||||
}
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
type Event = {
|
||||
name: string;
|
||||
cooldown: number;
|
||||
maxAttempts: number;
|
||||
lastAttempt?: number;
|
||||
attempts?: number[];
|
||||
};
|
||||
type user = {
|
||||
token: string;
|
||||
events: {
|
||||
[name: string]: Event;
|
||||
};
|
||||
};
|
||||
export default class RateLimit {
|
||||
users: {
|
||||
[token: string]: user;
|
||||
};
|
||||
events: {
|
||||
[name: string]: Event;
|
||||
};
|
||||
constructor(users?: {
|
||||
[token: string]: user;
|
||||
}, events?: {
|
||||
[name: string]: Event;
|
||||
});
|
||||
addEvent(event: Event): boolean;
|
||||
removeEvent(name: string): boolean;
|
||||
addUser(token: string): boolean;
|
||||
removeUser(token: string): boolean;
|
||||
attempt(token: string, name: string): boolean;
|
||||
getEvents(): {
|
||||
[name: string]: Event;
|
||||
};
|
||||
getUsers(): {
|
||||
[token: string]: user;
|
||||
};
|
||||
getEvent(name: string): Event;
|
||||
getUser(token: string): user;
|
||||
remainingAttempts(token: string, name: string): number;
|
||||
resetAttempts(token: string, name: string): boolean;
|
||||
resetAllAttempts(token: string): boolean;
|
||||
resetAllUsers(): boolean;
|
||||
resetEvent(name: string): boolean;
|
||||
resetUser(token: string): boolean;
|
||||
}
|
||||
export {};
|
||||
+16
-5
@@ -1,14 +1,17 @@
|
||||
{
|
||||
"name": "auth-guardian",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.2",
|
||||
"description": "auth-guardian a library for enhancing application security",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"main": "./dist/cjs/index.js",
|
||||
"module": "dist/esm/index.js",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"build": "tsc"
|
||||
"build": "tsc",
|
||||
"compile": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kajvan/guardian"
|
||||
@@ -33,5 +36,13 @@
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"require": "./dist/cjs/index.js",
|
||||
"import": "./dist/esm/index.js",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ export default class PassCheck{
|
||||
}
|
||||
|
||||
async verifyPassword(password: string, hash: string): Promise<boolean> {
|
||||
return await bcrypt.compare(password, hash);
|
||||
return Promise.resolve(await bcrypt.compare(password, hash));
|
||||
}
|
||||
|
||||
async hashPassword(password: string): Promise<string> {
|
||||
const salt = await bcrypt.genSalt(this.BcryptSaltRounds);
|
||||
const hash = await bcrypt.hash(password, salt);
|
||||
return hash;
|
||||
return Promise.resolve(hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/cjs",
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/esm",
|
||||
"module": "esnext"
|
||||
}
|
||||
}
|
||||
@@ -24,25 +24,6 @@
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/types",
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user