@naman_deep_singh/security 1.0.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +315 -80
- package/dist/cjs/core/crypto/decrypt.d.ts +1 -0
- package/dist/cjs/core/crypto/decrypt.js +21 -0
- package/dist/cjs/core/crypto/encrypt.d.ts +1 -0
- package/dist/cjs/core/crypto/encrypt.js +16 -0
- package/dist/cjs/core/crypto/hmac.d.ts +8 -0
- package/dist/cjs/core/crypto/hmac.js +24 -0
- package/dist/cjs/core/crypto/index.d.ts +4 -0
- package/dist/cjs/core/crypto/index.js +20 -0
- package/dist/cjs/core/crypto/random.d.ts +8 -0
- package/dist/cjs/core/crypto/random.js +21 -0
- package/dist/cjs/core/jwt/decode.d.ts +12 -0
- package/dist/cjs/core/jwt/decode.js +25 -0
- package/dist/cjs/core/jwt/extractToken.d.ts +11 -0
- package/dist/cjs/core/jwt/extractToken.js +54 -0
- package/dist/cjs/core/jwt/generateTokens.d.ts +4 -0
- package/dist/cjs/core/jwt/generateTokens.js +30 -0
- package/dist/cjs/core/jwt/index.d.ts +8 -0
- package/dist/cjs/core/jwt/index.js +24 -0
- package/dist/cjs/core/jwt/parseDuration.d.ts +1 -0
- package/dist/cjs/core/jwt/parseDuration.js +29 -0
- package/dist/cjs/core/jwt/signToken.d.ts +2 -0
- package/dist/cjs/core/jwt/signToken.js +26 -0
- package/dist/cjs/core/jwt/types.d.ts +22 -0
- package/dist/cjs/core/jwt/types.js +2 -0
- package/dist/cjs/core/jwt/validateToken.d.ts +13 -0
- package/dist/cjs/core/jwt/validateToken.js +37 -0
- package/dist/cjs/core/jwt/verify.d.ts +18 -0
- package/dist/cjs/core/jwt/verify.js +44 -0
- package/dist/cjs/core/password/hash.d.ts +10 -0
- package/dist/cjs/core/password/hash.js +45 -0
- package/dist/cjs/core/password/index.d.ts +3 -0
- package/dist/cjs/core/password/index.js +19 -0
- package/dist/cjs/core/password/strength.d.ts +2 -0
- package/dist/cjs/core/password/strength.js +21 -0
- package/dist/cjs/core/password/types.d.ts +7 -0
- package/dist/cjs/core/password/types.js +2 -0
- package/dist/cjs/core/password/utils.d.ts +4 -0
- package/dist/cjs/core/password/utils.js +38 -0
- package/dist/cjs/core/password/verify.d.ts +10 -0
- package/dist/cjs/core/password/verify.js +46 -0
- package/dist/cjs/index.d.ts +41 -0
- package/dist/cjs/index.js +56 -0
- package/dist/esm/core/crypto/decrypt.d.ts +1 -0
- package/dist/esm/core/crypto/decrypt.js +14 -0
- package/dist/esm/core/crypto/encrypt.d.ts +1 -0
- package/dist/esm/core/crypto/encrypt.js +9 -0
- package/dist/esm/core/crypto/hmac.d.ts +8 -0
- package/dist/esm/core/crypto/hmac.js +16 -0
- package/dist/esm/core/crypto/index.d.ts +4 -0
- package/dist/esm/core/crypto/index.js +4 -0
- package/dist/esm/core/crypto/random.d.ts +8 -0
- package/dist/esm/core/crypto/random.js +13 -0
- package/dist/esm/core/jwt/decode.d.ts +12 -0
- package/dist/esm/core/jwt/decode.js +21 -0
- package/dist/esm/core/jwt/extractToken.d.ts +11 -0
- package/dist/esm/core/jwt/extractToken.js +51 -0
- package/dist/esm/core/jwt/generateTokens.d.ts +4 -0
- package/dist/esm/core/jwt/generateTokens.js +25 -0
- package/dist/esm/core/jwt/index.d.ts +8 -0
- package/dist/esm/core/jwt/index.js +8 -0
- package/dist/esm/core/jwt/parseDuration.d.ts +1 -0
- package/dist/esm/core/jwt/parseDuration.js +26 -0
- package/dist/esm/core/jwt/signToken.d.ts +2 -0
- package/dist/esm/core/jwt/signToken.js +22 -0
- package/dist/esm/core/jwt/types.d.ts +22 -0
- package/dist/esm/core/jwt/types.js +1 -0
- package/dist/esm/core/jwt/validateToken.d.ts +13 -0
- package/dist/esm/core/jwt/validateToken.js +33 -0
- package/dist/esm/core/jwt/verify.d.ts +18 -0
- package/dist/esm/core/jwt/verify.js +37 -0
- package/dist/esm/core/password/hash.d.ts +10 -0
- package/dist/esm/core/password/hash.js +35 -0
- package/dist/esm/core/password/index.d.ts +3 -0
- package/dist/esm/core/password/index.js +3 -0
- package/dist/esm/core/password/strength.d.ts +2 -0
- package/dist/esm/core/password/strength.js +17 -0
- package/dist/esm/core/password/types.d.ts +7 -0
- package/dist/esm/core/password/types.js +1 -0
- package/dist/esm/core/password/utils.d.ts +4 -0
- package/dist/esm/core/password/utils.js +29 -0
- package/dist/esm/core/password/verify.d.ts +10 -0
- package/dist/esm/core/password/verify.js +36 -0
- package/dist/esm/index.d.ts +41 -0
- package/dist/esm/index.js +13 -0
- package/dist/types/core/crypto/decrypt.d.ts +1 -0
- package/dist/types/core/crypto/encrypt.d.ts +1 -0
- package/dist/types/core/crypto/hmac.d.ts +8 -0
- package/dist/types/core/crypto/index.d.ts +4 -0
- package/dist/types/core/crypto/random.d.ts +8 -0
- package/dist/types/core/jwt/decode.d.ts +12 -0
- package/dist/types/core/jwt/extractToken.d.ts +11 -0
- package/dist/types/core/jwt/generateTokens.d.ts +4 -0
- package/dist/types/core/jwt/index.d.ts +8 -0
- package/dist/types/core/jwt/parseDuration.d.ts +1 -0
- package/dist/types/core/jwt/signToken.d.ts +2 -0
- package/dist/types/core/jwt/types.d.ts +22 -0
- package/dist/types/core/jwt/validateToken.d.ts +13 -0
- package/dist/types/core/jwt/verify.d.ts +18 -0
- package/dist/types/core/password/hash.d.ts +10 -0
- package/dist/types/core/password/index.d.ts +3 -0
- package/dist/types/core/password/strength.d.ts +2 -0
- package/dist/types/core/password/types.d.ts +7 -0
- package/dist/types/core/password/utils.d.ts +4 -0
- package/dist/types/core/password/verify.d.ts +10 -0
- package/dist/types/index.d.ts +41 -0
- package/package.json +23 -7
- package/dist/index.d.ts +0 -16
- package/dist/index.js +0 -41
- package/src/index.ts +0 -39
- package/tsconfig.json +0 -21
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTokens = void 0;
|
|
4
|
+
exports.rotateRefreshToken = rotateRefreshToken;
|
|
5
|
+
const signToken_1 = require("./signToken");
|
|
6
|
+
const verify_1 = require("./verify");
|
|
7
|
+
// Helper function to create branded tokens
|
|
8
|
+
const createBrandedToken = (token, _brand) => {
|
|
9
|
+
return token;
|
|
10
|
+
};
|
|
11
|
+
const generateTokens = (payload, accessSecret, refreshSecret, accessExpiry = "15m", refreshExpiry = "7d") => {
|
|
12
|
+
const accessToken = (0, signToken_1.signToken)(payload, accessSecret, accessExpiry, { algorithm: "HS256" });
|
|
13
|
+
const refreshToken = (0, signToken_1.signToken)(payload, refreshSecret, refreshExpiry, { algorithm: "HS256" });
|
|
14
|
+
return {
|
|
15
|
+
accessToken: accessToken,
|
|
16
|
+
refreshToken: refreshToken,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
exports.generateTokens = generateTokens;
|
|
20
|
+
function rotateRefreshToken(oldToken, secret) {
|
|
21
|
+
const decoded = (0, verify_1.verifyToken)(oldToken, secret);
|
|
22
|
+
if (typeof decoded === "string") {
|
|
23
|
+
throw new Error("Invalid token payload — expected JWT payload object");
|
|
24
|
+
}
|
|
25
|
+
const payload = { ...decoded };
|
|
26
|
+
delete payload.iat;
|
|
27
|
+
delete payload.exp;
|
|
28
|
+
const newToken = (0, signToken_1.signToken)(payload, secret, "7d");
|
|
29
|
+
return newToken;
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./decode"), exports);
|
|
18
|
+
__exportStar(require("./extractToken"), exports);
|
|
19
|
+
__exportStar(require("./generateTokens"), exports);
|
|
20
|
+
__exportStar(require("./parseDuration"), exports);
|
|
21
|
+
__exportStar(require("./signToken"), exports);
|
|
22
|
+
__exportStar(require("./types"), exports);
|
|
23
|
+
__exportStar(require("./validateToken"), exports);
|
|
24
|
+
__exportStar(require("./verify"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseDuration(input: string | number): number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseDuration = parseDuration;
|
|
4
|
+
const TIME_UNITS = {
|
|
5
|
+
s: 1,
|
|
6
|
+
m: 60,
|
|
7
|
+
h: 3600,
|
|
8
|
+
d: 86400,
|
|
9
|
+
w: 604800
|
|
10
|
+
};
|
|
11
|
+
function parseDuration(input) {
|
|
12
|
+
if (typeof input === "number")
|
|
13
|
+
return input;
|
|
14
|
+
const regex = /(\d+)\s*(s|m|h|d|w)/gi;
|
|
15
|
+
let totalSeconds = 0;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = regex.exec(input)) !== null) {
|
|
18
|
+
const value = parseInt(match[1], 10);
|
|
19
|
+
const unit = match[2].toLowerCase();
|
|
20
|
+
if (!TIME_UNITS[unit]) {
|
|
21
|
+
throw new Error(`Invalid time unit: ${unit}`);
|
|
22
|
+
}
|
|
23
|
+
totalSeconds += value * TIME_UNITS[unit];
|
|
24
|
+
}
|
|
25
|
+
if (totalSeconds === 0) {
|
|
26
|
+
throw new Error(`Invalid expiry format: "${input}"`);
|
|
27
|
+
}
|
|
28
|
+
return totalSeconds;
|
|
29
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.signToken = void 0;
|
|
4
|
+
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
5
|
+
const parseDuration_1 = require("./parseDuration");
|
|
6
|
+
function getExpiryTimestamp(seconds) {
|
|
7
|
+
return Math.floor(Date.now() / 1000) + seconds;
|
|
8
|
+
}
|
|
9
|
+
const signToken = (payload, secret, expiresIn = "1h", options = {}) => {
|
|
10
|
+
const seconds = (0, parseDuration_1.parseDuration)(expiresIn);
|
|
11
|
+
if (!seconds || seconds < 10) {
|
|
12
|
+
throw new Error("Token expiry too small");
|
|
13
|
+
}
|
|
14
|
+
const tokenPayload = {
|
|
15
|
+
...payload
|
|
16
|
+
};
|
|
17
|
+
if (!("exp" in payload))
|
|
18
|
+
tokenPayload.exp = getExpiryTimestamp(seconds);
|
|
19
|
+
if (!("iat" in payload))
|
|
20
|
+
tokenPayload.iat = Math.floor(Date.now() / 1000);
|
|
21
|
+
return (0, jsonwebtoken_1.sign)(tokenPayload, secret, {
|
|
22
|
+
algorithm: "HS256",
|
|
23
|
+
...options
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
exports.signToken = signToken;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { JwtPayload } from "jsonwebtoken";
|
|
2
|
+
export interface AccessTokenBrand {
|
|
3
|
+
readonly access: unique symbol;
|
|
4
|
+
}
|
|
5
|
+
export interface RefreshTokenBrand {
|
|
6
|
+
readonly refresh: unique symbol;
|
|
7
|
+
}
|
|
8
|
+
export type AccessToken = string & AccessTokenBrand;
|
|
9
|
+
export type RefreshToken = string & RefreshTokenBrand;
|
|
10
|
+
export interface TokenPair {
|
|
11
|
+
accessToken: AccessToken;
|
|
12
|
+
refreshToken: RefreshToken;
|
|
13
|
+
}
|
|
14
|
+
export interface VerificationResult<T = JwtPayload> {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
payload?: T | string;
|
|
17
|
+
error?: Error;
|
|
18
|
+
}
|
|
19
|
+
export interface TokenValidationOptions {
|
|
20
|
+
ignoreExpiration?: boolean;
|
|
21
|
+
ignoreIssuedAt?: boolean;
|
|
22
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { JwtPayload } from "node_modules/@types/jsonwebtoken";
|
|
2
|
+
export interface TokenRequirements {
|
|
3
|
+
requiredFields?: string[];
|
|
4
|
+
forbiddenFields?: string[];
|
|
5
|
+
validateTypes?: Record<string, "string" | "number" | "boolean">;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateTokenPayload(payload: Record<string, unknown>, rules?: TokenRequirements): {
|
|
8
|
+
valid: true;
|
|
9
|
+
} | {
|
|
10
|
+
valid: false;
|
|
11
|
+
error: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function isTokenExpired(payload: JwtPayload): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateTokenPayload = validateTokenPayload;
|
|
4
|
+
exports.isTokenExpired = isTokenExpired;
|
|
5
|
+
function validateTokenPayload(payload, rules = {
|
|
6
|
+
requiredFields: ["exp", "iat"]
|
|
7
|
+
}) {
|
|
8
|
+
const { requiredFields = [], forbiddenFields = [], validateTypes = {} } = rules;
|
|
9
|
+
// 1. Required fields
|
|
10
|
+
for (const field of requiredFields) {
|
|
11
|
+
if (!(field in payload)) {
|
|
12
|
+
return { valid: false, error: `Missing required field: ${field}` };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// 2. Forbidden fields
|
|
16
|
+
for (const field of forbiddenFields) {
|
|
17
|
+
if (field in payload) {
|
|
18
|
+
return { valid: false, error: `Forbidden field in token: ${field}` };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// 3. Type validation
|
|
22
|
+
for (const key in validateTypes) {
|
|
23
|
+
const expectedType = validateTypes[key];
|
|
24
|
+
if (key in payload && typeof payload[key] !== expectedType) {
|
|
25
|
+
return {
|
|
26
|
+
valid: false,
|
|
27
|
+
error: `Invalid type for ${key}. Expected ${expectedType}.`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { valid: true };
|
|
32
|
+
}
|
|
33
|
+
function isTokenExpired(payload) {
|
|
34
|
+
if (!payload.exp)
|
|
35
|
+
return true;
|
|
36
|
+
return Date.now() >= payload.exp * 1000;
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import jwt, { Secret, JwtPayload } from "jsonwebtoken";
|
|
2
|
+
import { VerificationResult } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Verify token (throws if invalid or expired)
|
|
5
|
+
*/
|
|
6
|
+
export declare const verifyToken: (token: string, secret: Secret) => string | JwtPayload;
|
|
7
|
+
/**
|
|
8
|
+
* Safe verify — never throws, returns structured result
|
|
9
|
+
*/
|
|
10
|
+
export declare const safeVerifyToken: (token: string, secret: Secret) => VerificationResult;
|
|
11
|
+
/**
|
|
12
|
+
* Verify token with validation options
|
|
13
|
+
*/
|
|
14
|
+
export declare const verifyTokenWithOptions: (token: string, secret: Secret, options?: jwt.VerifyOptions) => string | JwtPayload;
|
|
15
|
+
/**
|
|
16
|
+
* Safe verify with validation options
|
|
17
|
+
*/
|
|
18
|
+
export declare const safeVerifyTokenWithOptions: (token: string, secret: Secret, options?: jwt.VerifyOptions) => VerificationResult;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.safeVerifyTokenWithOptions = exports.verifyTokenWithOptions = exports.safeVerifyToken = exports.verifyToken = void 0;
|
|
4
|
+
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
5
|
+
/**
|
|
6
|
+
* Verify token (throws if invalid or expired)
|
|
7
|
+
*/
|
|
8
|
+
const verifyToken = (token, secret) => {
|
|
9
|
+
return (0, jsonwebtoken_1.verify)(token, secret);
|
|
10
|
+
};
|
|
11
|
+
exports.verifyToken = verifyToken;
|
|
12
|
+
/**
|
|
13
|
+
* Safe verify — never throws, returns structured result
|
|
14
|
+
*/
|
|
15
|
+
const safeVerifyToken = (token, secret) => {
|
|
16
|
+
try {
|
|
17
|
+
const decoded = (0, jsonwebtoken_1.verify)(token, secret);
|
|
18
|
+
return { valid: true, payload: decoded };
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return { valid: false, error: error };
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.safeVerifyToken = safeVerifyToken;
|
|
25
|
+
/**
|
|
26
|
+
* Verify token with validation options
|
|
27
|
+
*/
|
|
28
|
+
const verifyTokenWithOptions = (token, secret, options = {}) => {
|
|
29
|
+
return (0, jsonwebtoken_1.verify)(token, secret, options);
|
|
30
|
+
};
|
|
31
|
+
exports.verifyTokenWithOptions = verifyTokenWithOptions;
|
|
32
|
+
/**
|
|
33
|
+
* Safe verify with validation options
|
|
34
|
+
*/
|
|
35
|
+
const safeVerifyTokenWithOptions = (token, secret, options = {}) => {
|
|
36
|
+
try {
|
|
37
|
+
const decoded = (0, jsonwebtoken_1.verify)(token, secret, options);
|
|
38
|
+
return { valid: true, payload: decoded };
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return { valid: false, error: error };
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
exports.safeVerifyTokenWithOptions = safeVerifyTokenWithOptions;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash a password asynchronously using bcrypt.
|
|
3
|
+
*/
|
|
4
|
+
export declare const hashPassword: (password: string, saltRounds?: number) => Promise<string>;
|
|
5
|
+
export declare function hashPasswordWithPepper(password: string, pepper: string): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Hash a password synchronously using bcrypt.
|
|
8
|
+
*/
|
|
9
|
+
export declare const hashPasswordSync: (password: string, saltRounds?: number) => string;
|
|
10
|
+
export declare function hashPasswordWithPepperSync(password: string, pepper: string): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hashPasswordSync = exports.hashPassword = void 0;
|
|
7
|
+
exports.hashPasswordWithPepper = hashPasswordWithPepper;
|
|
8
|
+
exports.hashPasswordWithPepperSync = hashPasswordWithPepperSync;
|
|
9
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const errors_utils_1 = require("@naman_deep_singh/errors-utils");
|
|
12
|
+
/**
|
|
13
|
+
* Hash a password asynchronously using bcrypt.
|
|
14
|
+
*/
|
|
15
|
+
const hashPassword = async (password, saltRounds = 10) => {
|
|
16
|
+
try {
|
|
17
|
+
(0, utils_1.ensureValidPassword)(password);
|
|
18
|
+
const salt = await bcryptjs_1.default.genSalt(saltRounds);
|
|
19
|
+
return bcryptjs_1.default.hash(password, salt);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
throw new errors_utils_1.InternalServerError('Password hashing failed');
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
exports.hashPassword = hashPassword;
|
|
26
|
+
function hashPasswordWithPepper(password, pepper) {
|
|
27
|
+
return (0, exports.hashPassword)(password + pepper);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hash a password synchronously using bcrypt.
|
|
31
|
+
*/
|
|
32
|
+
const hashPasswordSync = (password, saltRounds = 10) => {
|
|
33
|
+
try {
|
|
34
|
+
(0, utils_1.ensureValidPassword)(password);
|
|
35
|
+
const salt = bcryptjs_1.default.genSaltSync(saltRounds);
|
|
36
|
+
return bcryptjs_1.default.hashSync(password, salt);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new errors_utils_1.InternalServerError('Password hashing failed');
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.hashPasswordSync = hashPasswordSync;
|
|
43
|
+
function hashPasswordWithPepperSync(password, pepper) {
|
|
44
|
+
return (0, exports.hashPasswordSync)(password + pepper);
|
|
45
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./hash"), exports);
|
|
18
|
+
__exportStar(require("./strength"), exports);
|
|
19
|
+
__exportStar(require("./verify"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPasswordStrong = void 0;
|
|
4
|
+
const errors_utils_1 = require("@naman_deep_singh/errors-utils");
|
|
5
|
+
const isPasswordStrong = (password, options = {}) => {
|
|
6
|
+
if (!password)
|
|
7
|
+
throw new errors_utils_1.BadRequestError('Invalid password provided');
|
|
8
|
+
const { minLength = 8, requireUppercase = true, requireLowercase = true, requireNumbers = true, requireSymbols = false, } = options;
|
|
9
|
+
if (password.length < minLength)
|
|
10
|
+
throw new errors_utils_1.ValidationError(`Password must be at least ${minLength} characters`);
|
|
11
|
+
if (requireUppercase && !/[A-Z]/.test(password))
|
|
12
|
+
throw new errors_utils_1.ValidationError("Password must include uppercase letters");
|
|
13
|
+
if (requireLowercase && !/[a-z]/.test(password))
|
|
14
|
+
throw new errors_utils_1.ValidationError("Password must include lowercase letters");
|
|
15
|
+
if (requireNumbers && !/[0-9]/.test(password))
|
|
16
|
+
throw new errors_utils_1.ValidationError("Password must include numbers");
|
|
17
|
+
if (requireSymbols && !/[^A-Za-z0-9]/.test(password))
|
|
18
|
+
throw new errors_utils_1.ValidationError("Password must include symbols");
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
21
|
+
exports.isPasswordStrong = isPasswordStrong;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function ensureValidPassword(password: string): void;
|
|
2
|
+
export declare function safeCompare(a: string, b: string): boolean;
|
|
3
|
+
export declare function estimatePasswordEntropy(password: string): number;
|
|
4
|
+
export declare function normalizePassword(password: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ensureValidPassword = ensureValidPassword;
|
|
7
|
+
exports.safeCompare = safeCompare;
|
|
8
|
+
exports.estimatePasswordEntropy = estimatePasswordEntropy;
|
|
9
|
+
exports.normalizePassword = normalizePassword;
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
const errors_utils_1 = require("@naman_deep_singh/errors-utils");
|
|
12
|
+
function ensureValidPassword(password) {
|
|
13
|
+
if (!password || typeof password !== "string") {
|
|
14
|
+
throw new errors_utils_1.BadRequestError('Invalid password provided');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function safeCompare(a, b) {
|
|
18
|
+
const bufA = Buffer.from(a);
|
|
19
|
+
const bufB = Buffer.from(b);
|
|
20
|
+
if (bufA.length !== bufB.length)
|
|
21
|
+
return false;
|
|
22
|
+
return crypto_1.default.timingSafeEqual(bufA, bufB);
|
|
23
|
+
}
|
|
24
|
+
function estimatePasswordEntropy(password) {
|
|
25
|
+
let pool = 0;
|
|
26
|
+
if (/[a-z]/.test(password))
|
|
27
|
+
pool += 26;
|
|
28
|
+
if (/[A-Z]/.test(password))
|
|
29
|
+
pool += 26;
|
|
30
|
+
if (/[0-9]/.test(password))
|
|
31
|
+
pool += 10;
|
|
32
|
+
if (/[^A-Za-z0-9]/.test(password))
|
|
33
|
+
pool += 32;
|
|
34
|
+
return password.length * Math.log2(pool);
|
|
35
|
+
}
|
|
36
|
+
function normalizePassword(password) {
|
|
37
|
+
return password.normalize("NFKC");
|
|
38
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare a password with a stored hash asynchronously.
|
|
3
|
+
*/
|
|
4
|
+
export declare const verifyPassword: (password: string, hash: string) => Promise<boolean>;
|
|
5
|
+
export declare function verifyPasswordWithPepper(password: string, pepper: string, hash: string): Promise<boolean>;
|
|
6
|
+
/**
|
|
7
|
+
* Compare a password with a stored hash synchronously.
|
|
8
|
+
*/
|
|
9
|
+
export declare const verifyPasswordSync: (password: string, hash: string) => boolean;
|
|
10
|
+
export declare function verifyPasswordWithPepperSync(password: string, pepper: string, hash: string): Promise<boolean>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyPasswordSync = exports.verifyPassword = void 0;
|
|
7
|
+
exports.verifyPasswordWithPepper = verifyPasswordWithPepper;
|
|
8
|
+
exports.verifyPasswordWithPepperSync = verifyPasswordWithPepperSync;
|
|
9
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
10
|
+
const errors_utils_1 = require("@naman_deep_singh/errors-utils");
|
|
11
|
+
/**
|
|
12
|
+
* Compare a password with a stored hash asynchronously.
|
|
13
|
+
*/
|
|
14
|
+
const verifyPassword = async (password, hash) => {
|
|
15
|
+
try {
|
|
16
|
+
const result = await bcryptjs_1.default.compare(password, hash);
|
|
17
|
+
if (!result)
|
|
18
|
+
throw new errors_utils_1.UnauthorizedError('Password verification failed');
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new errors_utils_1.UnauthorizedError('Password verification failed');
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
exports.verifyPassword = verifyPassword;
|
|
26
|
+
async function verifyPasswordWithPepper(password, pepper, hash) {
|
|
27
|
+
return (0, exports.verifyPassword)(password + pepper, hash);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compare a password with a stored hash synchronously.
|
|
31
|
+
*/
|
|
32
|
+
const verifyPasswordSync = (password, hash) => {
|
|
33
|
+
try {
|
|
34
|
+
const result = bcryptjs_1.default.compareSync(password, hash);
|
|
35
|
+
if (!result)
|
|
36
|
+
throw new errors_utils_1.UnauthorizedError('Password verification failed');
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new errors_utils_1.UnauthorizedError('Password verification failed');
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.verifyPasswordSync = verifyPasswordSync;
|
|
44
|
+
async function verifyPasswordWithPepperSync(password, pepper, hash) {
|
|
45
|
+
return (0, exports.verifyPasswordSync)(password + pepper, hash);
|
|
46
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export * from "./core/password";
|
|
2
|
+
export * from "./core/jwt";
|
|
3
|
+
export * from "./core/crypto";
|
|
4
|
+
export { BadRequestError, UnauthorizedError, ValidationError, InternalServerError } from "@naman_deep_singh/errors-utils";
|
|
5
|
+
import * as JWTUtils from "./core/jwt";
|
|
6
|
+
declare const _default: {
|
|
7
|
+
decrypt: (data: string, secret: string) => string;
|
|
8
|
+
encrypt: (text: string, secret: string) => string;
|
|
9
|
+
hmacSign: (message: string, secret: string) => string;
|
|
10
|
+
hmacVerify: (message: string, secret: string, signature: string) => boolean;
|
|
11
|
+
randomToken: (length?: number) => string;
|
|
12
|
+
generateStrongPassword: (length?: number) => string;
|
|
13
|
+
decodeToken(token: string): null | string | import("node_modules/@types/jsonwebtoken").JwtPayload;
|
|
14
|
+
decodeTokenStrict(token: string): import("node_modules/@types/jsonwebtoken").JwtPayload;
|
|
15
|
+
extractToken(sources: JWTUtils.TokenSources): string | null;
|
|
16
|
+
rotateRefreshToken(oldToken: string, secret: import("node_modules/@types/jsonwebtoken").Secret): JWTUtils.RefreshToken;
|
|
17
|
+
generateTokens: (payload: Record<string, unknown>, accessSecret: import("node_modules/@types/jsonwebtoken").Secret, refreshSecret: import("node_modules/@types/jsonwebtoken").Secret, accessExpiry?: string | number, refreshExpiry?: string | number) => JWTUtils.TokenPair;
|
|
18
|
+
parseDuration(input: string | number): number;
|
|
19
|
+
signToken: (payload: Record<string, unknown>, secret: import("node_modules/@types/jsonwebtoken").Secret, expiresIn?: string | number, options?: import("node_modules/@types/jsonwebtoken").SignOptions) => string;
|
|
20
|
+
validateTokenPayload(payload: Record<string, unknown>, rules?: JWTUtils.TokenRequirements): {
|
|
21
|
+
valid: true;
|
|
22
|
+
} | {
|
|
23
|
+
valid: false;
|
|
24
|
+
error: string;
|
|
25
|
+
};
|
|
26
|
+
isTokenExpired(payload: import("node_modules/@types/jsonwebtoken").JwtPayload): boolean;
|
|
27
|
+
verifyToken: (token: string, secret: import("node_modules/@types/jsonwebtoken").Secret) => string | import("node_modules/@types/jsonwebtoken").JwtPayload;
|
|
28
|
+
safeVerifyToken: (token: string, secret: import("node_modules/@types/jsonwebtoken").Secret) => JWTUtils.VerificationResult;
|
|
29
|
+
verifyTokenWithOptions: (token: string, secret: import("node_modules/@types/jsonwebtoken").Secret, options?: import("node_modules/@types/jsonwebtoken").VerifyOptions) => string | import("node_modules/@types/jsonwebtoken").JwtPayload;
|
|
30
|
+
safeVerifyTokenWithOptions: (token: string, secret: import("node_modules/@types/jsonwebtoken").Secret, options?: import("node_modules/@types/jsonwebtoken").VerifyOptions) => JWTUtils.VerificationResult;
|
|
31
|
+
hashPasswordWithPepper(password: string, pepper: string): Promise<string>;
|
|
32
|
+
hashPasswordWithPepperSync(password: string, pepper: string): string;
|
|
33
|
+
hashPassword: (password: string, saltRounds?: number) => Promise<string>;
|
|
34
|
+
hashPasswordSync: (password: string, saltRounds?: number) => string;
|
|
35
|
+
isPasswordStrong: (password: string, options?: import("./core/password/types").PasswordStrengthOptions) => boolean;
|
|
36
|
+
verifyPasswordWithPepper(password: string, pepper: string, hash: string): Promise<boolean>;
|
|
37
|
+
verifyPasswordWithPepperSync(password: string, pepper: string, hash: string): Promise<boolean>;
|
|
38
|
+
verifyPassword: (password: string, hash: string) => Promise<boolean>;
|
|
39
|
+
verifyPasswordSync: (password: string, hash: string) => boolean;
|
|
40
|
+
};
|
|
41
|
+
export default _default;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.InternalServerError = exports.ValidationError = exports.UnauthorizedError = exports.BadRequestError = void 0;
|
|
40
|
+
__exportStar(require("./core/password"), exports);
|
|
41
|
+
__exportStar(require("./core/jwt"), exports);
|
|
42
|
+
__exportStar(require("./core/crypto"), exports);
|
|
43
|
+
// Re-export common errors for convenience
|
|
44
|
+
var errors_utils_1 = require("@naman_deep_singh/errors-utils");
|
|
45
|
+
Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return errors_utils_1.BadRequestError; } });
|
|
46
|
+
Object.defineProperty(exports, "UnauthorizedError", { enumerable: true, get: function () { return errors_utils_1.UnauthorizedError; } });
|
|
47
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_utils_1.ValidationError; } });
|
|
48
|
+
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return errors_utils_1.InternalServerError; } });
|
|
49
|
+
const PasswordUtils = __importStar(require("./core/password"));
|
|
50
|
+
const JWTUtils = __importStar(require("./core/jwt"));
|
|
51
|
+
const CryptoUtils = __importStar(require("./core/crypto"));
|
|
52
|
+
exports.default = {
|
|
53
|
+
...PasswordUtils,
|
|
54
|
+
...JWTUtils,
|
|
55
|
+
...CryptoUtils,
|
|
56
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const decrypt: (data: string, secret: string) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
const ALGO = "AES-256-GCM";
|
|
3
|
+
export const decrypt = (data, secret) => {
|
|
4
|
+
const [ivHex, encryptedHex] = data.split(":");
|
|
5
|
+
const iv = Buffer.from(ivHex, "hex");
|
|
6
|
+
const encrypted = Buffer.from(encryptedHex, "hex");
|
|
7
|
+
const key = crypto.createHash("sha256").update(secret).digest();
|
|
8
|
+
const decipher = crypto.createDecipheriv(ALGO, key, iv);
|
|
9
|
+
const decrypted = Buffer.concat([
|
|
10
|
+
decipher.update(encrypted),
|
|
11
|
+
decipher.final(),
|
|
12
|
+
]);
|
|
13
|
+
return decrypted.toString("utf8");
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const encrypt: (text: string, secret: string) => string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
const ALGO = "AES-256-GCM";
|
|
3
|
+
export const encrypt = (text, secret) => {
|
|
4
|
+
const key = crypto.createHash("sha256").update(secret).digest();
|
|
5
|
+
const iv = crypto.randomBytes(16);
|
|
6
|
+
const cipher = crypto.createCipheriv(ALGO, key, iv);
|
|
7
|
+
const encrypted = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);
|
|
8
|
+
return `${iv.toString("hex")}:${encrypted.toString("hex")}`;
|
|
9
|
+
};
|