Package Exports
- auth-verify
- auth-verify/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (auth-verify) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
auth-verify
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. - Installation - Initialization - JWT - OTP - TOTP - Passkeys - Auth-Verify client - OAuth - Magic Links - Custom Senders - Session Management - Crypto hashing - Auth-verify REST API
๐งฉ Installation
# from npm (when published)
npm install auth-verify
# or locally during development
# copy the package into your project and `require` it`โ๏ธ Quick overview
AuthVerify(entry): constructs and exposes.jwt,.otp, (optionally).session,.totpand.oauthmanagers.JWTManager: sign, verify, decode, revoke tokens. SupportsstoreTokens: "memory" | "redis" | "none"and middleware with custom cookie, header, and token extraction.OTPManager: generate, store, send, verify, resend OTPs. SupportsstoreTokens: "memory" | "redis" | "none". Supports email, SMS helper, Telegram bot, and custom dev senders.TOTPManager: generate, verify uri, codes and QR codes.SessionManager: simple session creation/verification/destroy with memory or Redis backend.OAuthManager: Handle OAuth 2.0 logins for 20+ providers.PasskeyManager: Handle passwordless login and registration using WebAuthn/passkey.MagicLinkManager: Handle passwordless login with magic link generation and verification.CrpytoManager: Handle hashing passwords or another data with algorithms like:"pbkdf2"and"scrypt"
๐ Example: Initialize library (CommonJS)
const AuthVerify = require('auth-verify');
const auth = new AuthVerify({
jwtSecret: 'your_jwt_secret',
cookieName: 'jwt_token',
otpExpiry: 300, // in seconds
storeTokens: 'memory', // or 'redis'
redisUrl: 'redis://localhost:6379',
totp: { digits: 6, step: 30, alg: 'SHA1' },
rpName: 'myApp',
passExp: '2m',
mlSecret: 'ml_secret',
mlExpiry: '5m',
appUrl: 'https://yourapp.com'
});Options explained:
| Option | Default | Description |
|---|---|---|
jwtSecret |
"jwt_secret" |
Secret key for JWT signing |
cookieName |
"jwt_token" |
Cookie name for JWT storage |
otpExpiry |
300 |
OTP expiration in seconds |
storeTokens |
"memory" |
Token storage type (memory or redis) |
redisUrl |
undefined |
Redis connection string if using Redis |
totp |
{ digits: 6, step: 30, alg: 'SHA1' } |
TOTP configuration |
rpName |
"auth-verify" |
Relying party name for Passkeys |
passExp |
"2m" |
Passkey expiration duration |
mlSecret |
"ml_secret" |
Magic link secret |
mlExpiry |
"5m" |
Magic link expiration duration |
appUrl |
"https://yourapp.com" |
App base URL for Magic Links |
๐ JWT Usage
๐ AuthVerify JWT API Guide
AuthVerify includes a powerful jwt manager that simplifies JSON Web Token (JWT) authentication.
It supports automatic cookie handling, memory or Redis token storage, and an Express middleware for route protection.
โ๏ธ Setup
const AuthVerify = require('auth-verify');
const auth = new AuthVerify({
jwtSecret: 'super_secret_key',
cookieName: 'auth_token',
storeTokens: 'redis', // or 'memory'
redisUrl: 'redis://localhost:6379',
useAlg: 'HS256', // or any supported algorithm
});After initialization, the JWT system is accessible via auth.jwt.
๐งฉ JWT Methods Overview
| Method | Description |
|---|---|
auth.jwt.sign(payload, expiry?, options?) |
Creates a JWT token and optionally sets it in a cookie |
auth.jwt.verify(tokenOrReq) |
Verifies a token or extracts it automatically from a request |
auth.jwt.decode(token) |
Decodes JWT payload without verification |
auth.jwt.revoke(token, revokeTime?) |
Revokes a token immediately or after a timeout |
auth.jwt.isRevoked(token) |
Checks whether a token has been revoked |
auth.jwt.protect(options?) |
Express middleware to protect API routes |
auth.jwt.readCookie(req, name) |
Reads a JWT from cookies manually |
auth.jwt.issue(user) |
Issues an access token and a refresh token |
auth.jwt.refresh(refreshToken) |
Refreshes an access token using a valid refresh token |
๐ช auth.jwt.sign(payload, expiry?, options?)
Signs a new JWT token. Can automatically store it in memory/Redis and set an HTTP-only cookie for browser clients.
const token = await auth.jwt.sign(
{ id: 'user_123', role: 'admin' },
'2h', // expiry time
{ res } // Express res object to auto-set cookie
);Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
payload |
object |
โ | Data to include in the JWT |
expiry |
string | number |
'1h' |
Expiration time (5m, 2h, 1d, etc.) |
options.res |
Response |
โ | Express response object (sets cookie automatically) |
options.secure |
boolean |
true |
If false, cookie is not secure (for localhost testing) |
Returns:
Promise<string> โ The generated JWT token.
โ
auth.jwt.verify(input)
Verifies and decodes a token.
You can pass either a raw JWT token string or an Express request object.
When passing req, the library automatically extracts the token from:
Authorizationheader (Bearer <token>)- Cookies (
auth_tokenby default)
// 1๏ธโฃ Verify a token string
const decoded = await auth.jwt.verify(token);
// 2๏ธโฃ Verify directly from a request
const decoded = await auth.jwt.verify(req);Returns:
Promise<object> โ Decoded payload if valid, throws error if invalid or revoked.
๐ง auth.jwt.decode(token)
Decodes a token without verifying the signature (useful for inspection or debugging).
const data = await auth.jwt.decode(token);Returns: Decoded object or null.
๐งฉ auth.jwt.issue(user)
Issues a new access token and a refresh token for a user.
const { accessToken, refreshToken } = auth.jwt.issue({ id: 'user_123' });- Access token: short-lived, used for authentication.
- Refresh token: long-lived, used to get a new access token without logging in again.
Parameters:
| Name | Type | Description |
|---|---|---|
| user | object | User object with id property |
| Returns: |
{ accessToken: string, refreshToken: string }๐ auth.jwt.refresh(refreshToken)
Refreshes an access token using a valid refresh token.
const newTokens = auth.jwt.refresh(refreshToken);- Validates the refresh token.
- Issues a new access token and refresh token pair.
- Throws an error if the token is invalid or expired.
Parameters:
| Name | Type | Description |
|---|---|---|
| refreshToken | string | A valid refresh token string |
| Returns: |
{ accessToken: string, refreshToken: string }โ auth.jwt.revoke(token, revokeTime?)
Revokes a token immediately or after a specified duration.
await auth.jwt.revoke(token); // revoke now
await auth.jwt.revoke(token, '5m'); // revoke after 5 minutesIf using:
memory: the token is removed from internal store.redis: the key is deleted or set to expire.
๐ซ auth.jwt.isRevoked(token)
Checks if a token is revoked (missing in memory or Redis).
const revoked = await auth.jwt.isRevoked(token);
if (revoked) console.log('Token is no longer valid.');Returns: boolean
๐ก๏ธ auth.jwt.protect(options)
Express middleware for protecting routes that require authentication.
app.get('/dashboard', auth.jwt.protect(), (req, res) => {
res.json({ user: req.user });
});Or with extra security options:
app.get('/admin',
auth.jwt.protect({
requiredRole: 'admin',
attachProperty: 'sessionUser',
onError: (err, req, res) => res.status(403).json({ error: err.message })
}),
(req, res) => {
res.json({ message: `Welcome ${req.sessionUser.id}` });
});Options:
| Name | Type | Default | Description |
|---|---|---|---|
attachProperty |
string |
'user' |
Where decoded data is attached on the request |
requiredRole |
string |
null |
Restricts route access by user role |
cookieName |
string |
Inherited from AuthVerify | Cookie name to extract token |
headerName |
string |
'authorization' |
Header name to look for JWT |
extractor |
function |
โ | Custom token extraction logic |
onError |
function |
โ | Custom error handler (err, req, res) |
๐ช auth.jwt.readCookie(req, name)
Manually extract a JWT from a cookie:
const token = auth.jwt.readCookie(req, 'auth_token');Returns: string | null
๐งฉ Full Example
const express = require('express');
const AuthVerify = require('auth-verify');
const auth = new AuthVerify({
jwtSecret: 'supersecret',
storeTokens: 'memory',
});
const app = express();
app.use(express.json());
// Login: issue JWT
app.post('/login', async (req, res) => {
const token = await auth.jwt.sign({ id: 'u1', role: 'admin' }, '2h', { res });
res.json({ token });
});
// Protected route
app.get('/me', auth.jwt.protect(), (req, res) => {
res.json({ message: `Welcome, ${req.user.id}` });
});
// Logout: revoke token
app.post('/logout', async (req, res) => {
const token = auth.jwt.readCookie(req, 'auth_token');
await auth.jwt.revoke(token);
res.json({ success: true, message: 'Logged out' });
});
app.listen(3000, () => console.log('โ
Auth server running on port 3000'));๐ง Notes
- Works seamlessly with
cookie-parseror built-in cookie reader. - Supports both stateful (Redis/Memory) and stateless (None) JWT modes.
- Built-in cookie signing ensures secure browser sessions.
- Middleware simplifies authentication guards in Express apps.
๐ข OTP (email / sms / telegram / whatsapp api / custom sender)
๐ OTP Manager โ auth-verify
The OTPManager handles one-time passwords (OTP) for multi-channel authentication:
- โ Email
- โ SMS
- โ WhatsApp
- โ Telegram Supports memory, Redis, or no storage, cooldowns, and max-attempt tracking.
๐ฆ Import
const AuthVerify = require("auth-verify");
const auth = new AuthVerify();
// Access OTP manager
const otp = auth.otp; // internally uses OTPManagerโ๏ธ Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
otpExpiry |
string/number | 300 |
OTP expiration time, e.g., "5m" or "30s" |
storeTokens |
string | "memory" |
Storage type: "memory", "redis", or "none" |
otpHash |
string | "sha256" |
Hashing algorithm for OTP (optional) |
sender |
object | null |
Email/SMS/WhatsApp/Telegram sender configuration |
redisUrl |
string | "redis://localhost:6379" |
Redis connection URL (if storeTokens = 'redis') |
โ๏ธ Sender Configuration
Email sender
Using Gmail
otp.sender({
via: "email", // or "sms", "telegram", "whatsapp"
service: "gmail", // email service
sender: "your_email@gmail.com",
pass: "your_app_password",
host: "smtp.gmail.com",
port: 587,
secure: false
});
// or you can use otp.setSender({...});Using SMTP service
otp.sender({
via: "email", // or "sms", "telegram", "whatsapp"
sender: "your_email@gmail.com",
pass: "your_app_password",
host: "smtp.gmail.com",
port: 587,
secure: false
})SMS sender
๐ Auth-Verify SMS API โ Full Guide
Auth-Verify supports sending OTPs via SMS using 30+ global SMS providers.
1๏ธโฃ Initialize SMS Sender
Before sending SMS, you must configure your sender:
otp.sender({
via: "sms", // REQUIRED โ "sms" or "email" or "telegram"
provider: "twilio", // REQUIRED โ choose provider
apiKey: process.env.TWILIO_SID, // varies per provider
apiSecret: process.env.TWILIO_TOKEN, // varies per provider
sender: "+15005550006", // sender phone or ID
mock: false // optional: true = no real SMS sent
});2๏ธโฃ Send OTP
const smsResponse = await otp.send("+998901234567");
console.log(smsResponse);โ Example Response
{
"status": "SENT",
"provider": "Twilio",
"to": "+998901234567"
}3๏ธโฃ Mock Mode for Testing
otp.sender({
via: "sms",
provider: "twilio",
mock: true
});Console output:
๐ฑ [Mock SMS via twilio]
โ To: +998901234567
โ Message: Your OTP is 1234565๏ธโฃ Supported SMS Providers & Example Config
| Provider | Config Example | Notes |
|---|---|---|
| Twilio | apiKey = SID, apiSecret = TOKEN, sender = +15005550006 |
Global |
| Vonage / Nexmo | apiKey, apiSecret, sender |
Global |
| Infobip | apiKey, sender |
Global / EU strong |
| Eskiz | email, password, sender |
Uzbekistan |
| PlayMobile | apiKey, apiSecret, sender |
Uzbekistan |
| MSG91 | apiKey, templateId = apiSecret |
India |
| Telesign | apiKey, apiSecret |
Global |
| SMS.ru | apiKey |
Russia |
| TextLocal | apiKey, sender |
India/UK |
| ClickSend | apiKey, apiSecret, sender |
Global |
| Sinch | apiKey, apiSecret |
Global |
| Telnyx | apiKey, sender |
Global |
| NetGSM | apiKey, apiSecret, sender |
Turkey |
| KaveNegar | apiKey |
Iran |
| Unifonic | apiKey, sender |
Saudi Arabia |
| Alibaba Cloud SMS | apiKey, template_id, region, sender |
China |
| Firebase | client SDK only | OTP must be sent client-side |
| CheapGlobalsms | apiKey, apiSecret, sender |
Global |
| Africa's Talking | apiKey, sender |
Africa |
| MessageBird | apiKey, sender |
Global |
| SMSAPI | apiKey, sender |
Europe |
| Clickatell | apiKey, sender |
Global |
| Plivo | apiKey, apiSecret, sender |
Global |
| Vibes | apiKey |
US |
| SMS Gateway Hub | apiKey, sender |
India |
| TextMagic | apiKey, apiSecret, sender |
Global |
All providers use the same
sendSMShelper, just change provider and API credentials. How to use this table:// Using eskiz provider (for example) otp.sender({ provider: 'eskiz', // (see Provider column) email: "YOUR_EMAIL_HERE", // (see Config Example column) password: "YOUR_PASSWORD_HERE", // (see Config Example column) sender: "YOUR_SENDER_NAME_HERE" // (see Config Example column) });
Error handling
try {
const result = await auth.otp.send("+998901234567");
} catch (err) {
console.error("SMS failed:", err.message);
}Telegram sender
otp.sender({
via: 'telegram',
token: '123:ABC', // bot token
// call auth.otp.setupTelegramBot(token) to start the bot
});WhatsApp Business API
otp.sender({
via: 'whatsapp',
phoneId: "YOUR_PHONE_ID",
token: "YOUR_WHATSAPP_TOKEN"
});๐ช Generate OTP
otp.generate(6); // 6-digit OTP- Returns a numeric string
- Supports callback style:
otp.generate(6, (err, code) => {
console.log(code);
});- Chainable:
otp.generate(6).set("user@example.com");๐พ Store OTP
await otp.set("user@example.com");- Supports memory and Redis
- Stores metadata: attempts, expiry, cooldown
- Can also use callback style for memory storage
๐ค Send OTP
await otp.send("user@example.com", {
subject: "Your OTP Code",
text: "Your OTP is 123456",
html: "<b>123456</b>"
});
// or simply
await otp.send("user@example.com");Supports channels:
via |
Notes |
|---|---|
| Configured with Gmail/SMTP | |
| sms | Uses sendSMS helper or custom provider |
| telegram | Sends OTP via bot, requires botToken |
| Uses WhatsApp Business API |
Callback style:
otp.send("user@example.com", options, (err, info) => {
if(err) console.error(err);
else console.log(info);
});๐ Verify OTP
// Promise style
const result = await otp.verify("user@example.com", "123456");
//const result = await otp.verify({ check: "user@example.com", code: "123456" }); or you can use this style
// Callback style
otp.verify("user@example.com", "123456", (err, success) => {
if(err) console.error(err.message);
else console.log("โ
OTP verified");
});- Automatically deletes OTP after successful verification
- Checks expiry and maximum attempts
- Throws descriptive errors:
OTP expiredInvalid OTPMax attempts reached
โฑ Cooldown
otp.cooldown("30s"); // cooldown before OTP can be resent- Accepts
"30s","2m","1h", or milliseconds - Enforced in
resend()method
๐ Resend OTP
const code = await otp.resend("user@example.com");- Automatically generates a new OTP if expired
- Updates cooldown
- Sends via configured channel (email/SMS/WhatsApp)
- Callback support:
otp.resend("user@example.com", (err, code) => {
if(err) console.error(err.message);
else console.log("Resent OTP:", code);
});๐ค Telegram Integration
await otp.setupTelegramBot("YOUR_BOT_TOKEN");- Sets up a Telegram bot to send OTP
- Users share their phone number in chat
- OTP automatically sent to the shared number
๐ Private Methods (Internal)
#sendEmail(reciever, options)โ Sends email OTP#sendSMS(reciever, options)โ Sends SMS OTP#sendWhatsApp(reciever, options)โ Sends WhatsApp OTPUsually not called directly โ use
otp.send()instead.
๐งฉ Example Usage
const AuthVerify = require("auth-verify");
const auth = new AuthVerify({ otpExpiry: "5m", storeTokens: "memory" });
// Set sender
auth.otp.setSender({
via: "email",
service: "gmail",
sender: process.env.EMAIL,
pass: process.env.EMAIL_PASS
});
// Generate and send OTP
await auth.otp.send("user@example.com", { subject: "Verify your account" });
// Verify OTP
try {
await auth.otp.verify({ check: "user@example.com", code: "123456" });
console.log("โ
OTP verified!");
} catch (err) {
console.error(err.message);
}
// Resend OTP if needed
const newCode = await auth.otp.resend("user@example.com");
console.log("Resent OTP:", newCode);โก Notes
- OTPManager is fully integrated into auth-verify wrapper
- Supports multi-channel OTP with memory or Redis storage
- Handles cooldowns, max attempts, and automatic expiry
- Can be extended with custom sender functions
๐ AuthVerify TOTP API Guide
โ TOTP (Time-based One Time Passwords) โ Google Authenticator support
1๏ธโฃ Generate TOTP Secret
Theory:
- Generate a Base32 secret for a user.
- Secret is required to generate TOTP codes in an authenticator app (Google Authenticator, Authy, etc.).
Code:
// GET /api/totp/secret
app.get("/api/totp/secret", (req, res) => {
const secret = auth.totp.secret(); // Base32 secret
res.json({ success: true, secret });
});Usage:
const response = await fetch("http://localhost:3000/api/totp/secret");
const data = await response.json();
console.log(data.secret); // "JBSWY3DPEHPK3PXP"Usage (with Auth-verify client):
const auth = new AuthVerify({ apiBase: "http://localhost:3000" });
const res = auth.get("/api/secret/totp/secret").data();
console.log(res.secret); // "JBSWY3DPEHPK3PXP"2๏ธโฃ Generate TOTP URI
Theory:
- Convert secret into an otpauth:// URI for authenticator apps.
- URI includes:
secret,label(user email),issuer(app name), algorithm, digits, and period.
Code:
// POST /api/totp/uri
app.post("/api/totp/uri", (req, res) => {
const { secret, label, issuer } = req.body;
const uri = auth.totp.uri({ secret, label, issuer });
res.json({ success: true, uri });
});Usage:
const { uri } = await fetch("http://localhost:3000/api/totp/uri", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
secret: "JBSWY3DPEHPK3PXP",
label: "user@example.com",
issuer: "MyApp"
})
}).then(r => r.json());
console.log(uri);
// otpauth://totp/MyApp:user@example.com?secret=...Usage (with Auth-verify client):
const auth = new AuthVerify({ apiBase: "http://localhost:3000" });
const uri = auth.post("/api/totp/uri").data({secret: "JBSWY3DPEHPK3PXP", label: "user@example.com", issuer: "MyApp"});
console.log(uri); // otpauth://totp/MyApp:user@example.com?secret=...3๏ธโฃ Generate QR Code
Theory:
- Convert TOTP URI into a QR code.
- Users can scan QR code with their authenticator app.
Code:
// POST /api/totp/qrcode
app.post("/api/totp/qrcode", async (req, res) => {
const { uri } = req.body;
const qr = await auth.totp.qr(uri); // returns base64 data URL
res.json({ success: true, qr });
});Usage:
const { qr } = await fetch("http://localhost:3000/api/totp/qrcode", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ uri })
}).then(r => r.json());
document.getElementById("totp-qrcode").src = qr;Usage (with Auth-verify client):
const auth = new AuthVerify({
apiBase: "http://localhost:3000",
qrEl: document.getElementById("totp-qrcode")
});
auth.get("/api/totp/qrcode").qr();4๏ธโฃ Verify TOTP Code
Theory:
- Compare user-provided code with expected code.
- Optional
windowallows ยฑ1 or more steps to account for clock skew.
Code:
// POST /api/totp/verify
app.post("/api/totp/verify", (req, res) => {
const { secret, code, window } = req.body;
const valid = auth.totp.verify(secret, code, window);
res.json({ success: true, valid });
});Usage:
const userCode = prompt("Enter your TOTP code:");
const { valid } = await fetch("http://localhost:3000/api/totp/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
secret: "JBSWY3DPEHPK3PXP",
code: userCode
})
}).then(r => r.json());
if(valid) alert("โ
Verified!");
else alert("โ Invalid TOTP code");Usage (with Auth-verify client):
const auth = new AuthVerify({ apiBase: "http://localhost:3000" });
const valid = auth.post("/api/totp/verify").verify(userCode);
if(valid) alert("โ
Verified!");
else alert("โ Invalid TOTP code");5๏ธโฃ API Reference Table
| Endpoint | Method | Description | Payload | Response |
|---|---|---|---|---|
/api/totp/secret |
GET | Generate a Base32 secret | None | { success: true, secret: "..." } |
/api/totp/uri |
POST | Convert secret to otpauth URI | { secret, label, issuer } |
{ success: true, uri: "..." } |
/api/totp/qrcode |
POST | Generate QR code from URI | { uri } |
{ success: true, qr: "data:image/png;base64,..." } |
/api/totp/verify |
POST | Verify user TOTP code | { secret, code, window? } |
{ success: true, valid: true/false } |
๐๏ธ Passkey (WebAuthn)
๐ Passkey Authentication โ AuthVerify Frontend + Backend Guide
This guide explains how to integrate Passkey (WebAuthn) authentication using the AuthVerify ecosystem โ including both:
- ๐ง Backend:
PasskeyManager(Node.js) - ๐ป Frontend:
window.AuthVerifywrapper (Browser)
โ๏ธ 1. Backend Setup (Node.js)
Import and configure AuthVerify:
const express = require("express");
const AuthVerify = require("auth-verify");
const app = express();
app.use(express.json());
const auth = new AuthVerify({
rpName: "AuthVerifyApp", // Display name in browser prompt
storeTokens: "memory", // or "redis"
passExp: "2m", // Challenge expiration
});๐งฉ 2. Passkey Registration API
โ
POST /api/register/start
Generate registration challenge for a new user.
app.post("/api/register/start", async (req, res) => {
const user = req.body.user; // e.g. { id: "u123", username: "john_doe" }
await auth.passkey.register(user);
res.json(auth.passkey.getOptions());
});
auth.issue()can be used for saving passkey in any device
โ
POST /api/register/finish
Verify attestation and save credential.
app.post("/api/register/finish", async (req, res) => {
const result = await auth.passkey.finish(req.body);
res.json(result);
});Example successful response:
{
"status": "ok",
"user": {
"id": "u123",
"username": "john_doe",
"credentials": [
{
"id": "AaBbCcDdEe...",
"publicKey": "-----BEGIN PUBLIC KEY-----...",
"signCount": 0
}
]
},
"credentialId": "AaBbCcDdEe..."
}๐ 3. Passkey Login API
โ
POST /api/login/start
Generate login challenge for existing user.
app.post("/api/login/start", async (req, res) => {
const user = req.body.user; // same user object used at registration
await auth.passkey.login(user);
res.json(auth.passkey.getOptions());
});โ
POST /api/login/finish
Verify user assertion (digital signature).
app.post("/api/login/finish", async (req, res) => {
const result = await auth.passkey.finish(req.body);
res.json(result);
});Successful login:
{
"status": "ok",
"user": { "id": "u123", "username": "john_doe" }
}๐ป 4. Frontend Integration (Browser)
Include your frontend wrapper (already built as window.AuthVerify):
<script src="https://cdn.jsdelivr.net/gh/jahongir2007/auth-verify/auth-verify.client.js"></script>
<script>
const auth = new AuthVerify({ apiBase: "http://localhost:3000" });
</script>โก 5. Frontend Methods
๐งฑ .post(url) / .get(url)
Set endpoint for POST/GET requests before calling .data().
โ๏ธ .data(payload)
Send JSON to backend and return response.
๐ง Step Breakdown
1๏ธโฃ Frontend โ Backend: /api/register/start
Sends { user } and gets WebAuthn challenge/options.
2๏ธโฃ Browser:
Calls navigator.credentials.create({ publicKey })
Prompts user for biometric or security key registration.
3๏ธโฃ Frontend โ Backend: /api/register/finish
Sends credential data (clientDataJSON, attestationObject, etc.)
4๏ธโฃ Backend:
Validates and stores public key in user credentials.
๐ง Step Breakdown
1๏ธโฃ Frontend โ Backend: /api/login/start
Sends { user, login: true } to get challenge and allowCredentials.
2๏ธโฃ Browser:
Calls navigator.credentials.get({ publicKey }).
3๏ธโฃ Frontend โ Backend: /api/login/finish
Sends credential signature data (authenticatorData, signature, etc.)
4๏ธโฃ Backend:
Verifies signature using stored public key.
๐ง 8. Quick Reference
| Layer | Method | Description |
|---|---|---|
| Backend | passkey.register(user) |
Start registration |
| Backend | passkey.getOptions() |
Return challenge for browser |
| Backend | passkey.finish(clientResponse) |
Finish registration/login |
โ 9. Notes & Best Practices
- Use HTTPS in production (
navigator.credentialsrequires secure origin) - Always send real
user.id(string, not numeric) - Store public keys securely in DB after registration
- Set realistic expiration time for passkey challenges (
passExp) - Combine with your
JWTManagerfor session generation after successful login
๐ AuthVerify Client Guide
This client is designed to interact with the backend AuthVerify API for passkeys / WebAuthn credentials. It does not require body-parser or any server-side logic on the frontend.
๐ฆ Import
<!-- โ
Import auth-verify client -->
<script src="https://cdn.jsdelivr.net/gh/jahongir2007/auth-verify/auth-verify.client.js"></script>โ๏ธ Initialization
const auth = new AuthVerify({
apiBase: "http://localhost:3000",
qrEl: document.getElementById("qr") // optional, for QR codes
});| Option | Type | Default | Description |
|---|---|---|---|
apiBase |
string |
'http://localhost:3000' |
Backend API base URL |
qrEl |
HTMLImageElement |
null |
Optional element to display QR codes |
๐ฌ Methods
1๏ธโฃ post(url)
Sets the POST endpoint for the next request.
auth.post("/start-passkey");2๏ธโฃ get(url)
Sets the GET endpoint for the next request.
auth.get("/fetch-qr");3๏ธโฃ qr()
Fetches a QR code from the backend and renders it in qrEl.
await auth.get("/fetch-qr").qr();Behavior:
- If
qrElexists, itssrcwill be set to the QR image returned by the backend. - Logs an error if no QR or fetch fails.
4๏ธโฃ data(payload)
Sends a POST request with JSON payload to the set endpoint.
const response = await auth.post("/verify-otp").data({ code: "123456" });
console.log(response);5๏ธโฃ header()
Returns an authorization header if jwt exists.
const headers = auth.header();
// { Authorization: 'Bearer <token>' }6๏ธโฃ verify(code)
Shortcut for sending OTP / code to backend.
const result = await auth.verify("123456");7๏ธโฃ base64urlToUint8Array(base64url)
Helper to decode Base64URL strings (used for WebAuthn challenges).
const arr = auth.base64urlToUint8Array("BASE64URL_STRING");8๏ธโฃ issue(publicKey)
Creates a WebAuthn credential on the client (passkey).
// 1๏ธโฃ Get registration options from backend
const publicKey = await auth.post("/start-passkey").data({ user: { id: "user123", name: "Alice" } });
// 2๏ธโฃ Issue credential in browser
const credentialData = await auth.issue(publicKey);
// 3๏ธโฃ Send credential back to backend
const result = await auth.post("/finish-passkey").data(credentialData);
console.log(result);| Step | Description |
|---|---|
| 1 | Fetch publicKey options from backend |
| 2 | Decode challenge & user ID, create credential with navigator.credentials.create() |
| 3 | Convert ArrayBuffers to Base64 and return structured object |
| 4 | Send credential to backend via post() |
Returned object:
{
id: "...",
rawId: "...",
type: "public-key",
response: {
clientDataJSON: "...",
attestationObject: "..."
}
}๐งช Example Full Flow
(async () => {
const auth = new AuthVerify({ apiBase: "http://localhost:3000", qrEl: document.getElementById("qr") });
// Display QR from backend
await auth.get("/fetch-qr").qr();
// Create a passkey
const publicKey = await auth.post("/start-passkey").data({ user: { id: "user123", name: "Alice" } });
const credential = await auth.issue(publicKey);
// Send back to backend
const result = await auth.post("/finish-passkey").data(credential);
console.log(result);
})();9๏ธโฃ Example HTML
<img id="qrImage" />
<div id="response"></div>
<button id="getQRBtn">Get QR</button>
<button id="sendBtn">Send Data</button>
<script src="https://cdn.jsdelivr.net/gh/jahongir2007/auth-verify/auth-verify.client.js"></script>
<script>
const qrImage = document.getElementById('qrImage');
const responseDiv = document.getElementById('response');
const auth = new AuthVerify({ apiBase: 'http://localhost:3000', qrEl: qrImage });
document.getElementById('getQRBtn').addEventListener('click', () => auth.get('/api/qr').qr());
document.getElementById('sendBtn').addEventListener('click', async () => {
const payload = { name: 'Jahongir' };
const result = await auth.post('/api/sign-jwt').data(payload);
responseDiv.textContent = JSON.stringify(result, null, 2);
});
</script>10๏ธโฃ Tips for Developers
- Always call
auth.get('/api/qr').qr()after page loads - Use
auth.header()for any authenticated request - Backend must provide endpoints for
/api/qr,/api/verify-totp,/api/sign-jwt - Make sure backend endpoints return raw WebAuthn options (
challenge,user,allowCredentials) in Base64URL format. user.idandchallengemust be Base64URL encoded on backend.- JWT storage is automatic if backend returns token.
๐ OAuth Manager โ auth-verify
The OAuthManager in auth-verify provides an easy and unified way to integrate popular social logins such as Google, GitHub, Facebook, Twitter (X), LinkedIn, and others.
Each provider offers two main methods:
redirect(res)โ Redirects users to providerโs authorization pagecallback(code)โ Exchanges authorization code for access token and retrieves user data
๐ฆ Import
const AuthVerify = require("auth-verify");
const auth = new AuthVerify();Then access:
auth.oauthโ๏ธ Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
providers |
object |
{} |
Register custom OAuth providers dynamically. |
๐งฉ Supported Providers
The following providers are built-in and ready to use:
| Provider | Method | OAuth Version |
|---|---|---|
auth.oauth.google() |
v2 | |
auth.oauth.facebook() |
v2 | |
| GitHub | auth.oauth.github() |
v2 |
| Twitter (X) | auth.oauth.x() |
v2 |
auth.oauth.linkedin() |
v2 | |
| Apple | auth.oauth.apple() |
v2 |
| Discord | auth.oauth.discord() |
v2 |
| Slack | auth.oauth.slack() |
v2 |
| Microsoft | auth.oauth.microsoft() |
v2 |
| Telegram | auth.oauth.telegram() |
Deep Link |
auth.oauth.whatsapp() |
Deep Link | |
auth.oauth.reddit() |
v2 | |
| Yandex | auth.oauth.yandex() |
v2 |
| Tumblr | auth.oauth.tumblr() |
v2 |
| Mail.ru | auth.oauth.mailru() |
v2 |
| VK | auth.oauth.vk() |
v2 |
| Yahoo | auth.oauth.yahoo() |
v2 |
๐ช Common Usage
Step 1: Redirect user to provider
app.get("/auth/google", (req, res) => {
auth.oauth.google({
clientId: process.env.GOOGLE_CLIENT_ID,
redirectUri: "http://localhost:3000/auth/google/callback"
}).redirect(res);
});Step 2: Handle callback and get user data
app.get("/auth/google/callback", async (req, res) => {
try {
const data = await auth.oauth.google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: "http://localhost:3000/auth/google/callback"
}).callback(req.query.code);
res.json({ success: true, user: data });
} catch (err) {
res.status(400).json({ error: err.message });
}
});๐ Provider Reference
Each provider returns { redirect, callback }.
Below are provider-specific examples and scopes.
๐ข Google Login
Scopes: openid email profile
auth.oauth.google({
clientId,
clientSecret,
redirectUri
});Returns user:
{
"email": "user@gmail.com",
"name": "John Doe",
"picture": "https://...",
"access_token": "ya29.a0..."
}๐ต Facebook Login
Scopes: email, public_profile
auth.oauth.facebook({ clientId, clientSecret, redirectUri });Returns user:
{
"id": "123456789",
"name": "John Doe",
"email": "john@example.com",
"picture": { "data": { "url": "https://..." } },
"access_token": "EAAJ..."
}โซ GitHub Login
Scopes: user:email
auth.oauth.github({ clientId, clientSecret, redirectUri });Returns user:
{
"login": "johndoe",
"id": 123456,
"email": "john@example.com",
"avatar_url": "https://github.com/images/...",
"access_token": "gho_..."
}๐ฆ Twitter (X) Login
Scopes: tweet.read users.read offline.access
auth.oauth.x({ clientId, clientSecret, redirectUri });Returns user:
{
"data": { "id": "12345", "name": "John Doe", "username": "johndoe" },
"access_token": "2.abc..."
}๐ผ LinkedIn Login
Scopes: r_liteprofile r_emailaddress
auth.oauth.linkedin({ clientId, clientSecret, redirectUri });Returns user:
{
"id": "A1B2C3D4",
"name": "John Doe",
"email": "john@example.com",
"access_token": "AQW..."
}๐ Apple Login
Scopes: name email
auth.oauth.apple({ clientId, clientSecret, redirectUri });Returns:
{
"access_token": "eyJraWQiOi...",
"id_token": "...",
"refresh_token": "...",
"expires_in": 3600
}๐ฌ Discord Login
Scopes: identify email
auth.oauth.discord({ clientId, clientSecret, redirectUri });Returns:
{
"id": "123456789",
"username": "john",
"email": "john@example.com",
"access_token": "abc123..."
}๐งฐ Slack Login
Scopes: identity.basic identity.email
auth.oauth.slack({ clientId, clientSecret, redirectUri });Returns:
{
"ok": true,
"access_token": "xoxp-...",
"authed_user": { "id": "U1234", "scope": "identity.basic,identity.email" }
}๐ช Microsoft Login
Scopes:* User.Read
auth.oauth.microsoft({ clientId, clientSecret, redirectUri });Returns token:
{
"token_type": "Bearer",
"expires_in": 3599,
"access_token": "EwB4A8l6..."
}๐ฌ Telegram Login (Deep Link)
auth.oauth.telegram({ botId: "YourBotName", redirectUri });Note: Telegram handles authentication through deep links. Returns:
{ "message": "Telegram login uses deep link auth" }๐ข WhatsApp Login (Deep Link)
auth.oauth.whatsapp({ phoneNumberId: "1234567890", redirectUri });Note: Usually handled via QR code or direct chat. Returns:
{ "message": "WhatsApp login uses QR/deep link auth" }๐งฑ Reddit Login
Scopes: identity
auth.oauth.reddit({ clientId, clientSecret, redirectUri });Returns user:
{
"name": "johndoe",
"id": "t2_123abc",
"icon_img": "https://styles.redditmedia.com/...",
"access_token": "abc123..."
}๐ฅ Yandex Login
Scopes: login:email login:info
auth.oauth.yandex({ clientId, clientSecret, redirectUri });Returns user:
{
"id": "1234567",
"display_name": "John Doe",
"emails": ["john@yandex.ru"],
"default_email": "john@yandex.ru",
"access_token": "y0_AgAAA..."
}๐ Tumblr Login
Scopes: basic write offline_access
auth.oauth.tumblr({ clientId, clientSecret, redirectUri });Returns user:
{
"name": "johndoe",
"blogs": [{ "name": "myblog", "title": "My Tumblr Blog" }],
"access_token": "xyz..."
}โ๏ธ Mail.ru Login
Scopes: userinfo.email
auth.oauth.mailru({ clientId, clientSecret, redirectUri });Returns user:
{
"id": "123456",
"email": "user@mail.ru",
"name": "John Doe",
"access_token": "abc123..."
}๐ง VK (VKontakte) Login
Scopes: email
auth.oauth.vk({ clientId, clientSecret, redirectUri });Returns user:
{
"id": 987654,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"access_token": "vk1.a.abc..."
}๐ Yahoo Login
Scopes: openid profile email
auth.oauth.yahoo({ clientId, clientSecret, redirectUri });Returns user:
{
"sub": "12345",
"email": "john@yahoo.com",
"name": "John Doe",
"access_token": "y0_AgA..."
}๐งฉ Custom OAuth Provider
You can register your own provider logic:
auth.oauth.register("custom", ({ clientId, clientSecret, redirectUri }) => ({
redirect(res) {
res.redirect("https://custom-oauth.com/auth");
},
async callback(code) {
return { code, message: "Custom provider handled!" };
},
}));
// Usage:
auth.oauth.use("custom", { clientId, clientSecret, redirectUri });๐ Error Handling
Each callback() method may throw:
OAuth Error: invalid_clientOAuth Error: invalid_grantOAuth Error: unauthorized_clientOAuth Error: access_deniedAlways wrap in try/catch:
try {
const user = await auth.oauth.google(...).callback(code);
} catch (err) {
console.error("Login failed:", err.message);
}๐ก Notes
- Every provider uses OAuth 2.0 Authorization Code flow.
redirect(res)is server-side only (Node.js Express compatible).- Works perfectly inside your
auth-verifyunified wrapper.
๐ Magiclink (Passwordless login) (v1.8.0+)
The Magic Link Manager allows developers to implement secure, passwordless login using email-based links. Built directly into the AuthVerify SDK, it supports Gmail, custom SMTP, and token storage via Memory or Redis.
๐ Basic Setup
const AuthVerify = require('auth-verify');
const auth = new AuthVerify({
mlSecret: 'super_secret_key',
mlExpiry: '5m',
appUrl: 'http://localhost:3000',
storeTokens: 'memory'
});โ๏ธ Configure Magic Link Sender
Before sending links, you must set up your email transport.
Gmail Example
await auth.magic.sender({
service: 'gmail',
sender: 'yourapp@gmail.com',
pass: 'your_gmail_app_password'
});Custom SMTP Example
await auth.magic.sender({
host: 'smtp.mailgun.org',
port: 587,
secure: false,
sender: 'noreply@yourdomain.com',
pass: 'your_smtp_password'
});โ Both Gmail and any SMTP provider are supported. Use app passwords or tokens instead of your real password!
๐ฉ Send Magic Link
Send a secure, expiring link to the userโs email:
await auth.magic.send('user@example.com', {
subject: 'Your Secure Login Link โจ',
html: `<p>Click below to sign in:</p>
<a href="{{link}}">Login Now</a>`
});The
{{link}}placeholder will automatically be replaced with the generated magic link.
๐ช Generate Magic Link Manually
If you just want to create a link (not send it yet):
const token = await auth.magic.generate('user@example.com');
console.log(token);Then make your own URL:
const link = `http://localhost:3000/auth/verify?token=${token}`;๐ Verify Magic Link
Typically used in your backend /auth/verify route:
app.get('/auth/verify', async (req, res) => {
const { token } = req.query;
try {
const user = await auth.magic.verify(token);
res.json({ success: true, user });
} catch (err) {
res.status(400).json({ success: false, message: err.message });
}
});๐ง How It Works
auth.magic.generate()โ creates a short-lived JWT with the userโs email.auth.magic.send()โ sends a secure login link by email.auth.magic.verify()โ decodes & validates the token, optionally checks store.
๐พ Storage Options
| Mode | Description | Best For |
|---|---|---|
memory (default) |
Uses in-memory Map() | Single server / small projects |
redis |
Uses Redis with TTL | Scalable, multi-server apps |
Example using Redis:
const auth = new AuthVerify({
storeTokens: 'redis',
redisUrl: 'redis://localhost:6379'
});๐งฐ Callback Support
You can also use Node-style callbacks if you prefer:
auth.magic.send('user@example.com', (err) => {
if (err) console.error('โ Failed to send link:', err);
else console.log('โ
Magic link sent!');
});๐ Example Express Integration
const express = require('express');
const bodyParser = require('body-parser');
const { AuthVerify } = require('auth-verify');
const app = express();
app.use(bodyParser.json());
const auth = new AuthVerify({
mlSecret: 'supersecretkey',
appUrl: 'http://localhost:3000',
storeTokens: 'memory'
});
auth.magic.sender({
service: 'gmail',
sender: 'yourapp@gmail.com',
pass: 'your_app_password'
});
// Send link
app.post('/auth/send', async (req, res) => {
const { email } = req.body;
await auth.magic.send(email);
res.json({ message: 'Magic link sent!' });
});
// Verify link
app.get('/auth/verify', async (req, res) => {
try {
const user = await auth.magic.verify(req.query.token);
res.json({ message: 'Login successful!', user });
} catch (err) {
res.status(400).json({ message: err.message });
}
});
app.listen(3000, () => console.log('๐ Server running on port 3000'));๐งพ Summary
| Feature | Supported |
|---|---|
| Gmail & SMTP | โ |
| Memory & Redis Token Store | โ |
| Token Expiry | โ |
| Callback & Promise APIs | โ |
| HTML Custom Email | โ |
โก Future Vision
auth.magic is built for modern SaaS, fintech, and crypto apps that need passwordless, secure, and user-friendly authentication.
Telegram integration
There are two ways to use Telegram flow:
Use the built-in
senderConfig.via = 'telegram'and callauth.otp.setupTelegramBot(botToken)โ this starts a polling bot that asks users to share their phone via/start, and then matches the phone to in-memory/Redis OTP records and replies with the code.Developer-supplied custom sender (see below) โ you can create your own bot and call it from
auth.use(...).send(...)or register viaauth.register.sender().
Important: Only one bot using long polling must be running per bot token โ if you get 409 Conflict it's because another process or instance is already polling that bot token.
Developer extensibility (custom senders)
You can register custom senders and use them:
// register a named sender function
auth.register.sender('consoleOtp', async ({ to, code }) => {
console.log(`[DEV SEND] send to ${to}: ${code}`);
});
// use it later (chainable)
await auth.use('consoleOtp').send({ to: '+998901234567', code: await auth.otp.generate(5).code });When a custom sender is registered, auth.otp.message() will first attempt the customSender before falling back to built-in providers.
๐ SessionManager API Documentation - auth-verify
The session manager of auth-verify provides a simple way to create, verify, and destroy user sessions in either memory or Redis storage.
Import
const AuthVerify = require('auth-verify');
const auth = new AuthVerify({ storeTokens: 'redis', redisUrl: "redis://localhost:6379" });Options:
| Option | Type | Default | Description |
|---|---|---|---|
storeTokens |
string | 'memory' |
Storage type for sessions: 'memory' or 'redis' |
redisUrl |
string | "redis://localhost:6379" |
Redis connection URL (required if storeTokens: 'redis') |
Methods
1๏ธโฃ create(userId, options)
Create a new session for a user. Parameters:
| Name | Type | Required | Description | |
|---|---|---|---|---|
userId |
string | โ | Unique ID of the user | |
options |
object | โ | Optional settings: `{ expiresIn: number | string }` |
expiresIn formats:
- Number โ seconds
- String โ
"30s","5m","2h","1d"
Returns:
Promise<string> โ The session ID (UUID)
Example:
// Memory storage
const auth = new AuthVerify({ storeTokens: 'memory' });
const sessionId = await auth.session.create("user123", { expiresIn: "2h" });
console.log(sessionId); // "550e8400-e29b-41d4-a716-446655440000"2๏ธโฃ verify(sessionId)
Verify if a session is valid.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sessionId |
string | โ | The session ID to verify |
Returns:
Promise<string> โ Returns the userId if session is valid
Throws:
"Session not found or expired""Session expired"
Example:
const userId = await auth.session.verify(sessionId);
console.log(userId); // "user123"3๏ธโฃ destroy(sessionId)
Invalidate (destroy) a session manually.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sessionId |
string | โ | The session ID to destroy |
Returns:
Promise<void>
Example:
await auth.session.destroy(sessionId);
console.log("Session destroyed");Notes & Best Practices
- Memory storage is fast but not persistent across server restarts. Use Redis in production.
- Always verify session before allowing access to protected routes.
- Optionally, combine with JWT or OTP for multi-layered authentication.
- Use
expiresInwisely โ shorter times improve security but may require more frequent re-login.
๐ CryptoManager API Guide
It supports both PBKDF2 and scrypt algorithms for password or data hashing.
๐ Overview
The CryptoManager class helps developers easily hash and verify passwords or any sensitive data
using strong cryptographic functions. It supports both Promise and callback styles.
๐งฉ Import and Setup
const AuthVerify = require('auth-verify');
// Default: pbkdf2 algorithm
const auth = new AuthVerify({
hashAlg: 'pbkdf2', // or 'scrypt'
iterations: 100000,
keyLen: 64
});๐จ 1๏ธโฃ Hash Data
Method
async hash(data, [callback])Description
Hashes a string (like a password) using the specified algorithm and salt. You can use Promise or callback style.
Parameters
| Name | Type | Description |
|---|---|---|
data |
string |
The input data to hash (e.g. password) |
callback |
function? |
Optional Node-style callback (err, result) |
Returns
An object containing:
{
hashAlg: "pbkdf2" | "scrypt",
salt: "<random hex string>",
hash: "<hashed data in hex>"
}Example (Promise)
const result = await auth.crypto.hash("myPassword123");
console.log(result);
// { hashAlg: 'pbkdf2', salt: '...', hash: '...' }Example (Callback)
auth.crypto.hash("myPassword123", (err, result) => {
if (err) return console.error(err);
console.log(result);
});๐ 2๏ธโฃ Verify Data
Method
async verify(data, { hashAlg, salt, hash }, [callback])Description
Verifies whether a given input matches a stored hash.
Parameters
| Name | Type | Description |
|---|---|---|
data |
string |
The plaintext input (e.g. user password) |
{ hashAlg, salt, hash } |
object |
The hash object from .hash() |
callback |
function? |
Optional Node-style callback (err, isValid) |
Returns
A boolean value:
trueโ data matchesfalseโ mismatch
Example (Promise)
const result = await cryptoManager.hash("secret123");
const isValid = await cryptoManager.verify("secret123", result);
console.log(isValid); // trueExample (Callback)
const original = await cryptoManager.hash("secret123");
cryptoManager.verify("secret123", original, (err, valid) => {
if (err) throw err;
console.log(valid); // true
});๐ 3๏ธโฃ Summary Table
| Method | Description | Returns | Async |
|---|---|---|---|
hash(data, [callback]) |
Hashes input using PBKDF2 or scrypt | { hashAlg, salt, hash } |
โ |
verify(data, { hashAlg, salt, hash }, [callback]) |
Verifies input against hash | boolean |
โ |
๐ง Notes
- Both PBKDF2 and scrypt are strong, salted, one-way hashing algorithms.
- Use PBKDF2 for compatibility; use scrypt for better memory-hard protection.
- Salt ensures that each hash output is unique even for identical inputs.
- The default iteration count (100,000) is secure but can be increased for stronger protection.
๐งช Example Full Flow
(async () => {
const manager = new CryptoManager({ hashAlg: 'scrypt' });
// Hash password
const hashData = await manager.hash('MyStrongPassword');
console.log('Stored hash:', hashData);
// Verify password
const match = await manager.verify('MyStrongPassword', hashData);
console.log('Password valid:', match);
})();Helpers
helpers/helper.js exposes utility functions used by managers:
generateSecureOTP(length, hashAlgorithm)โ returns secure numeric OTP stringparseTime(strOrNumber)โ converts'1h' | '30s' | numberinto millisecondsresendGeneratedOTP(params)โ helper to send email via nodemailer (used by resend)sendSMS(params)โ helper for sending SMS using supported providers or mock
Error handling and notes
- Many methods support both callback and Promise (async/await) styles. When using Redis store, prefer async/await (callback variants intentionally return an error when Redis is selected).
- OTP storage keys are the user identifier you pass (email or phone number). Keep identifiers consistent.
- Be careful when using Telegram polling: do not run two instances with polling true for the same bot token (use webhooks or a single process).
- When configuring SMTP (non-Gmail), provide
host,portandsecureinsetSender().
Suggested folder structure
auth-verify/
โโ README.md
โโ package.json
โโ index.js // exports AuthVerify
โโ src/
โ โโ jwt/
| | โโ index.js
| | โโ cookie/index.js
โ โโ /otp/index.js
โ โโ /magiclink/index.js
โ โโ /crypto/index.js
โ โโ totp/
| | โโ index.js
| | โโ base32.js
โ โโ /session/index.js
| โโ /oauth/index.js
โ โโ helpers/helper.js
โโ rest-api/
โ โโ public/index.html
โ โโ index.js
โโ babel.config.js
โโ auth-verify.client.jsContributing & License
Contributions welcome! Open issues / PRs for bugs, improvements, or API suggestions.
MIT ยฉ 2025 โ Jahongir Sobirov