@naman_deep_singh/security 1.2.0 → 1.3.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.
Files changed (35) hide show
  1. package/README.md +355 -176
  2. package/dist/cjs/core/crypto/cryptoManager.d.ts +111 -0
  3. package/dist/cjs/core/crypto/cryptoManager.js +185 -0
  4. package/dist/cjs/core/crypto/index.d.ts +5 -4
  5. package/dist/cjs/core/crypto/index.js +12 -4
  6. package/dist/cjs/core/jwt/jwtManager.d.ts +66 -0
  7. package/dist/cjs/core/jwt/jwtManager.js +319 -0
  8. package/dist/cjs/core/password/passwordManager.d.ts +29 -0
  9. package/dist/cjs/core/password/passwordManager.js +242 -0
  10. package/dist/cjs/index.d.ts +4 -0
  11. package/dist/cjs/interfaces/jwt.interface.d.ts +47 -0
  12. package/dist/cjs/interfaces/jwt.interface.js +2 -0
  13. package/dist/cjs/interfaces/password.interface.d.ts +60 -0
  14. package/dist/cjs/interfaces/password.interface.js +2 -0
  15. package/dist/esm/core/crypto/cryptoManager.d.ts +111 -0
  16. package/dist/esm/core/crypto/cryptoManager.js +180 -0
  17. package/dist/esm/core/crypto/index.d.ts +5 -4
  18. package/dist/esm/core/crypto/index.js +5 -4
  19. package/dist/esm/core/jwt/jwtManager.d.ts +66 -0
  20. package/dist/esm/core/jwt/jwtManager.js +312 -0
  21. package/dist/esm/core/password/passwordManager.d.ts +29 -0
  22. package/dist/esm/core/password/passwordManager.js +235 -0
  23. package/dist/esm/index.d.ts +4 -0
  24. package/dist/esm/interfaces/jwt.interface.d.ts +47 -0
  25. package/dist/esm/interfaces/jwt.interface.js +1 -0
  26. package/dist/esm/interfaces/password.interface.d.ts +60 -0
  27. package/dist/esm/interfaces/password.interface.js +1 -0
  28. package/dist/types/core/crypto/cryptoManager.d.ts +111 -0
  29. package/dist/types/core/crypto/index.d.ts +5 -4
  30. package/dist/types/core/jwt/jwtManager.d.ts +66 -0
  31. package/dist/types/core/password/passwordManager.d.ts +29 -0
  32. package/dist/types/index.d.ts +4 -0
  33. package/dist/types/interfaces/jwt.interface.d.ts +47 -0
  34. package/dist/types/interfaces/password.interface.d.ts +60 -0
  35. package/package.json +1 -1
@@ -0,0 +1,319 @@
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.JWTManager = void 0;
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const signToken_1 = require("./signToken");
9
+ const verify_1 = require("./verify");
10
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
11
+ // Simple LRU cache for token validation
12
+ class TokenCache {
13
+ constructor(maxSize = 100, ttl = 5 * 60 * 1000) {
14
+ this.cache = new Map();
15
+ this.maxSize = maxSize;
16
+ this.ttl = ttl;
17
+ }
18
+ get(key) {
19
+ const entry = this.cache.get(key);
20
+ if (!entry)
21
+ return null;
22
+ if (Date.now() - entry.timestamp > this.ttl) {
23
+ this.cache.delete(key);
24
+ return null;
25
+ }
26
+ // Move to end (most recently used)
27
+ this.cache.delete(key);
28
+ this.cache.set(key, entry);
29
+ return { valid: entry.valid, payload: entry.payload };
30
+ }
31
+ set(key, value) {
32
+ if (this.cache.has(key)) {
33
+ this.cache.delete(key);
34
+ }
35
+ else if (this.cache.size >= this.maxSize) {
36
+ // Remove least recently used (first item)
37
+ const firstKey = this.cache.keys().next().value;
38
+ if (firstKey !== undefined) {
39
+ this.cache.delete(firstKey);
40
+ }
41
+ }
42
+ this.cache.set(key, { ...value, timestamp: Date.now() });
43
+ }
44
+ clear() {
45
+ this.cache.clear();
46
+ }
47
+ }
48
+ class JWTManager {
49
+ constructor(config) {
50
+ this.accessSecret = config.accessSecret;
51
+ this.refreshSecret = config.refreshSecret;
52
+ this.accessExpiry = config.accessExpiry || "15m";
53
+ this.refreshExpiry = config.refreshExpiry || "7d";
54
+ if (config.enableCaching) {
55
+ this.cache = new TokenCache(config.maxCacheSize || 100);
56
+ }
57
+ }
58
+ /**
59
+ * Generate both access and refresh tokens
60
+ */
61
+ async generateTokens(payload) {
62
+ try {
63
+ this.validatePayload(payload);
64
+ const accessToken = await this.generateAccessToken(payload);
65
+ const refreshToken = await this.generateRefreshToken(payload);
66
+ return {
67
+ accessToken,
68
+ refreshToken,
69
+ };
70
+ }
71
+ catch (error) {
72
+ if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
73
+ throw error;
74
+ }
75
+ throw new errors_utils_1.BadRequestError("Failed to generate tokens");
76
+ }
77
+ }
78
+ /**
79
+ * Generate access token
80
+ */
81
+ async generateAccessToken(payload) {
82
+ try {
83
+ this.validatePayload(payload);
84
+ const token = (0, signToken_1.signToken)(payload, this.accessSecret, this.accessExpiry, { algorithm: "HS256" });
85
+ return token;
86
+ }
87
+ catch (error) {
88
+ if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
89
+ throw error;
90
+ }
91
+ throw new errors_utils_1.BadRequestError("Failed to generate access token");
92
+ }
93
+ }
94
+ /**
95
+ * Generate refresh token
96
+ */
97
+ async generateRefreshToken(payload) {
98
+ try {
99
+ this.validatePayload(payload);
100
+ const token = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry, { algorithm: "HS256" });
101
+ return token;
102
+ }
103
+ catch (error) {
104
+ if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
105
+ throw error;
106
+ }
107
+ throw new errors_utils_1.BadRequestError("Failed to generate refresh token");
108
+ }
109
+ }
110
+ /**
111
+ * Verify access token
112
+ */
113
+ async verifyAccessToken(token) {
114
+ try {
115
+ if (!token || typeof token !== "string") {
116
+ throw new errors_utils_1.ValidationError("Access token must be a non-empty string");
117
+ }
118
+ const cacheKey = `access_${token}`;
119
+ if (this.cache) {
120
+ const cached = this.cache.get(cacheKey);
121
+ if (cached) {
122
+ if (!cached.valid) {
123
+ throw new errors_utils_1.UnauthorizedError("Access token is invalid or expired");
124
+ }
125
+ return cached.payload;
126
+ }
127
+ }
128
+ const decoded = (0, verify_1.verifyToken)(token, this.accessSecret);
129
+ if (this.cache) {
130
+ this.cache.set(cacheKey, { valid: true, payload: decoded });
131
+ }
132
+ return decoded;
133
+ }
134
+ catch (error) {
135
+ if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
136
+ throw error;
137
+ }
138
+ if (error instanceof Error && error.name === "TokenExpiredError") {
139
+ throw new errors_utils_1.UnauthorizedError("Access token has expired");
140
+ }
141
+ if (error instanceof Error && error.name === "JsonWebTokenError") {
142
+ throw new errors_utils_1.UnauthorizedError("Access token is invalid");
143
+ }
144
+ throw new errors_utils_1.UnauthorizedError("Failed to verify access token");
145
+ }
146
+ }
147
+ /**
148
+ * Verify refresh token
149
+ */
150
+ async verifyRefreshToken(token) {
151
+ try {
152
+ if (!token || typeof token !== "string") {
153
+ throw new errors_utils_1.ValidationError("Refresh token must be a non-empty string");
154
+ }
155
+ const cacheKey = `refresh_${token}`;
156
+ if (this.cache) {
157
+ const cached = this.cache.get(cacheKey);
158
+ if (cached) {
159
+ if (!cached.valid) {
160
+ throw new errors_utils_1.UnauthorizedError("Refresh token is invalid or expired");
161
+ }
162
+ return cached.payload;
163
+ }
164
+ }
165
+ const decoded = (0, verify_1.verifyToken)(token, this.refreshSecret);
166
+ if (this.cache) {
167
+ this.cache.set(cacheKey, { valid: true, payload: decoded });
168
+ }
169
+ return decoded;
170
+ }
171
+ catch (error) {
172
+ if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
173
+ throw error;
174
+ }
175
+ if (error instanceof Error && error.name === "TokenExpiredError") {
176
+ throw new errors_utils_1.UnauthorizedError("Refresh token has expired");
177
+ }
178
+ if (error instanceof Error && error.name === "JsonWebTokenError") {
179
+ throw new errors_utils_1.UnauthorizedError("Refresh token is invalid");
180
+ }
181
+ throw new errors_utils_1.UnauthorizedError("Failed to verify refresh token");
182
+ }
183
+ }
184
+ /**
185
+ * Decode token without verification
186
+ */
187
+ decodeToken(token, complete = false) {
188
+ try {
189
+ if (!token || typeof token !== "string") {
190
+ throw new errors_utils_1.ValidationError("Token must be a non-empty string");
191
+ }
192
+ return jsonwebtoken_1.default.decode(token, { complete });
193
+ }
194
+ catch (error) {
195
+ if (error instanceof errors_utils_1.ValidationError) {
196
+ throw error;
197
+ }
198
+ return null;
199
+ }
200
+ }
201
+ /**
202
+ * Extract token from Authorization header
203
+ */
204
+ extractTokenFromHeader(authHeader) {
205
+ try {
206
+ if (!authHeader || typeof authHeader !== "string") {
207
+ return null;
208
+ }
209
+ const parts = authHeader.split(" ");
210
+ if (parts.length !== 2 || parts[0] !== "Bearer") {
211
+ return null;
212
+ }
213
+ return parts[1];
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ /**
220
+ * Validate token without throwing exceptions
221
+ */
222
+ validateToken(token, secret, options = {}) {
223
+ try {
224
+ if (!token || typeof token !== "string") {
225
+ return false;
226
+ }
227
+ const result = (0, verify_1.safeVerifyToken)(token, secret);
228
+ return result.valid;
229
+ }
230
+ catch {
231
+ return false;
232
+ }
233
+ }
234
+ /**
235
+ * Rotate refresh token
236
+ */
237
+ async rotateRefreshToken(oldToken) {
238
+ try {
239
+ if (!oldToken || typeof oldToken !== "string") {
240
+ throw new errors_utils_1.ValidationError("Old refresh token must be a non-empty string");
241
+ }
242
+ const decoded = await this.verifyRefreshToken(oldToken);
243
+ if (typeof decoded === "string") {
244
+ throw new errors_utils_1.ValidationError("Invalid token payload — expected JWT payload object");
245
+ }
246
+ // Create new payload without issued/expired timestamps
247
+ const payload = { ...decoded };
248
+ delete payload.iat;
249
+ delete payload.exp;
250
+ // Generate new refresh token
251
+ const newToken = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry);
252
+ return newToken;
253
+ }
254
+ catch (error) {
255
+ if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
256
+ throw error;
257
+ }
258
+ throw new errors_utils_1.BadRequestError("Failed to rotate refresh token");
259
+ }
260
+ }
261
+ /**
262
+ * Check if token is expired
263
+ */
264
+ isTokenExpired(token) {
265
+ try {
266
+ const decoded = this.decodeToken(token);
267
+ if (!decoded || !decoded.exp) {
268
+ return true;
269
+ }
270
+ const currentTime = Math.floor(Date.now() / 1000);
271
+ return decoded.exp < currentTime;
272
+ }
273
+ catch {
274
+ return true;
275
+ }
276
+ }
277
+ /**
278
+ * Get token expiration date
279
+ */
280
+ getTokenExpiration(token) {
281
+ try {
282
+ const decoded = this.decodeToken(token);
283
+ if (!decoded || !decoded.exp) {
284
+ return null;
285
+ }
286
+ return new Date(decoded.exp * 1000);
287
+ }
288
+ catch {
289
+ return null;
290
+ }
291
+ }
292
+ /**
293
+ * Clear token cache
294
+ */
295
+ clearCache() {
296
+ this.cache?.clear();
297
+ }
298
+ /**
299
+ * Get cache statistics
300
+ */
301
+ getCacheStats() {
302
+ if (!this.cache)
303
+ return null;
304
+ return {
305
+ size: this.cache.cache.size,
306
+ maxSize: this.cache.maxSize
307
+ };
308
+ }
309
+ // Private helper methods
310
+ validatePayload(payload) {
311
+ if (!payload || typeof payload !== "object") {
312
+ throw new errors_utils_1.ValidationError("Payload must be a non-null object");
313
+ }
314
+ if (Object.keys(payload).length === 0) {
315
+ throw new errors_utils_1.ValidationError("Payload cannot be empty");
316
+ }
317
+ }
318
+ }
319
+ exports.JWTManager = JWTManager;
@@ -0,0 +1,29 @@
1
+ import { IPasswordManager, PasswordConfig, PasswordValidationResult, HashedPassword, PasswordStrength } from "../../interfaces/password.interface";
2
+ export declare class PasswordManager implements IPasswordManager {
3
+ private defaultConfig;
4
+ constructor(config?: PasswordConfig);
5
+ /**
6
+ * Hash a password asynchronously using bcrypt
7
+ */
8
+ hash(password: string, salt?: string): Promise<HashedPassword>;
9
+ /**
10
+ * Verify password against hash and salt
11
+ */
12
+ verify(password: string, hash: string, salt: string): Promise<boolean>;
13
+ /**
14
+ * Generate a random password
15
+ */
16
+ generate(length?: number, options?: PasswordConfig): string;
17
+ /**
18
+ * Validate password against configuration
19
+ */
20
+ validate(password: string, config?: PasswordConfig): PasswordValidationResult;
21
+ /**
22
+ * Check password strength
23
+ */
24
+ checkStrength(password: string): PasswordStrength;
25
+ /**
26
+ * Check if password hash needs upgrade (different salt rounds)
27
+ */
28
+ needsUpgrade(hash: string, currentConfig: PasswordConfig): boolean;
29
+ }
@@ -0,0 +1,242 @@
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.PasswordManager = void 0;
7
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const utils_1 = require("./utils");
10
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
11
+ class PasswordManager {
12
+ constructor(config = {}) {
13
+ this.defaultConfig = {
14
+ saltRounds: 10,
15
+ minLength: 8,
16
+ maxLength: 128,
17
+ requireUppercase: true,
18
+ requireLowercase: true,
19
+ requireNumbers: true,
20
+ requireSpecialChars: false,
21
+ ...config
22
+ };
23
+ }
24
+ /**
25
+ * Hash a password asynchronously using bcrypt
26
+ */
27
+ async hash(password, salt) {
28
+ try {
29
+ (0, utils_1.ensureValidPassword)(password);
30
+ // Validate password meets basic requirements
31
+ this.validate(password);
32
+ const saltRounds = this.defaultConfig.saltRounds;
33
+ let passwordSalt = salt;
34
+ if (!passwordSalt) {
35
+ passwordSalt = await bcryptjs_1.default.genSalt(saltRounds);
36
+ }
37
+ const hash = await bcryptjs_1.default.hash(password, passwordSalt);
38
+ return {
39
+ hash,
40
+ salt: passwordSalt
41
+ };
42
+ }
43
+ catch (error) {
44
+ if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
45
+ throw error;
46
+ }
47
+ throw new errors_utils_1.BadRequestError("Failed to hash password");
48
+ }
49
+ }
50
+ /**
51
+ * Verify password against hash and salt
52
+ */
53
+ async verify(password, hash, salt) {
54
+ try {
55
+ if (!password || !hash || !salt) {
56
+ return false;
57
+ }
58
+ // First verify with the provided salt
59
+ const isValid = await bcryptjs_1.default.compare(password, hash);
60
+ // If invalid and different salt was used, try regenerating hash with new salt
61
+ if (!isValid && salt !== this.defaultConfig.saltRounds?.toString()) {
62
+ const newHash = await bcryptjs_1.default.hash(password, salt);
63
+ return newHash === hash;
64
+ }
65
+ return isValid;
66
+ }
67
+ catch (error) {
68
+ return false;
69
+ }
70
+ }
71
+ /**
72
+ * Generate a random password
73
+ */
74
+ generate(length = 16, options = {}) {
75
+ const config = { ...this.defaultConfig, ...options };
76
+ if (length < config.minLength || length > config.maxLength) {
77
+ throw new errors_utils_1.ValidationError(`Password length must be between ${config.minLength} and ${config.maxLength}`);
78
+ }
79
+ let charset = "abcdefghijklmnopqrstuvwxyz";
80
+ if (config.requireUppercase)
81
+ charset += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
82
+ if (config.requireNumbers)
83
+ charset += "0123456789";
84
+ if (config.requireSpecialChars)
85
+ charset += "!@#$%^&*()_+-=[]{}|;:,.<>?";
86
+ let password = "";
87
+ const randomBytes = crypto_1.default.randomBytes(length);
88
+ for (let i = 0; i < length; i++) {
89
+ password += charset[randomBytes[i] % charset.length];
90
+ }
91
+ // Ensure all requirements are met
92
+ if (config.requireUppercase && !/[A-Z]/.test(password)) {
93
+ password = password.replace(/[a-z]/, 'A');
94
+ }
95
+ if (config.requireLowercase && !/[a-z]/.test(password)) {
96
+ password = password.replace(/[A-Z]/, 'a');
97
+ }
98
+ if (config.requireNumbers && !/[0-9]/.test(password)) {
99
+ password = password.replace(/[A-Za-z]/, '0');
100
+ }
101
+ if (config.requireSpecialChars && !/[^A-Za-z0-9]/.test(password)) {
102
+ password = password.replace(/[A-Za-z0-9]/, '!');
103
+ }
104
+ return password;
105
+ }
106
+ /**
107
+ * Validate password against configuration
108
+ */
109
+ validate(password, config = {}) {
110
+ const finalConfig = { ...this.defaultConfig, ...config };
111
+ const errors = [];
112
+ // Basic validation
113
+ if (!password || typeof password !== "string") {
114
+ errors.push("Password must be a non-empty string");
115
+ }
116
+ // Length validation
117
+ if (password.length < finalConfig.minLength) {
118
+ errors.push(`Password must be at least ${finalConfig.minLength} characters long`);
119
+ }
120
+ if (password.length > finalConfig.maxLength) {
121
+ errors.push(`Password must not exceed ${finalConfig.maxLength} characters`);
122
+ }
123
+ // Complexity requirements
124
+ if (finalConfig.requireUppercase && !/[A-Z]/.test(password)) {
125
+ errors.push("Password must contain at least one uppercase letter");
126
+ }
127
+ if (finalConfig.requireLowercase && !/[a-z]/.test(password)) {
128
+ errors.push("Password must contain at least one lowercase letter");
129
+ }
130
+ if (finalConfig.requireNumbers && !/[0-9]/.test(password)) {
131
+ errors.push("Password must contain at least one number");
132
+ }
133
+ if (finalConfig.requireSpecialChars && !/[^A-Za-z0-9]/.test(password)) {
134
+ errors.push("Password must contain at least one special character");
135
+ }
136
+ // Custom rules
137
+ if (finalConfig.customRules) {
138
+ finalConfig.customRules.forEach(rule => {
139
+ if (!rule.test(password)) {
140
+ errors.push(rule.message);
141
+ }
142
+ });
143
+ }
144
+ const strength = this.checkStrength(password);
145
+ const isValid = errors.length === 0;
146
+ return {
147
+ isValid,
148
+ errors,
149
+ strength
150
+ };
151
+ }
152
+ /**
153
+ * Check password strength
154
+ */
155
+ checkStrength(password) {
156
+ const entropy = (0, utils_1.estimatePasswordEntropy)(password);
157
+ let score = 0;
158
+ const feedback = [];
159
+ const suggestions = [];
160
+ // Length scoring
161
+ if (password.length >= 8)
162
+ score++;
163
+ if (password.length >= 12)
164
+ score++;
165
+ if (password.length >= 16)
166
+ score++;
167
+ // Character variety scoring
168
+ if (/[a-z]/.test(password))
169
+ score++;
170
+ if (/[A-Z]/.test(password))
171
+ score++;
172
+ if (/[0-9]/.test(password))
173
+ score++;
174
+ if (/[^A-Za-z0-9]/.test(password))
175
+ score++;
176
+ // Common patterns deduction
177
+ if (/^[A-Za-z]+$/.test(password)) {
178
+ score--;
179
+ feedback.push("Consider adding numbers and symbols");
180
+ }
181
+ if (/^[0-9]+$/.test(password)) {
182
+ score -= 2;
183
+ feedback.push("Avoid using only numbers");
184
+ }
185
+ if (/([a-zA-Z0-9])\1{2,}/.test(password)) {
186
+ score--;
187
+ feedback.push("Avoid repeated characters");
188
+ }
189
+ if (/(?:012|123|234|345|456|567|678|789)/.test(password)) {
190
+ score--;
191
+ feedback.push("Avoid sequential patterns");
192
+ }
193
+ // Common passwords check
194
+ const commonPasswords = ['password', '123456', 'qwerty', 'admin', 'letmein'];
195
+ if (commonPasswords.some(common => password.toLowerCase().includes(common))) {
196
+ score = 0;
197
+ feedback.push("Avoid common passwords");
198
+ }
199
+ // Clamp score and determine label
200
+ score = Math.max(0, Math.min(4, score));
201
+ let label;
202
+ switch (score) {
203
+ case 0:
204
+ label = 'very-weak';
205
+ suggestions.push("Use a longer password with mixed characters");
206
+ break;
207
+ case 1:
208
+ label = 'weak';
209
+ suggestions.push("Add more character variety");
210
+ break;
211
+ case 2:
212
+ label = 'fair';
213
+ suggestions.push("Consider adding more length or character types");
214
+ break;
215
+ case 3:
216
+ label = 'good';
217
+ suggestions.push("Your password is reasonably secure");
218
+ break;
219
+ case 4:
220
+ label = 'strong';
221
+ suggestions.push("Your password is very secure");
222
+ break;
223
+ default:
224
+ label = 'very-weak';
225
+ }
226
+ return {
227
+ score,
228
+ label,
229
+ feedback,
230
+ suggestions
231
+ };
232
+ }
233
+ /**
234
+ * Check if password hash needs upgrade (different salt rounds)
235
+ */
236
+ needsUpgrade(hash, currentConfig) {
237
+ // Simple heuristic: if the hash doesn't match current salt rounds pattern
238
+ // In practice, you'd need to store the salt rounds with the hash
239
+ return false;
240
+ }
241
+ }
242
+ exports.PasswordManager = PasswordManager;
@@ -3,6 +3,7 @@ export * from "./core/jwt";
3
3
  export * from "./core/crypto";
4
4
  export { BadRequestError, UnauthorizedError, ValidationError, InternalServerError } from "@naman_deep_singh/errors-utils";
5
5
  import * as JWTUtils from "./core/jwt";
6
+ import * as CryptoUtils from "./core/crypto";
6
7
  declare const _default: {
7
8
  decrypt: (data: string, secret: string) => string;
8
9
  encrypt: (text: string, secret: string) => string;
@@ -10,6 +11,9 @@ declare const _default: {
10
11
  hmacVerify: (message: string, secret: string, signature: string) => boolean;
11
12
  randomToken: (length?: number) => string;
12
13
  generateStrongPassword: (length?: number) => string;
14
+ CryptoManager: typeof CryptoUtils.CryptoManager;
15
+ createCryptoManager: (config?: CryptoUtils.CryptoManagerConfig) => CryptoUtils.CryptoManager;
16
+ cryptoManager: CryptoUtils.CryptoManager;
13
17
  decodeToken(token: string): null | string | import("node_modules/@types/jsonwebtoken").JwtPayload;
14
18
  decodeTokenStrict(token: string): import("node_modules/@types/jsonwebtoken").JwtPayload;
15
19
  extractToken(sources: JWTUtils.TokenSources): string | null;
@@ -0,0 +1,47 @@
1
+ import { JwtPayload, Secret } from "jsonwebtoken";
2
+ export interface AccessToken extends String {
3
+ readonly __type: 'AccessToken';
4
+ }
5
+ export interface RefreshToken extends String {
6
+ readonly __type: 'RefreshToken';
7
+ }
8
+ export interface TokenPair {
9
+ accessToken: AccessToken;
10
+ refreshToken: RefreshToken;
11
+ }
12
+ export interface JWTConfig {
13
+ accessSecret: Secret;
14
+ refreshSecret: Secret;
15
+ accessExpiry?: string | number;
16
+ refreshExpiry?: string | number;
17
+ enableCaching?: boolean;
18
+ maxCacheSize?: number;
19
+ }
20
+ export interface TokenValidationOptions {
21
+ ignoreExpiration?: boolean;
22
+ ignoreNotBefore?: boolean;
23
+ audience?: string | string[];
24
+ issuer?: string;
25
+ algorithms?: string[];
26
+ }
27
+ export interface TokenGenerationOptions {
28
+ algorithm?: string;
29
+ expiresIn?: string | number;
30
+ audience?: string | string[];
31
+ issuer?: string;
32
+ subject?: string;
33
+ kid?: string;
34
+ }
35
+ export interface ITokenManager {
36
+ generateTokens(payload: Record<string, unknown>): Promise<TokenPair>;
37
+ generateAccessToken(payload: Record<string, unknown>): Promise<AccessToken>;
38
+ generateRefreshToken(payload: Record<string, unknown>): Promise<RefreshToken>;
39
+ verifyAccessToken(token: string): Promise<JwtPayload | string>;
40
+ verifyRefreshToken(token: string): Promise<JwtPayload | string>;
41
+ decodeToken(token: string, complete?: boolean): JwtPayload | string | null;
42
+ extractTokenFromHeader(authHeader: string): string | null;
43
+ validateToken(token: string, secret: Secret, options?: TokenValidationOptions): boolean;
44
+ rotateRefreshToken(oldToken: string): Promise<RefreshToken>;
45
+ isTokenExpired(token: string): boolean;
46
+ getTokenExpiration(token: string): Date | null;
47
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });