New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

auth-verify

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

auth-verify

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

latest
Source
npmnpm
Version
1.13.3
Version published
Maintainers
1
Created
Source

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, .totp and .oauth managers.
  • JWTManager: sign, verify, decode, revoke tokens. Supports storeTokens: "memory" | "redis" | "none" and middleware with custom cookie, header, and token extraction.
  • OTPManager: generate, store, send, verify, resend OTPs. Supports storeTokens: "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:

OptionDefaultDescription
jwtSecret"jwt_secret"Secret key for JWT signing
cookieName"jwt_token"Cookie name for JWT storage
otpExpiry300OTP expiration in seconds
storeTokens"memory"Token storage type (memory or redis)
redisUrlundefinedRedis 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

MethodDescription
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:

NameTypeDefaultDescription
payloadobjectData to include in the JWT
expirystring | number'1h'Expiration time (5m, 2h, 1d, etc.)
options.resResponseExpress response object (sets cookie automatically)
options.securebooleantrueIf 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:

  • Authorization header (Bearer <token>)
  • Cookies (auth_token by 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:

NameTypeDescription
userobjectUser 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:

NameTypeDescription
refreshTokenstringA 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 minutes

If 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:

NameTypeDefaultDescription
attachPropertystring'user'Where decoded data is attached on the request
requiredRolestringnullRestricts route access by user role
cookieNamestringInherited from AuthVerifyCookie name to extract token
headerNamestring'authorization'Header name to look for JWT
extractorfunctionCustom token extraction logic
onErrorfunctionCustom 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-parser or 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

OptionTypeDefaultDescription
otpExpirystring/number300OTP expiration time, e.g., "5m" or "30s"
storeTokensstring"memory"Storage type: "memory", "redis", or "none"
otpHashstring"sha256"Hashing algorithm for OTP (optional)
senderobjectnullEmail/SMS/WhatsApp/Telegram sender configuration
redisUrlstring"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
})

Using API

otp.sender({
  via: "email",
  service: "api",
  sender: "your_email@gmail.com",
  apiService: "resend", // "mailgun", "sendgrid"
  apiKey: "your-api-key"
})

For "mailgun" you should also add also your domain

 domain: "your-domain.com"

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 123456
5️⃣ Supported SMS Providers & Example Config
ProviderConfig ExampleNotes
TwilioapiKey = SID, apiSecret = TOKEN, sender = +15005550006Global
Vonage / NexmoapiKey, apiSecret, senderGlobal
InfobipapiKey, senderGlobal / EU strong
Eskizemail, password, senderUzbekistan
PlayMobileapiKey, apiSecret, senderUzbekistan
MSG91apiKey, templateId = apiSecretIndia
TelesignapiKey, apiSecretGlobal
SMS.ruapiKeyRussia
TextLocalapiKey, senderIndia/UK
ClickSendapiKey, apiSecret, senderGlobal
SinchapiKey, apiSecretGlobal
TelnyxapiKey, senderGlobal
NetGSMapiKey, apiSecret, senderTurkey
KaveNegarapiKeyIran
UnifonicapiKey, senderSaudi Arabia
Alibaba Cloud SMSapiKey, template_id, region, senderChina
Firebaseclient SDK onlyOTP must be sent client-side
CheapGlobalsmsapiKey, apiSecret, senderGlobal
Africa's TalkingapiKey, senderAfrica
MessageBirdapiKey, senderGlobal
SMSAPIapiKey, senderEurope
ClickatellapiKey, senderGlobal
PlivoapiKey, apiSecret, senderGlobal
VibesapiKeyUS
SMS Gateway HubapiKey, senderIndia
TextMagicapiKey, apiSecret, senderGlobal

All providers use the same sendSMS helper, 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:

viaNotes
emailConfigured with Gmail/SMTP
smsUses sendSMS helper or custom provider
telegramSends OTP via bot, requires botToken
whatsappUses 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 expired
  • Invalid OTP
  • Max 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 OTP

Usually 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 window allows ±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

EndpointMethodDescriptionPayloadResponse
/api/totp/secretGETGenerate a Base32 secretNone{ success: true, secret: "..." }
/api/totp/uriPOSTConvert secret to otpauth URI{ secret, label, issuer }{ success: true, uri: "..." }
/api/totp/qrcodePOSTGenerate QR code from URI{ uri }{ success: true, qr: "data:image/png;base64,..." }
/api/totp/verifyPOSTVerify 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.AuthVerify wrapper (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

LayerMethodDescription
Backendpasskey.register(user)Start registration
Backendpasskey.getOptions()Return challenge for browser
Backendpasskey.finish(clientResponse)Finish registration/login

✅ 9. Notes & Best Practices

  • Use HTTPS in production (navigator.credentials requires 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 JWTManager for 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
});
OptionTypeDefaultDescription
apiBasestring'http://localhost:3000'Backend API base URL
qrElHTMLImageElementnullOptional 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 qrEl exists, its src will 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);
StepDescription
1Fetch publicKey options from backend
2Decode challenge & user ID, create credential with navigator.credentials.create()
3Convert ArrayBuffers to Base64 and return structured object
4Send 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.id and challenge must 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 page
  • callback(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

OptionTypeDefaultDescription
providersobject{}Register custom OAuth providers dynamically.

🧩 Supported Providers

The following providers are built-in and ready to use:

ProviderMethodOAuth Version
Googleauth.oauth.google()v2
Facebookauth.oauth.facebook()v2
GitHubauth.oauth.github()v2
Twitter (X)auth.oauth.x()v2
LinkedInauth.oauth.linkedin()v2
Appleauth.oauth.apple()v2
Discordauth.oauth.discord()v2
Slackauth.oauth.slack()v2
Microsoftauth.oauth.microsoft()v2
Telegramauth.oauth.telegram()Deep Link
WhatsAppauth.oauth.whatsapp()Deep Link
Redditauth.oauth.reddit()v2
Yandexauth.oauth.yandex()v2
Tumblrauth.oauth.tumblr()v2
Mail.ruauth.oauth.mailru()v2
VKauth.oauth.vk()v2
Yahooauth.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..."
}
auth.oauth.telegram({ botId: "YourBotName", redirectUri });

Note: Telegram handles authentication through deep links. Returns:

{ "message": "Telegram login uses deep link auth" }
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_client
  • OAuth Error: invalid_grant
  • OAuth Error: unauthorized_client
  • OAuth Error: access_denied Always 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-verify unified wrapper.

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'
});

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 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.

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}`;

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

ModeDescriptionBest For
memory (default)Uses in-memory Map()Single server / small projects
redisUses Redis with TTLScalable, 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

FeatureSupported
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 call auth.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 via auth.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:
OptionTypeDefaultDescription
storeTokensstring'memory'Storage type for sessions: 'memory' or 'redis'
redisUrlstring"redis://localhost:6379"Redis connection URL (required if storeTokens: 'redis')

Methods

1️⃣ create(userId, options)

Create a new session for a user. Parameters:

NameTypeRequiredDescription
userIdstringUnique ID of the user
optionsobjectOptional settings: `{ expiresIn: numberstring }`

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:
NameTypeRequiredDescription
sessionIdstringThe 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:
NameTypeRequiredDescription
sessionIdstringThe 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 expiresIn wisely — 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

NameTypeDescription
datastringThe input data to hash (e.g. password)
callbackfunction?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

NameTypeDescription
datastringThe plaintext input (e.g. user password)
{ hashAlg, salt, hash }objectThe hash object from .hash()
callbackfunction?Optional Node-style callback (err, isValid)

Returns

A boolean value:

  • true → data matches
  • false → mismatch

Example (Promise)

const result = await cryptoManager.hash("secret123");
const isValid = await cryptoManager.verify("secret123", result);
console.log(isValid); // true

Example (Callback)

const original = await cryptoManager.hash("secret123");

cryptoManager.verify("secret123", original, (err, valid) => {
  if (err) throw err;
  console.log(valid); // true
});

📊 3️⃣ Summary Table

MethodDescriptionReturnsAsync
hash(data, [callback])Hashes input using PBKDF2 or scrypt{ hashAlg, salt, hash }
verify(data, { hashAlg, salt, hash }, [callback])Verifies input against hashboolean

🧠 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 string
  • parseTime(strOrNumber) — converts '1h' | '30s' | number into milliseconds
  • resendGeneratedOTP(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, port and secure in setSender().

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.js

Contributing & License

Contributions welcome! Open issues / PRs for bugs, improvements, or API suggestions.

MIT © 2025 - 2026 — Jahongir Sobirov

Keywords

auth

FAQs

Package last updated on 16 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts