Web SDK
@quickauth/web — phone OTP, WhatsApp OTP, and marketing attribution for any JavaScript app. 3.6 KB gzipped, zero runtime dependencies, ESM + CJS + UMD builds.
Install
npm install @quickauth/webInitialize
Call init once on app boot. Pass an onTokenExpirycallback that returns a short-lived QuickAuth session JWT (your backend mints this via POST /v1/sdk/session), and an onAuthEvent handler that receives the typed lifecycle events the SDK emits.
import { QuickAuth } from '@quickauth/web'
QuickAuth.init({
// Returns a fresh session JWT from your backend. The SDK auto-refreshes
// ~30s before expiry, so this is called rarely.
onTokenExpiry: async () =>
(await fetch('/api/quickauth-token').then(r => r.json())).sessionToken,
// Single typed event stream the SDK pushes lifecycle events into.
onAuthEvent: (event) => {
switch (event.type) {
case 'OTP_SENT': showOtpInput(); break
case 'OTP_AUTO_READ': prefillInput(event.code); break
case 'VERIFIED': finishLogin(event.requestId); break // covers OneTap silent re-auth too
case 'OTP_FAILED': showError(event.message); break
case 'ERROR': showError(event.message); break
}
},
})Consent (DPDP / GDPR)
By default, the SDK refuses to send identifiable fields (phone, fingerprint, attribution params) until you call consent.set(true).
// Once the user accepts your cookie / privacy banner:
QuickAuth.consent.set(true)
// Read state any time:
const ok = QuickAuth.consent.get() // boolean
// React to changes (e.g. revoke flow):
QuickAuth.consent.subscribe((granted) => {
console.log('Consent now:', granted)
})Headless flow
Two methods. initiate kicks off the auth attempt; submitOtp hands back the user-typed code. All outcomes arrive as typed events on the onAuthEvent handler you registered at init — including the OneTap silent re-auth path, where the backend recognises the trusted device and emits VERIFIED without ever sending an OTP.
// Step 1 — kick off the attempt. Returns a promise that resolves once the
// network call dispatched; lifecycle events arrive via onAuthEvent.
await QuickAuth.auth.initiate({
phone: '+919876543210',
channel: 'auto', // 'auto' | 'sms' | 'whatsapp'
})
// → onAuthEvent fires with one of:
// { type: 'OTP_SENT', sessionId, channel, expiresIn } // show OTP input
// { type: 'VERIFIED', requestId } // OneTap fired
// { type: 'ERROR', code, message } // transport failure
// Step 2 — when OTP_SENT fires and the user types a code:
await QuickAuth.auth.submitOtp('123456')
// → onAuthEvent fires with:
// { type: 'VERIFIED', requestId, message } // forward requestId to your backend
// { type: 'OTP_FAILED', message } // wrong code, retry allowed
// { type: 'ERROR', code, message }
// On user-initiated logout, drop the device-trust token so the next session
// behaves like a brand-new install (no OneTap):
QuickAuth.auth.reset({ forgetDevice: true })OneTap is automatic
When OneTap is enabled for your merchant and the device has previously verified successfully, initiate emits VERIFIED directly — no SMS sent, no OTP screen needed. Your onAuthEvent handler simply jumps to the logged-in state. Switch on event type; you don't need to check any implementation-specific flag.
SMS auto-fill (WebOTP API)
On Android Chrome, an SMS that includes the WebOTP origin annotation gets auto-detected and inserted into a properly-tagged input. The SDK ships a tiny helper that wires the browser API to your callback:
// Subscribe once your OTP input is mounted.
QuickAuth.auth.observeOTP({
onCode: (code) => {
// Auto-fill your input and (optionally) auto-submit.
document.querySelector('#otp').value = code
},
})iOS auto-fill is browser-native
Safari on iOS recognises OTP messages automatically through autocomplete="one-time-code" on the input — no JS needed. The SDK helper above is a no-op on iOS; it only activates the WebOTP API on supported Chromium browsers.
WhatsApp OTP
Skip OTP entirely for users on WhatsApp — the SDK opens a wa.me chat with a one-tap verification message, then catches the return URL.
await QuickAuth.auth.startWhatsAppLogin({
businessNumber: '+919574980048',
returnURL: 'https://app.example.com/wa-return',
})
// In your /wa-return route, capture the launch params:
await QuickAuth.attribution.captureLaunch() // reads window.locationAttribution & conversions
// Call once per session — captures qa_clid / UTM / referrer / fingerprint
// (consent-gated).
await QuickAuth.attribution.captureLaunch()
// Track a conversion when the user completes value-bearing action:
await QuickAuth.attribution.trackConversion({
event: 'signup',
value: 0,
currency: 'INR',
metadata: { plan: 'free' },
})API reference
| Method | Description |
|---|---|
init(config) | Initialize the SDK. Call once on app boot. |
consent.set(granted) | Set consent state. Booleans only. |
consent.get() | Read current consent state. |
consent.subscribe(cb) | Listen to consent changes. Returns an unsubscribe fn. |
auth.initiate({ phone, channel }) | Begin an auth attempt. Emits OTP_SENT or VERIFIED via onAuthEvent. |
auth.submitOtp(code) | Submit the user-typed code. Emits VERIFIED or OTP_FAILED. |
auth.reset({ forgetDevice }) | Reset the state machine. Pass forgetDevice: true on logout to drop the OneTap trust token. |
auth.observeOTP({ onCode }) | WebOTP API hook. Also surfaces auto-read codes as OTP_AUTO_READ events. |
auth.startWhatsAppLogin(params) | Open wa.me login chat. |
attribution.captureLaunch() | Read URL params + fingerprint and POST to attribution. |
attribution.trackConversion(params) | Mark a conversion event. |
Source & changelog
Source: github.com/quickauthin/quickauth-sdk-web. Releases: GitHub Releases. Package: @quickauth/web on npm.