auth-verify 1.2.5 → 1.2.6
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/index.js +32 -50
- package/package.json +2 -1
- package/src/jwt/index.js +4 -3
- package/tests/jwtmanager.multitab.test.js +34 -0
package/index.js
CHANGED
|
@@ -1,51 +1,43 @@
|
|
|
1
1
|
const JWTManager = require("./src/jwt");
|
|
2
2
|
const OTPManager = require("./src/otp");
|
|
3
3
|
const SessionManager = require("./src/session");
|
|
4
|
-
const OAuthManager = require("./src/oauth")
|
|
4
|
+
const OAuthManager = require("./src/oauth");
|
|
5
5
|
|
|
6
6
|
class AuthVerify {
|
|
7
7
|
constructor(options = {}) {
|
|
8
8
|
let {
|
|
9
|
-
jwtSecret,
|
|
9
|
+
jwtSecret = "jwt_secret",
|
|
10
|
+
cookieName = "jwt_token",
|
|
10
11
|
otpExpiry = 300,
|
|
11
12
|
storeTokens = "none",
|
|
12
13
|
otpHash = "sha256",
|
|
13
14
|
redisUrl,
|
|
14
15
|
} = options;
|
|
15
16
|
|
|
16
|
-
//
|
|
17
|
-
|
|
17
|
+
// ✅ Ensure cookieName and secret always exist
|
|
18
|
+
this.cookieName = cookieName;
|
|
19
|
+
this.jwtSecret = jwtSecret;
|
|
20
|
+
|
|
21
|
+
// ✅ Pass both into JWTManager
|
|
22
|
+
this.jwt = new JWTManager(jwtSecret, {
|
|
23
|
+
storeTokens,
|
|
24
|
+
cookieName,
|
|
25
|
+
});
|
|
18
26
|
|
|
19
|
-
this.senderName;
|
|
20
|
-
this.jwt = new JWTManager(jwtSecret, { storeTokens });
|
|
21
27
|
this.otp = new OTPManager({
|
|
22
28
|
storeTokens,
|
|
23
29
|
otpExpiry,
|
|
24
30
|
otpHash,
|
|
25
31
|
redisUrl,
|
|
26
32
|
});
|
|
33
|
+
|
|
27
34
|
this.session = new SessionManager({ storeTokens, redisUrl });
|
|
35
|
+
this.oauth = new OAuthManager();
|
|
28
36
|
|
|
29
37
|
this.senders = new Map();
|
|
30
|
-
// this.register = {
|
|
31
|
-
// sender: (name, fn)=>{
|
|
32
|
-
// if (!name || typeof fn !== "function") {
|
|
33
|
-
// throw new Error("Sender registration requires a name and a function");
|
|
34
|
-
// }else{
|
|
35
|
-
// try{
|
|
36
|
-
// this.senders.set(name, fn);
|
|
37
|
-
// }catch(err){
|
|
38
|
-
// throw new Error(err);
|
|
39
|
-
// }
|
|
40
|
-
// }
|
|
41
|
-
// }
|
|
42
|
-
// }
|
|
43
|
-
// ✅ No getters — directly reference otp.dev (it's a plain object)
|
|
44
|
-
|
|
45
|
-
this.oauth = new OAuthManager();
|
|
46
38
|
}
|
|
47
|
-
|
|
48
|
-
// Session helpers
|
|
39
|
+
|
|
40
|
+
// --- Session helpers ---
|
|
49
41
|
async createSession(userId, options = {}) {
|
|
50
42
|
return this.session.create(userId, options);
|
|
51
43
|
}
|
|
@@ -58,33 +50,23 @@ class AuthVerify {
|
|
|
58
50
|
return this.session.destroy(sessionId);
|
|
59
51
|
}
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
// --- Sender registration ---
|
|
54
|
+
register = {
|
|
55
|
+
sender: (name, fn) => {
|
|
56
|
+
if (!name || typeof fn !== "function") {
|
|
57
|
+
throw new Error("Sender registration requires a name and a function");
|
|
58
|
+
}
|
|
59
|
+
this.senders.set(name, fn);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.senders.set(name, fn);
|
|
73
|
-
// console.log(`✅ Sender registered: ${name}`);
|
|
74
|
-
}
|
|
63
|
+
use(name) {
|
|
64
|
+
const senderFn = this.senders.get(name);
|
|
65
|
+
if (!senderFn) throw new Error(`Sender "${name}" not found`);
|
|
66
|
+
return {
|
|
67
|
+
send: async (options) => await senderFn(options),
|
|
75
68
|
};
|
|
76
|
-
|
|
77
|
-
// use a sender by name
|
|
78
|
-
use(name) {
|
|
79
|
-
const senderFn = this.senders.get(name);
|
|
80
|
-
if (!senderFn) throw new Error(`Sender "${name}" not found`);
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
send: async (options) => {
|
|
84
|
-
return await senderFn(options); // call user function
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
69
|
+
}
|
|
88
70
|
}
|
|
89
71
|
|
|
90
|
-
module.exports = AuthVerify;
|
|
72
|
+
module.exports = AuthVerify;
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"auth-verify": "^1.2.4",
|
|
4
4
|
"axios": "^1.12.2",
|
|
5
5
|
"crypto": "^1.0.1",
|
|
6
|
+
"express": "^5.1.0",
|
|
6
7
|
"ioredis": "^5.8.1",
|
|
7
8
|
"jsonwebtoken": "^9.0.2",
|
|
8
9
|
"node-telegram-bot-api": "^0.66.0",
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
"uuid": "^9.0.1"
|
|
13
14
|
},
|
|
14
15
|
"name": "auth-verify",
|
|
15
|
-
"version": "1.2.
|
|
16
|
+
"version": "1.2.6",
|
|
16
17
|
"description": "A simple Node.js library for sending and verifying OTP via email, SMS and Telegram bot",
|
|
17
18
|
"main": "index.js",
|
|
18
19
|
"scripts": {
|
package/src/jwt/index.js
CHANGED
|
@@ -249,7 +249,8 @@ const CookieManager = require("./cookie");
|
|
|
249
249
|
class JWTManager {
|
|
250
250
|
constructor(secret, options = {}) {
|
|
251
251
|
// if (!secret) throw new Error("JWT secret is required");
|
|
252
|
-
this.secret = secret || "
|
|
252
|
+
this.secret = secret || "jwt_secret";
|
|
253
|
+
this.cookieName = options.cookieName || "jwt_token";
|
|
253
254
|
this.storeType = options.storeTokens || "none";
|
|
254
255
|
|
|
255
256
|
if (this.storeType === "memory") {
|
|
@@ -307,7 +308,7 @@ class JWTManager {
|
|
|
307
308
|
|
|
308
309
|
// Auto cookie support
|
|
309
310
|
if (options.res) {
|
|
310
|
-
CookieManager.setCookie(options.res, this.
|
|
311
|
+
CookieManager.setCookie(options.res, this.cookieName, token, {
|
|
311
312
|
httpOnly: true,
|
|
312
313
|
secure: options.secure ?? true,
|
|
313
314
|
sameSite: "Strict",
|
|
@@ -325,7 +326,7 @@ class JWTManager {
|
|
|
325
326
|
// If request object provided
|
|
326
327
|
if (typeof input === "object" && input.headers) {
|
|
327
328
|
token =
|
|
328
|
-
CookieManager.getCookie(input, this.
|
|
329
|
+
CookieManager.getCookie(input, this.cookieName) ||
|
|
329
330
|
(input.headers.authorization
|
|
330
331
|
? input.headers.authorization.replace("Bearer ", "")
|
|
331
332
|
: null);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const request = require("supertest");
|
|
3
|
+
const AuthVerify = require("../index");
|
|
4
|
+
|
|
5
|
+
describe("JWT multi-tab verification", () => {
|
|
6
|
+
const auth = new AuthVerify({ jwtSecret: "test_secret", storeTokens: "memory" });
|
|
7
|
+
const app = express();
|
|
8
|
+
|
|
9
|
+
app.get("/login", async (req, res) => {
|
|
10
|
+
const token = await auth.jwt.sign({ userId: 1 }, "5s", { res });
|
|
11
|
+
res.json({ token });
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
app.get("/protected", async (req, res) => {
|
|
15
|
+
try {
|
|
16
|
+
const data = await auth.jwt.verify(req);
|
|
17
|
+
res.json({ valid: true, data });
|
|
18
|
+
} catch (err) {
|
|
19
|
+
res.status(401).json({ valid: false, error: err.message });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("should work in second tab (same cookie)", async () => {
|
|
24
|
+
const loginRes = await request(app).get("/login");
|
|
25
|
+
const cookie = loginRes.headers["set-cookie"][0];
|
|
26
|
+
|
|
27
|
+
const protectedRes = await request(app)
|
|
28
|
+
.get("/protected")
|
|
29
|
+
.set("Cookie", cookie);
|
|
30
|
+
|
|
31
|
+
expect(protectedRes.body.valid).toBe(true);
|
|
32
|
+
expect(protectedRes.body.data.userId).toBe(1);
|
|
33
|
+
});
|
|
34
|
+
});
|