auth-verify 1.13.6 → 1.14.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  const JWTManager = require("./src/jwt");
2
2
  const OTPManager = require("./src/otp");
3
- const SessionManager = require("./src/session");
3
+ // const SessionManager = require("./src/session");
4
4
  const OAuthManager = require("./src/oauth");
5
5
  const TOTPManager = require("./src/totp");
6
6
  const PasskeyManager = require("./src/passkey");
@@ -51,7 +51,7 @@ class AuthVerify {
51
51
  redisUrl,
52
52
  });
53
53
 
54
- this.session = new SessionManager({ storeTokens, redisUrl });
54
+ // this.session = new SessionManager({ storeTokens, redisUrl });
55
55
  this.oauth = new OAuthManager();
56
56
  this.totp = new TOTPManager(totp);
57
57
 
@@ -63,17 +63,17 @@ class AuthVerify {
63
63
  }
64
64
 
65
65
  // --- Session helpers ---
66
- async createSession(userId, options = {}) {
67
- return this.session.create(userId, options);
68
- }
66
+ // async createSession(userId, options = {}) {
67
+ // return this.session.create(userId, options);
68
+ // }
69
69
 
70
- async verifySession(sessionId) {
71
- return this.session.verify(sessionId);
72
- }
70
+ // async verifySession(sessionId) {
71
+ // return this.session.verify(sessionId);
72
+ // }
73
73
 
74
- async destroySession(sessionId) {
75
- return this.session.destroy(sessionId);
76
- }
74
+ // async destroySession(sessionId) {
75
+ // return this.session.destroy(sessionId);
76
+ // }
77
77
 
78
78
  // --- Passkey helpers ---
79
79
  async registerPasskey(user) {
package/package.json CHANGED
@@ -15,11 +15,10 @@
15
15
  "nodemailer": "^7.0.6",
16
16
  "path": "^0.12.7",
17
17
  "qrcode": "^1.5.4",
18
- "resend": "^6.9.1",
19
- "uuid": "^9.0.1"
18
+ "resend": "^6.9.1"
20
19
  },
21
20
  "name": "auth-verify",
22
- "version": "1.13.6",
21
+ "version": "1.14.1",
23
22
  "description": "A simple Node.js library for sending and verifying OTP via email, SMS and Telegram bot. And generating TOTP codes and QR codes. And handling JWT with Cookies. And also handling passwordless logins with passkeys/webauth. And handling magiclink passwordless logins",
24
23
  "main": "index.js",
25
24
  "scripts": {
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # auth-verify
2
2
 
3
- **AuthVerify** is a modular authentication library for Node.js, providing JWT, OTP, TOTP, Passkeys (WebAuthn), Magic Links, Sessions, and OAuth helpers. You can easily register custom senders for OTPs or notifications. Auth-verify now supports **REST API** for generating, sending OTP with email/SMS and verifying it.
3
+ **AuthVerify** is a modular authentication library for Node.js, providing JWT, OTP, TOTP, Passkeys (WebAuthn), Magic Links, and OAuth helpers. You can easily register custom senders for OTPs or notifications. Auth-verify now supports **REST API** for generating, sending OTP with email/SMS and verifying it.
4
4
  - [Installation](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-installation)
5
5
  - [Initialization](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-example-initialize-library-commonjs)
6
6
  - [JWT](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-jwt-usage)
@@ -11,7 +11,6 @@
11
11
  - [OAuth](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-oauth-manager--auth-verify)
12
12
  - [Magic Links](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-magiclink-passwordless-login-v180)
13
13
  - [Custom Senders](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#developer-extensibility-custom-senders)
14
- - [Session Management](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-sessionmanager-api-documentation---auth-verify)
15
14
  - [Crypto hashing](https://github.com/Jahongir2007/auth-verify/blob/main/docs/docs.md#-cryptomanager-api-guide)
16
15
  - [Auth-verify REST API](https://auth-verify-sy2y.onrender.com/)
17
16
  ---
@@ -30,11 +29,10 @@ npm install auth-verify
30
29
 
31
30
  ## ⚙️ Quick overview
32
31
 
33
- - `AuthVerify` (entry): constructs and exposes `.jwt`, `.otp`, (optionally) `.session`, `.totp` and `.oauth` managers.
32
+ - `AuthVerify` (entry): constructs and exposes `.jwt`, `.otp`, `.totp` and `.oauth` managers.
34
33
  - `JWTManager`: sign, verify, decode, revoke tokens. Supports `storeTokens: "memory" | "redis" | "none"` and middleware with custom cookie, header, and token extraction.
35
34
  - `OTPManager`: generate, store, send, verify, resend OTPs. Supports `storeTokens: "memory" | "redis" | "none"`. Supports email, SMS helper, Telegram bot, and custom dev senders.
36
35
  - `TOTPManager`: generate, verify uri, codes and QR codes.
37
- - `SessionManager`: simple session creation/verification/destroy with memory or Redis backend.
38
36
  - `OAuthManager`: Handle OAuth 2.0 logins for 20+ providers.
39
37
  - `PasskeyManager`: Handle passwordless login and registration using WebAuthn/passkey.
40
38
  - `MagicLinkManager`: Handle passwordless login with magic link generation and verification.
@@ -1447,7 +1445,22 @@ await auth.magic.sender({
1447
1445
  pass: 'your_smtp_password'
1448
1446
  });
1449
1447
  ```
1450
- > ✅ Both Gmail and any SMTP provider are supported.
1448
+
1449
+ #### API services Example
1450
+ ```js
1451
+ auth.magic.sender({
1452
+ service: 'api',
1453
+ apiService: 'resend', // 'mailgun', 'sendgrid'
1454
+ sender: 'noreply@yourdomain.com',
1455
+ apiKey: 'YOUR_API_KEY'
1456
+ })
1457
+ ```
1458
+ > For `"mailgun"` you should also add also your domain
1459
+ > ```js
1460
+ > domain: "your-domain.com"
1461
+ >```
1462
+
1463
+ > ✅ Gmail, any SMTP provider and API based email services are supported.
1451
1464
  > Use app passwords or tokens instead of your real password!
1452
1465
 
1453
1466
  ### 📩 Send Magic Link
@@ -1518,7 +1531,7 @@ auth.magic.send('user@example.com', (err) => {
1518
1531
  ```js
1519
1532
  const express = require('express');
1520
1533
  const bodyParser = require('body-parser');
1521
- const { AuthVerify } = require('auth-verify');
1534
+ const AuthVerify = require('auth-verify');
1522
1535
 
1523
1536
  const app = express();
1524
1537
  app.use(bodyParser.json());
@@ -1602,79 +1615,6 @@ When a custom sender is registered, `auth.otp.message()` will first attempt the
1602
1615
 
1603
1616
  ---
1604
1617
 
1605
- ## 📝 SessionManager API Documentation - `auth-verify`
1606
- The session manager of `auth-verify` provides a simple way to **create**, **verify**, and **destroy user sessions** in either **memory** or **Redis** storage.
1607
-
1608
- ### Import
1609
- ```js
1610
- const AuthVerify = require('auth-verify');
1611
- const auth = new AuthVerify({ storeTokens: 'redis', redisUrl: "redis://localhost:6379" });
1612
- ```
1613
- ##### Options:
1614
- | Option | Type | Default | Description |
1615
- | ------------- | ------ | -------------------------- | --------------------------------------------------------- |
1616
- | `storeTokens` | string | `'memory'` | Storage type for sessions: `'memory'` or `'redis'` |
1617
- | `redisUrl` | string | `"redis://localhost:6379"` | Redis connection URL (required if `storeTokens: 'redis'`) |
1618
-
1619
- ### Methods
1620
- #### 1️⃣ `create(userId, options)`
1621
- Create a new session for a user.
1622
- **Parameters:**
1623
- | Name | Type | Required | Description | |
1624
- | --------- | ------ | -------- | --------------------------------------- | --------- |
1625
- | `userId` | string | ✅ | Unique ID of the user | |
1626
- | `options` | object | ❌ | Optional settings: `{ expiresIn: number | string }` |
1627
-
1628
- `expiresIn` formats:
1629
- - Number → seconds
1630
- - String → `"30s"`, `"5m"`, `"2h"`, `"1d"`
1631
- ##### **Returns:**
1632
- `Promise<string>` → The session ID (UUID)
1633
- ##### **Example:**
1634
- ```js
1635
- // Memory storage
1636
- const auth = new AuthVerify({ storeTokens: 'memory' });
1637
- const sessionId = await auth.session.create("user123", { expiresIn: "2h" });
1638
- console.log(sessionId); // "550e8400-e29b-41d4-a716-446655440000"
1639
- ```
1640
- #### 2️⃣ `verify(sessionId)`
1641
- Verify if a session is valid.
1642
- ##### **Parameters:**
1643
- | Name | Type | Required | Description |
1644
- | ----------- | ------ | -------- | ------------------------ |
1645
- | `sessionId` | string | ✅ | The session ID to verify |
1646
- ##### Returns:
1647
- `Promise<string>` → Returns the `userId` if session is valid
1648
- ##### Throws:
1649
- - `"Session not found or expired"`
1650
- - `"Session expired"`
1651
- ##### Example:
1652
- ```js
1653
- const userId = await auth.session.verify(sessionId);
1654
- console.log(userId); // "user123"
1655
- ```
1656
- #### 3️⃣ `destroy(sessionId)`
1657
- Invalidate (destroy) a session manually.
1658
- ##### Parameters:
1659
- | Name | Type | Required | Description |
1660
- | ----------- | ------ | -------- | ------------------------- |
1661
- | `sessionId` | string | ✅ | The session ID to destroy |
1662
- ##### Returns:
1663
- `Promise<void>`
1664
- ##### Example:
1665
- ```js
1666
- await auth.session.destroy(sessionId);
1667
- console.log("Session destroyed");
1668
- ```
1669
-
1670
- ### Notes & Best Practices
1671
- - **Memory** storage is fast but not persistent across server restarts. Use **Redis** in production.
1672
- - Always verify session before allowing access to protected routes.
1673
- - Optionally, combine with JWT or OTP for multi-layered authentication.
1674
- - Use `expiresIn` wisely — shorter times improve security but may require more frequent re-login.
1675
-
1676
- ---
1677
-
1678
1618
  ## 🔐 CryptoManager API Guide
1679
1619
  It supports both **PBKDF2** and **scrypt** algorithms for password or data hashing.
1680
1620
 
@@ -1829,7 +1769,6 @@ auth-verify/
1829
1769
  │ ├─ totp/
1830
1770
  | | ├─ index.js
1831
1771
  | | ├─ base32.js
1832
- │ ├─ /session/index.js
1833
1772
  | ├─ /oauth/index.js
1834
1773
  │ └─ helpers/helper.js
1835
1774
  ├─ rest-api/
@@ -1,6 +1,10 @@
1
1
  const jwt = require('jsonwebtoken');
2
2
  const nodemailer = require('nodemailer');
3
3
  const Redis = require('ioredis');
4
+ const sgMail = require('@sendgrid/mail');
5
+ const formData = require('form-data');
6
+ const Mailgun = require('mailgun.js');
7
+ const { Resend } = require('resend');
4
8
 
5
9
  class MagicLinkManager {
6
10
  constructor(config = {}) {
@@ -40,10 +44,114 @@ class MagicLinkManager {
40
44
  ? mailOption.html.replace(/{{\s*link\s*}}/gi, link)
41
45
  : `<p>Click to login: <a href="${link}">${link}</a></p>`;
42
46
 
47
+ if(this.senderConfig.apiService === "sendgrid" && this.senderConfig.service === 'api'){
48
+ sgMail.setApiKey(this.senderConfig.apiKey)
49
+
50
+ const apiMail = {
51
+ to: email,
52
+ from: this.senderConfig.sender,
53
+ subject: mailOption.subject || 'Your Magic Login Link ✨',
54
+ html: letterHtml
55
+ };
56
+
57
+ try{
58
+ const info = await sgMail.send(apiMail)
59
+ this.recieverConfig = mailOption
60
+ // return info
61
+
62
+ let timeVal = 5 * 60 * 1000;
63
+ if (typeof this.expiresIn === 'string') {
64
+ if (this.expiresIn.endsWith('m')) timeVal = parseInt(this.expiresIn) * 60 * 1000;
65
+ else if (this.expiresIn.endsWith('s')) timeVal = parseInt(this.expiresIn) * 1000;
66
+ } else if (typeof this.expiresIn === 'number') timeVal = this.expiresIn * 1000;
67
+
68
+ if (this.storeType === 'memory') {
69
+ this.tokenStore.set(email, token);
70
+ setTimeout(() => this.tokenStore.delete(email), timeVal);
71
+ } else if (this.storeType === 'redis') {
72
+ await this.redis.set(email, token, 'PX', timeVal);
73
+ }
74
+
75
+ return { token, link };
76
+ }catch(err){
77
+ throw new Error(err.response?.body || err.message)
78
+ }
79
+ }else if(this.senderConfig.apiService === "mailgun" && this.senderConfig.service === "api"){
80
+ const mg = new Mailgun(formData).client({
81
+ username: 'api',
82
+ key: this.senderConfig.apiKey,
83
+ });
84
+
85
+ const apiMail = {
86
+ to: email,
87
+ from: this.senderConfig.sender,
88
+ subject: mailOption.subject || 'Your Magic Login Link ✨',
89
+ html: letterHtml
90
+ };
91
+
92
+ try{
93
+ const info = await mg.messages.create(this.senderConfig.domain, apiMail)
94
+ this.recieverConfig = mailOption
95
+ // return info
96
+
97
+ let timeVal = 5 * 60 * 1000;
98
+ if (typeof this.expiresIn === 'string') {
99
+ if (this.expiresIn.endsWith('m')) timeVal = parseInt(this.expiresIn) * 60 * 1000;
100
+ else if (this.expiresIn.endsWith('s')) timeVal = parseInt(this.expiresIn) * 1000;
101
+ } else if (typeof this.expiresIn === 'number') timeVal = this.expiresIn * 1000;
102
+
103
+ if (this.storeType === 'memory') {
104
+ this.tokenStore.set(email, token);
105
+ setTimeout(() => this.tokenStore.delete(email), timeVal);
106
+ } else if (this.storeType === 'redis') {
107
+ await this.redis.set(email, token, 'PX', timeVal);
108
+ }
109
+
110
+ return { token, link };
111
+ }catch(err){
112
+ throw new Error(err.response?.body || err.message)
113
+ }
114
+
115
+ }else if(this.senderConfig.apiService === "resend" && this.senderConfig.service === 'api'){
116
+ const resend = new Resend(this.senderConfig.apiKey);
117
+
118
+ const apiMail = {
119
+ to: email,
120
+ from: this.senderConfig.sender,
121
+ subject: mailOption.subject || 'Your Magic Login Link ✨',
122
+ html: letterHtml
123
+ };
124
+
125
+ try {
126
+ const info = await resend.emails.send(apiMail);
127
+ this.recieverConfig = mailOption;
128
+ // return info;
129
+
130
+ let timeVal = 5 * 60 * 1000;
131
+ if (typeof this.expiresIn === 'string') {
132
+ if (this.expiresIn.endsWith('m')) timeVal = parseInt(this.expiresIn) * 60 * 1000;
133
+ else if (this.expiresIn.endsWith('s')) timeVal = parseInt(this.expiresIn) * 1000;
134
+ } else if (typeof this.expiresIn === 'number') timeVal = this.expiresIn * 1000;
135
+
136
+ if (this.storeType === 'memory') {
137
+ this.tokenStore.set(email, token);
138
+ setTimeout(() => this.tokenStore.delete(email), timeVal);
139
+ } else if (this.storeType === 'redis') {
140
+ await this.redis.set(email, token, 'PX', timeVal);
141
+ }
142
+
143
+ return { token, link };
144
+ } catch(err) {
145
+ throw new Error(err.response?.body || err.message);
146
+ }
147
+ }
148
+
43
149
  let transporter;
44
150
  if (this.senderConfig.service === 'gmail') {
45
151
  transporter = nodemailer.createTransport({
46
- service: 'gmail',
152
+ host: 'smtp.gmail.com',
153
+ port: this.senderConfig.port || 587,
154
+ secure: this.senderConfig.secure || false,
47
155
  auth: { user: this.senderConfig.sender, pass: this.senderConfig.pass },
48
156
  pool: true,
49
157
  maxConnections: 3,
@@ -92,7 +200,9 @@ class MagicLinkManager {
92
200
  const verifyProcess = async () => {
93
201
  try {
94
202
  const decoded = jwt.verify(token, this.secret);
95
- // console.log(decoded);
203
+ // console.log("Decoded",decoded);
204
+ // console.log("Token", token);
205
+ // console.log("Secret", this.secret);
96
206
  const email = decoded.email;
97
207
 
98
208
  let stored;
@@ -107,7 +217,7 @@ class MagicLinkManager {
107
217
 
108
218
  return { success: true, user: decoded };
109
219
  } catch (err) {
110
- throw new Error('Invalid or expired magic link');
220
+ throw new Error(`Invalid or expired magic link: ${err}`);
111
221
  }
112
222
  };
113
223
 
@@ -117,4 +227,4 @@ class MagicLinkManager {
117
227
  }
118
228
  }
119
229
 
120
- module.exports = MagicLinkManager;
230
+ module.exports = MagicLinkManager;
@@ -19,6 +19,8 @@ class OAuthManager {
19
19
  access_type: "offline",
20
20
  prompt: "consent",
21
21
  });
22
+
23
+ // console.log(googleURL);
22
24
  res.redirect(googleURL);
23
25
  },
24
26
 
package/src/otp/index.js CHANGED
@@ -6,7 +6,7 @@ const sgMail = require('@sendgrid/mail')
6
6
  const formData = require('form-data');
7
7
  const Mailgun = require('mailgun.js');
8
8
  const { Resend } = require('resend');
9
- const mail = require('@sendgrid/mail');
9
+ // const mail = require('@sendgrid/mail');
10
10
 
11
11
  class OTPManager {
12
12
  constructor(otpOptions = {}){
@@ -1,83 +0,0 @@
1
- const Redis = require("ioredis");
2
- const { v4: uuidv4 } = require("uuid");
3
-
4
- class SessionManager {
5
- constructor(options = {}) {
6
- this.storeType = options.storeTokens || 'memory'; // 'memory' or 'redis'
7
-
8
- if (this.storeType === 'memory') {
9
- this.sessions = new Map();
10
- } else if (this.storeType === 'redis') {
11
- this.redis = new Redis(options.redisUrl || "redis://localhost:6379");
12
- }else if(this.storeType === 'none'){
13
- return;
14
- } else {
15
- throw new Error("{storeTokens} should be 'memory' or 'redis'");
16
- }
17
- }
18
-
19
- // Create a session
20
- async create(userId, options = {}) {
21
- const sessionId = uuidv4();
22
- const expiresIn = options.expiresIn || 3600; // default 1 hour
23
- if (typeof expiresIn === "string") {
24
- const timeValue = parseInt(expiresIn);
25
- if (expiresIn.endsWith("s")) expiresIn = timeValue;
26
- else if (expiresIn.endsWith("m")) expiresIn = timeValue * 60;
27
- else if (expiresIn.endsWith("h")) expiresIn = timeValue * 60 * 60;
28
- else if (expiresIn.endsWith("d")) expiresIn = timeValue * 60 * 60 * 24;
29
- else throw new Error("Invalid expiresIn format (use s, m, h, d)");
30
- }
31
- const now = Date.now();
32
-
33
- const sessionData = {
34
- userId,
35
- createdAt: now,
36
- expiresAt: now + expiresIn * 1000
37
- };
38
-
39
- if (this.storeType === 'memory') {
40
- this.sessions.set(sessionId, sessionData);
41
- } else if (this.storeType === 'redis') {
42
- await this.redis.set(
43
- sessionId,
44
- JSON.stringify(sessionData),
45
- "EX",
46
- expiresIn
47
- );
48
- }
49
-
50
- return sessionId;
51
- }
52
-
53
- // Verify a session
54
- async verify(sessionId) {
55
- let data;
56
- if (this.storeType === 'memory') {
57
- data = this.sessions.get(sessionId);
58
- } else if (this.storeType === 'redis') {
59
- const raw = await this.redis.get(sessionId);
60
- data = raw ? JSON.parse(raw) : null;
61
- }
62
-
63
- if (!data) throw new Error("Session not found or expired");
64
-
65
- if (Date.now() > data.expiresAt) {
66
- await this.destroy(sessionId);
67
- throw new Error("Session expired");
68
- }
69
-
70
- return data.userId;
71
- }
72
-
73
- // Destroy a session
74
- async destroy(sessionId) {
75
- if (this.storeType === 'memory') {
76
- this.sessions.delete(sessionId);
77
- } else if (this.storeType === 'redis') {
78
- await this.redis.del(sessionId);
79
- }
80
- }
81
- }
82
-
83
- module.exports = SessionManager;