UNPKG

rauth-provider

Version:

A lightweight, plug-and-play Node.js library for phone number authentication using the Rauth.io reverse verification flow via WhatsApp or SMS.

251 lines (188 loc) • 7.19 kB
# RauthProvider A lightweight, plug-and-play Node.js library for phone number authentication using the Rauth.io reverse verification flow via WhatsApp or SMS. It handles everything from session creation to revocation — with real-time webhook updates and Express.js support, all with minimal setup. --- ## āœ… Features šŸ“² **Reverse Authentication** – Authenticate users via WhatsApp or SMS without sending OTPs šŸ” **Session Management** – Track sessions, verify tokens, and revoke access automatically šŸ“” **Webhook Support** – Listen for number verification and session revocation in real-time 🧩 **Plug-and-Play API** – Simple, developer-friendly API surface ⚔ **Express Middleware** – Drop-in Express.js integration šŸ›”ļø **Secure by Design** – Signature-based verification and session validation 🧠 **Smart Caching** – In-memory session tracking with fallback to API šŸ”— **Rauth API Ready** – Built to connect seamlessly with the Rauth.io platform 🟪 **TypeScript Native** – Full TypeScript typings included for modern development --- ## Installation ```bash npm install rauth-provider ``` --- ## Quick Start (Hybrid ESM + CommonJS) ### ESM / TypeScript (Recommended) ```js import { RauthProvider } from 'rauth-provider'; RauthProvider.init({ rauth_api_key: process.env.RAUTH_API_KEY, app_id: process.env.RAUTH_APP_ID, webhook_secret: process.env.RAUTH_WEBHOOK_SECRET, }); app.post('/rauth/webhook', RauthProvider.webhookHandler()); ``` ### CommonJS (Legacy Node.js) ```js const { RauthProvider } = require('rauth-provider'); RauthProvider.init({ rauth_api_key: process.env.RAUTH_API_KEY, app_id: process.env.RAUTH_APP_ID, webhook_secret: process.env.RAUTH_WEBHOOK_SECRET, }); app.post('/rauth/webhook', RauthProvider.webhookHandler()); ``` > **Note:** This package supports both ESM and CommonJS. The RauthProvider is a singleton object that maintains state across your application. --- ## Usage Examples ### ESM / TypeScript (Express + JWT + Webhook) ```ts import express from 'express'; import jwt from 'jsonwebtoken'; import { RauthProvider } from 'rauth-provider'; const app = express(); RauthProvider.init({ rauth_api_key: process.env.RAUTH_API_KEY!, app_id: process.env.RAUTH_APP_ID!, webhook_secret: process.env.RAUTH_WEBHOOK_SECRET!, }); // Webhook endpoint app.post('/rauth/webhook', RauthProvider.webhookHandler()); // Session verification endpoint app.post('/api/login', async (req, res) => { const { sessionToken, userPhone } = req.body; const isVerified = await RauthProvider.verifySession(sessionToken, userPhone); if (!isVerified) { return res.status(401).json({ error: 'Phone number not verified' }); } const jwtToken = jwt.sign({ userPhone, sessionToken }, process.env.JWT_SECRET!); res.json({ jwtToken }); }); // Protected route app.get('/api/protected', async (req, res) => { try { const jwtToken = req.headers.authorization?.replace('Bearer ', ''); const decoded = jwt.verify(jwtToken, process.env.JWT_SECRET!); const isRevoked = await RauthProvider.isSessionRevoked(decoded.sessionToken); if (isRevoked) { return res.status(401).json({ error: 'Session revoked. Please log in again.' }); } res.json({ message: 'Protected route accessed', user: decoded.userPhone }); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }); app.listen(3000, () => { console.log('Server running on port 3000'); }); ``` ### CommonJS (Express + JWT + Webhook) ```js const express = require('express'); const jwt = require('jsonwebtoken'); const { RauthProvider } = require('rauth-provider'); const app = express(); RauthProvider.init({ rauth_api_key: process.env.RAUTH_API_KEY, app_id: process.env.RAUTH_APP_ID, webhook_secret: process.env.RAUTH_WEBHOOK_SECRET, }); // Webhook endpoint app.post('/rauth/webhook', RauthProvider.webhookHandler()); // Session verification endpoint app.post('/api/login', async (req, res) => { const { sessionToken, userPhone } = req.body; const isVerified = await RauthProvider.verifySession(sessionToken, userPhone); if (!isVerified) { return res.status(401).json({ error: 'Phone number not verified' }); } const jwtToken = jwt.sign({ userPhone, sessionToken }, process.env.JWT_SECRET); res.json({ jwtToken }); }); // Protected route app.get('/api/protected', async (req, res) => { try { const jwtToken = req.headers.authorization?.replace('Bearer ', ''); const decoded = jwt.verify(jwtToken, process.env.JWT_SECRET); const isRevoked = await RauthProvider.isSessionRevoked(decoded.sessionToken); if (isRevoked) { return res.status(401).json({ error: 'Session revoked. Please log in again.' }); } res.json({ message: 'Protected route accessed', user: decoded.userPhone }); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }); app.listen(3000, () => { console.log('Server running on port 3000'); }); ``` --- ## API Reference ### RauthProvider.init(options) Initialize the RauthProvider with configuration options. ```js RauthProvider.init({ rauth_api_key: 'your-api-key', app_id: 'your-app-id', webhook_secret: 'your-webhook-secret', default_session_ttl: 900, // 15 minutes (optional) default_revoked_ttl: 3600, // 1 hour (optional) }); ``` ### RauthProvider.verifySession(sessionToken, userPhone) Verify if a session is valid and matches the phone number. ```js const isValid = await RauthProvider.verifySession('session-token', '+1234567890'); // Returns: Promise<boolean> ``` ### RauthProvider.isSessionRevoked(sessionToken) Check if a session has been revoked. ```js const isRevoked = await RauthProvider.isSessionRevoked('session-token'); // Returns: Promise<boolean> ``` ### RauthProvider.checkApiHealth() Check if the rauth.io API is reachable. ```js const isHealthy = await RauthProvider.checkApiHealth(); // Returns: Promise<boolean> ``` ### RauthProvider.webhookHandler() Returns Express middleware to handle webhook events. ```js app.post('/rauth/webhook', RauthProvider.webhookHandler()); ``` --- ## Environment Variables Create a `.env` file with the following variables: ```env RAUTH_API_KEY=your-rauth-api-key RAUTH_APP_ID=your-app-id RAUTH_WEBHOOK_SECRET=your-webhook-secret JWT_SECRET=your-jwt-secret ``` --- ## Error Handling The library provides detailed error messages: ```js try { RauthProvider.init({ // missing required fields }); } catch (error) { console.error(error.message); // "RauthProvider.init(): Missing required fields: rauth_api_key, app_id, webhook_secret" } ``` --- ## Hybrid Compatibility - **ESM/TypeScript:** Use named import (`import { RauthProvider } from 'rauth-provider';`). - **CommonJS:** Use require with destructuring (`const { RauthProvider } = require('rauth-provider');`). - RauthProvider is a singleton object that maintains state across your application.