auth-verify 0.0.2 → 1.1.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.
@@ -0,0 +1,284 @@
1
+ const crypto = require('crypto');
2
+ const nodemailer = require("nodemailer");
3
+ const axios = require('axios');
4
+
5
+ /**
6
+ * Convert time strings like "1h", "30m", "10s" to milliseconds
7
+ */
8
+ function parseTime(str) {
9
+ if (typeof str === 'number') return str; // already ms
10
+ if (typeof str !== 'string') return 0;
11
+
12
+ const num = parseInt(str);
13
+ if (str.endsWith('h')) return num * 60 * 60 * 1000;
14
+ if (str.endsWith('m')) return num * 60 * 1000;
15
+ if (str.endsWith('s')) return num * 1000;
16
+ return num;
17
+ }
18
+
19
+ /**
20
+ * Generate a random numeric OTP of given length
21
+ */
22
+ function generateSecureOTP(length = 6, hash = 'sha256') {
23
+ // Create random bytes
24
+ const randomBytes = crypto.randomBytes(32);
25
+ // Hash the bytes
26
+ const hashed = crypto.createHash(hash).update(randomBytes).digest('hex');
27
+
28
+ // Convert to numeric OTP
29
+ let otp = '';
30
+ for (let i = 0; i < hashed.length && otp.length < length; i++) {
31
+ const char = hashed[i];
32
+ if (!isNaN(char)) otp += char;
33
+ }
34
+
35
+ // If not enough digits, recursively generate more
36
+ if (otp.length < length) return generateSecureOTP(length, hash);
37
+ return otp.slice(0, length);
38
+ }
39
+
40
+ function otpSendingProcessByEmail({senderService, senderEmail, senderPass, senderHost, senderPort, senderSecure, receiverEmail, senderText, senderSubject, senderHtml}){
41
+ if(senderService == 'gmail'){
42
+ const transporter = nodemailer.createTransport({
43
+ service: senderService,
44
+ auth: {
45
+ user: senderEmail,
46
+ pass: senderPass, // not your normal password
47
+ },
48
+ });
49
+
50
+ if(senderText && !senderHtml){
51
+ transporter.sendMail({
52
+ from: senderEmail,
53
+ to: receiverEmail,
54
+ subject: senderSubject,
55
+ text: senderText,
56
+ // html: senderHtml
57
+ }, (err, info) => {
58
+ if (err) return console.error("❌ Failed:", err);
59
+ // console.log("✅ Email sent:", info.response);
60
+ });
61
+ }else if (senderHtml && !senderText){
62
+ transporter.sendMail({
63
+ from: senderEmail,
64
+ to: receiverEmail,
65
+ subject: senderSubject,
66
+ // text: senderText,
67
+ html: senderHtml
68
+ }, (err, info) => {
69
+ if (err) return console.error("❌ Failed:", err);
70
+ // console.log("✅ Email sent:", info.response);
71
+ });
72
+ }
73
+ }else{
74
+ const transporter = nodemailer.createTransport({
75
+ host: senderHost,
76
+ port: senderPort,
77
+ secure: senderSecure, // true for 465, false for others
78
+ auth: {
79
+ user: senderEmail,
80
+ pass: senderPass,
81
+ },
82
+ });
83
+
84
+ if(senderText && !senderHtml){
85
+ transporter.sendMail({
86
+ from: senderEmail,
87
+ to: receiverEmail,
88
+ subject: senderSubject,
89
+ text: senderText,
90
+ // html: senderHtml
91
+ }, (err, info) => {
92
+ if (err) return console.error("❌ Failed:", err);
93
+ // console.log("✅ Email sent:", info.response);
94
+ });
95
+ }else if (senderHtml && !senderText){
96
+ transporter.sendMail({
97
+ from: senderEmail,
98
+ to: receiverEmail,
99
+ subject: senderSubject,
100
+ // text: senderText,
101
+ html: senderHtml
102
+ }, (err, info) => {
103
+ if (err) return console.error("❌ Failed:", err);
104
+ // console.log("✅ Email sent:", info.response);
105
+ });
106
+ }
107
+ }
108
+ }
109
+
110
+ async function resendGeneratedOTP({from, to, pass, service, host, secure, port, subject, text, html, code}, callbackData){
111
+ if(callbackData && typeof callbackData == 'function'){
112
+ // const code = generateSecureOTP(data.code.length, this.hashAlgorithm);
113
+ let transporter;
114
+ if (service === 'gmail') {
115
+ transporter = nodemailer.createTransport({
116
+ service: 'gmail',
117
+ auth: { user: from, pass }
118
+ });
119
+ } else if (service === 'smtp') {
120
+ transporter = nodemailer.createTransport({
121
+ host,
122
+ port,
123
+ secure: !!secure,
124
+ auth: { user: from, pass }
125
+ });
126
+ } else {
127
+ throw new Error(`Unsupported email service: ${service}`);
128
+ }
129
+ // prepare mail
130
+ const mail = {
131
+ from,
132
+ to,
133
+ subject: subject || 'Your OTP Code',
134
+ text: text || `Your OTP is ${code}`,
135
+ html: html || `<p>Your OTP is <b>${code}</b></p>`
136
+ };
137
+ transporter.sendMail(mail, (err, info)=>{
138
+ if(err) return callbackData(new Error(err));
139
+ callbackData(null, info);
140
+ });
141
+ }else{
142
+ try{
143
+ let transporter;
144
+ if (service === 'gmail') {
145
+ transporter = nodemailer.createTransport({
146
+ service: 'gmail',
147
+ auth: { user: from, pass }
148
+ });
149
+ } else if (service === 'smtp') {
150
+ transporter = nodemailer.createTransport({
151
+ host,
152
+ port,
153
+ secure: !!secure,
154
+ auth: { user: from, pass: pass }
155
+ });
156
+ } else {
157
+ throw new Error(`Unsupported email service: ${service}`);
158
+ }
159
+ // prepare mail
160
+ const mail = {
161
+ from,
162
+ to,
163
+ subject: subject || 'Your OTP Code',
164
+ text: text || `Your OTP is ${code}`,
165
+ html: html || `<p>Your OTP is <b>${code}</b></p>`
166
+ };
167
+ await transporter.sendMail(mail);
168
+ }catch(err){
169
+ throw new Error(err);
170
+ }
171
+ }
172
+ }
173
+
174
+ async function sendSMS({ provider, apiKey, apiSecret, from, to, text, mock = false }) {
175
+ try {
176
+ // 🧪 For testing only — no real SMS sent
177
+ if (mock) {
178
+ console.log(`📱 [Mock SMS via ${provider}]`);
179
+ console.log(`→ To: ${to}`);
180
+ console.log(`→ Message: ${text}`);
181
+ return { status: "SENT (mock)", to, text };
182
+ }
183
+
184
+ // 🔷 Infobip API
185
+ if (provider === 'infobip') {
186
+ await axios.post(
187
+ 'https://api.infobip.com/sms/2/text/advanced',
188
+ {
189
+ messages: [{ from, destinations: [{ to }], text }],
190
+ },
191
+ {
192
+ headers: {
193
+ Authorization: `App ${apiKey}`,
194
+ 'Content-Type': 'application/json',
195
+ },
196
+ }
197
+ );
198
+ return { status: "SENT", provider: "Infobip", to };
199
+ }
200
+
201
+ // 🟪 Vonage API
202
+ if (provider === 'vonage') {
203
+ await axios.post(
204
+ 'https://rest.nexmo.com/sms/json',
205
+ {
206
+ api_key: apiKey,
207
+ api_secret: apiSecret,
208
+ to,
209
+ from,
210
+ text,
211
+ },
212
+ { headers: { 'Content-Type': 'application/json' } }
213
+ );
214
+ return { status: "SENT", provider: "Vonage", to };
215
+ }
216
+
217
+ // 🟩 Twilio API
218
+ if (provider === 'twilio') {
219
+ await axios.post(
220
+ `https://api.twilio.com/2010-04-01/Accounts/${apiKey}/Messages.json`,
221
+ new URLSearchParams({
222
+ To: to,
223
+ From: from,
224
+ Body: text,
225
+ }),
226
+ {
227
+ auth: {
228
+ username: apiKey,
229
+ password: apiSecret,
230
+ },
231
+ }
232
+ );
233
+ return { status: "SENT", provider: "Twilio", to };
234
+ }
235
+
236
+ throw new Error(`Unsupported SMS provider: ${provider}`);
237
+ } catch (err) {
238
+ console.error("❌ SMS send failed:", err.message);
239
+ throw new Error(err.message);
240
+ }
241
+ }
242
+
243
+ // async function sendOTPwithTelegramBot(otpCode){
244
+ // bot.onText(/\/start/, (msg) => {
245
+ // bot.sendMessage(chatId, "Please share your phone number:", {
246
+ // reply_markup: {
247
+ // keyboard: [
248
+ // [
249
+ // {
250
+ // text: "📞 Share my phone number",
251
+ // request_contact: true, // 🔥 this requests the user's phone
252
+ // },
253
+ // ],
254
+ // ],
255
+ // resize_keyboard: true,
256
+ // one_time_keyboard: true,
257
+ // },
258
+ // });
259
+ // bot.sendMessage(msg.chat.id, `Your Verification code is <b>${otpCode}</b>`, {parse_mode: "HTML"});
260
+ // });
261
+
262
+ // bot.on("contact", (msg) => {
263
+ // const phoneNumber = msg.contact.phone_number;
264
+ // const firstName = msg.contact.first_name;
265
+ // const userId = msg.from.id;
266
+
267
+ // console.log("User shared phone:", phoneNumber);
268
+
269
+ // bot.sendMessage(
270
+ // msg.chat.id,
271
+ // `Thanks, ${firstName}! Your phone number is ${phoneNumber}.`
272
+ // );
273
+
274
+ // // Here you can verify or store it in your database
275
+ // });
276
+ // }
277
+
278
+ module.exports = {
279
+ parseTime,
280
+ generateSecureOTP,
281
+ otpSendingProcessByEmail,
282
+ resendGeneratedOTP,
283
+ sendSMS
284
+ };
@@ -0,0 +1,29 @@
1
+ class CookieManager {
2
+ static setCookie(res, name, value, options = {}) {
3
+ if (!res || typeof res.setHeader !== 'function') {
4
+ throw new Error("Response object must have setHeader() method");
5
+ }
6
+
7
+ let cookieStr = `${name}=${encodeURIComponent(value)}; Path=/;`;
8
+
9
+ if (options.httpOnly) cookieStr += " HttpOnly;";
10
+ if (options.secure) cookieStr += " Secure;";
11
+ if (options.maxAge) cookieStr += ` Max-Age=${Math.floor(options.maxAge / 1000)};`;
12
+ if (options.sameSite) cookieStr += ` SameSite=${options.sameSite};`;
13
+ if (options.domain) cookieStr += ` Domain=${options.domain};`;
14
+
15
+ const existing = res.getHeader('Set-Cookie') || [];
16
+ const newCookies = Array.isArray(existing) ? [...existing, cookieStr] : [cookieStr];
17
+ res.setHeader('Set-Cookie', newCookies);
18
+ }
19
+
20
+ static getCookie(req, name) {
21
+ const cookieHeader = req.headers?.cookie;
22
+ if (!cookieHeader) return null;
23
+ const cookies = cookieHeader.split(';').map(c => c.trim());
24
+ const found = cookies.find(c => c.startsWith(name + '='));
25
+ return found ? decodeURIComponent(found.split('=')[1]) : null;
26
+ }
27
+ }
28
+
29
+ module.exports = CookieManager;