auth-verify 1.2.0 → 1.2.2
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/package.json +3 -2
- package/readme.md +29 -4
- package/src/jwt/index.js +1 -0
- package/src/oauth/index.js +60 -0
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"uuid": "^13.0.0"
|
|
13
13
|
},
|
|
14
14
|
"name": "auth-verify",
|
|
15
|
-
"version": "1.2.
|
|
15
|
+
"version": "1.2.2",
|
|
16
16
|
"description": "A simple Node.js library for sending and verifying OTP via email",
|
|
17
17
|
"main": "index.js",
|
|
18
18
|
"scripts": {
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"two-factor",
|
|
38
38
|
"2fa",
|
|
39
39
|
"email",
|
|
40
|
-
"jwt"
|
|
40
|
+
"jwt",
|
|
41
|
+
"oauth"
|
|
41
42
|
],
|
|
42
43
|
"author": "Jahongir Sobirov",
|
|
43
44
|
"license": "MIT",
|
package/readme.md
CHANGED
|
@@ -23,11 +23,11 @@ npm install auth-verify
|
|
|
23
23
|
|
|
24
24
|
## ⚙️ Quick overview
|
|
25
25
|
|
|
26
|
-
- `AuthVerify` (entry): constructs and exposes `.jwt`, `.otp`,
|
|
26
|
+
- `AuthVerify` (entry): constructs and exposes `.jwt`, `.otp`, (optionally) `.session` and `.oauth` managers.
|
|
27
27
|
- `JWTManager`: sign, verify, decode, revoke tokens. Supports `storeTokens: "memory" | "redis" | "none"`.
|
|
28
28
|
- `OTPManager`: generate, store, send, verify, resend OTPs. Supports `storeTokens: "memory" | "redis" | "none"`. Supports email, SMS helper, Telegram bot, and custom dev senders.
|
|
29
29
|
- `SessionManager`: simple session creation/verification/destroy with memory or Redis backend.
|
|
30
|
-
- `OAuthManager`: Handle OAuth 2.0 logins for Google, Facebook, GitHub, X
|
|
30
|
+
- `OAuthManager`: Handle OAuth 2.0 logins for Google, Facebook, GitHub, X and Linkedin
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
## 🚀 Example: Initialize library (CommonJS)
|
|
@@ -50,7 +50,7 @@ const auth = new AuthVerify({
|
|
|
50
50
|
|
|
51
51
|
```js
|
|
52
52
|
// create JWT
|
|
53
|
-
const token = await auth.jwt.sign({ userId: 123 }, '1h'); // expiry string or number (ms)
|
|
53
|
+
const token = await auth.jwt.sign({ userId: 123 }, '1h'); // expiry string or number (ms) (and also you can add '1m' (minute), '5s' (second) and '7d' (day))
|
|
54
54
|
console.log('token', token);
|
|
55
55
|
|
|
56
56
|
// verify
|
|
@@ -186,6 +186,11 @@ try {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// Callback style also supported: auth.otp.verify({check, code}, callback)
|
|
189
|
+
auth.otp.verify({ check: 'user@example.com', code: '123456' }, (err, isValid)=>{
|
|
190
|
+
if(err) console.log(err);
|
|
191
|
+
if(isValid) console.log('Correct code!');
|
|
192
|
+
else console.log('Incorrect code!');
|
|
193
|
+
});
|
|
189
194
|
```
|
|
190
195
|
|
|
191
196
|
### Resend and cooldown / max attempts
|
|
@@ -198,7 +203,7 @@ try {
|
|
|
198
203
|
|
|
199
204
|
---
|
|
200
205
|
## 🌍 OAuth 2.0 Integration (New in v1.2.0)
|
|
201
|
-
`auth.oauth` supports login via Google, Facebook, GitHub,
|
|
206
|
+
`auth.oauth` supports login via Google, Facebook, GitHub, X (Twitter) and Linkedin.
|
|
202
207
|
### Example (Google Login with Express)
|
|
203
208
|
```js
|
|
204
209
|
const express = require('express');
|
|
@@ -272,6 +277,13 @@ const twitter = auth.oauth.x({
|
|
|
272
277
|
redirectUri: "http://localhost:3000/auth/x/callback",
|
|
273
278
|
});
|
|
274
279
|
|
|
280
|
+
// --- Example: Linkedin LOGIN ---
|
|
281
|
+
const linkedin = auth.oauth.linkedin({
|
|
282
|
+
clientId: "YOUR_LINKEDIN_CLIENT_ID",
|
|
283
|
+
clientSecret: "YOUR_LINKEDIN_CLIENT_SECRET",
|
|
284
|
+
redirectUri: "http://localhost:3000/auth/linkedin/callback"
|
|
285
|
+
});
|
|
286
|
+
|
|
275
287
|
|
|
276
288
|
// ===== FACEBOOK ROUTES =====
|
|
277
289
|
app.get("/auth/facebook", (req, res) => facebook.redirect(res));
|
|
@@ -313,6 +325,19 @@ app.get("/auth/x/callback", async (req, res) => {
|
|
|
313
325
|
res.status(400).json({ error: err.message });
|
|
314
326
|
}
|
|
315
327
|
});
|
|
328
|
+
|
|
329
|
+
// ==== LINKEDIN ROUTES ====
|
|
330
|
+
app.get("/auth/linkedin", (req, res) => linkedin.redirect(res));
|
|
331
|
+
|
|
332
|
+
app.get("/auth/linkedin/callback", async (req, res)=>{
|
|
333
|
+
try{
|
|
334
|
+
const { code } = req.query;
|
|
335
|
+
const user = await linkedin.callback(code);
|
|
336
|
+
res.json({ success: true, provider: "x", user });
|
|
337
|
+
}catch(err){
|
|
338
|
+
res.status(400).json({ error: err.message });
|
|
339
|
+
}
|
|
340
|
+
});
|
|
316
341
|
|
|
317
342
|
|
|
318
343
|
app.listen(PORT, () => console.log(`🚀 Server running at http://localhost:${PORT}`));
|
package/src/jwt/index.js
CHANGED
|
@@ -265,6 +265,7 @@ class JWTManager {
|
|
|
265
265
|
if (typeof expiry === "number") return expiry;
|
|
266
266
|
if (typeof expiry !== "string") return 3600000; // default 1h
|
|
267
267
|
const num = parseInt(expiry);
|
|
268
|
+
if (expiry.endsWith("d")) return num * 3600000 * 24;
|
|
268
269
|
if (expiry.endsWith("h")) return num * 3600000;
|
|
269
270
|
if (expiry.endsWith("m")) return num * 60000;
|
|
270
271
|
if (expiry.endsWith("s")) return num * 1000;
|
package/src/oauth/index.js
CHANGED
|
@@ -175,6 +175,66 @@ class OAuthManager {
|
|
|
175
175
|
},
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
|
+
|
|
179
|
+
// --- LINKEDIN LOGIN ---
|
|
180
|
+
linkedin({ clientId, clientSecret, redirectUri }) {
|
|
181
|
+
return {
|
|
182
|
+
// Step 1: Redirect user to LinkedIn's authorization page
|
|
183
|
+
redirect(res) {
|
|
184
|
+
const linkedinURL =
|
|
185
|
+
"https://www.linkedin.com/oauth/v2/authorization?" +
|
|
186
|
+
new URLSearchParams({
|
|
187
|
+
response_type: "code",
|
|
188
|
+
client_id: clientId,
|
|
189
|
+
redirect_uri: redirectUri,
|
|
190
|
+
scope: "r_liteprofile r_emailaddress",
|
|
191
|
+
state: "secure123", // optional: you can randomize this
|
|
192
|
+
});
|
|
193
|
+
res.redirect(linkedinURL);
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
// Step 2: Handle callback, exchange code for token, then get user data
|
|
197
|
+
async callback(code) {
|
|
198
|
+
// Exchange authorization code for access token
|
|
199
|
+
const tokenRes = await fetch("https://www.linkedin.com/oauth/v2/accessToken", {
|
|
200
|
+
method: "POST",
|
|
201
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
202
|
+
body: new URLSearchParams({
|
|
203
|
+
grant_type: "authorization_code",
|
|
204
|
+
code,
|
|
205
|
+
redirect_uri: redirectUri,
|
|
206
|
+
client_id: clientId,
|
|
207
|
+
client_secret: clientSecret,
|
|
208
|
+
}),
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const tokenData = await tokenRes.json();
|
|
212
|
+
if (tokenData.error)
|
|
213
|
+
throw new Error("OAuth Error: " + tokenData.error_description);
|
|
214
|
+
|
|
215
|
+
// Fetch basic profile info
|
|
216
|
+
const profileRes = await fetch("https://api.linkedin.com/v2/me", {
|
|
217
|
+
headers: { Authorization: `Bearer ${tokenData.access_token}` },
|
|
218
|
+
});
|
|
219
|
+
const profile = await profileRes.json();
|
|
220
|
+
|
|
221
|
+
// Fetch user's primary email
|
|
222
|
+
const emailRes = await fetch(
|
|
223
|
+
"https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))",
|
|
224
|
+
{ headers: { Authorization: `Bearer ${tokenData.access_token}` } }
|
|
225
|
+
);
|
|
226
|
+
const emailData = await emailRes.json();
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
id: profile.id,
|
|
230
|
+
name: profile.localizedFirstName + " " + profile.localizedLastName,
|
|
231
|
+
email: emailData.elements?.[0]?.["handle~"]?.emailAddress || null,
|
|
232
|
+
access_token: tokenData.access_token,
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
178
238
|
}
|
|
179
239
|
|
|
180
240
|
module.exports = OAuthManager;
|