API Docs Security Widget Guide otp.royaltycoding.com
API Reference · v1.4

OTP Authentication Service

A standalone TOTP microservice with origin-based multi-tenancy, database-driven CORS, and fully configurable DDoS protection — all without touching your passwords or sessions.

RFC 6238 TOTP otp.royaltycoding.com application/json Express.js + MySQL DDoS Protected Web Component Widget v1.4

⚡ Integration Flow

🔑 What this API does
  • Generate TOTP secrets & QR codes per origin
  • Verify 6-digit codes at login
  • Enable and disable TOTP per user
  • Prevent replay attacks automatically
  • Block unknown origins at the CORS level
🏗️ What your system does
  • Authenticate users with email + password
  • Issue JWTs or sessions after login
  • Send requests with the correct Origin header
  • Pass tempToken = base64(email) to verify
  • Add your domain to allowed_origins table
Setup + Login Flow
1
Add your domain to allowed_origins
INSERT INTO allowed_origins (origin) VALUES ('https://myapp.com')
2
User enables 2FA → gets QR code
POST /auth/totp/setup → returns secret + qrCode
3
User scans QR in authenticator app
POST /auth/totp/verify-setup → TOTP activated
4
User logs in — your system checks password
Generate tempToken = btoa(email) server-side
5
User enters 6-digit code
POST /auth/totp/verify → login complete

📷 How to Scan the QR Code

1
Download an Authenticator App
Install one of the apps listed below — Google Authenticator, Authy, Microsoft Authenticator, 1Password, or Aegis are all compatible.
2
Call /auth/totp/setup
POST with user email. Response includes qrCode (base64 PNG data URI) and secret for manual entry. Render as: <img src="{qrCode}"/>
3
Tap "Add Account" in Your App
Google Authenticator → + icon → Scan a QR code
Authy → + → Scan QR Code
Microsoft Authenticator → + → Other account
1Password → Edit item → Add one-time password field → scan QR
Aegis → + → Scan QR code
4
Point Camera at QR Code
The app auto-detects the QR and adds a new 6-digit code that rotates every 30 seconds.
💡 Can't scan? Tap "Enter setup key" / "Manual entry" and paste the secret value instead.
5
Confirm with /auth/totp/verify-setup
Enter the 6-digit code from the app and call POST /auth/totp/verify-setup. On success, TOTP is active for this (email, origin) pair.
💡 Codes expire every 30 s — the window accepts the previous period too for clock drift.

📱 Recommended Authenticator Apps

All standard TOTP apps (RFC 6238) are compatible. These are the most widely used and trusted options:

Tip: If you use a password manager like 1Password or Bitwarden, you can store your TOTP secret alongside your passwords — no separate app needed. Bitwarden also has a free built-in authenticator available at bitwarden.com/products/authenticator.
🔑
API Token Authorization: Bearer <token>
All API calls require a valid token. Create one via /admin/tokens. See docs →

📋 Endpoints

POST /auth/totp/setup Generate TOTP secret & QR code
Parameters
Responses
Try It

Generates a TOTP secret + QR code. Auto-creates the user (email, origin) if they don't exist. The origin is taken from the request Origin header — not the body.

NameTypeRequiredSourceDescription
AuthorizationstringrequiredheaderBearer <token> — API token created via /admin/tokens.
emailstringrequiredbodyUser email — shown as the account label in the authenticator app.
OriginstringrequiredheaderSet automatically by the browser. Must be in allowed_origins. Stored on the user record for multi-tenancy.
200Secret and QR generated
"secret": "JBSWY3DPEHPK3PXP", "qrCode": "data:image/png;base64,...", "otpauthUrl": "otpauth://totp/..."
403Origin not in whitelist
"error": "Forbidden", "message": "Origin \"...\" is not allowed."
429Rate limit exceeded
"error": "Too Many Requests"
400Missing email
"error": "Missing required fields: email"
// Origin header sent automatically by browser
···
POST /auth/totp/verify-setup Confirm QR scan & enable TOTP
Parameters
Responses
Try It

Confirms the user scanned the QR. TOTP is only active after this succeeds. Lookup is by (email, origin).

NameTypeRequiredSourceDescription
AuthorizationstringrequiredheaderBearer <token> — API token created via /admin/tokens.
emailstringrequiredbodyUser email.
tokenstringrequiredbody6-digit code currently shown in the authenticator app.
OriginstringrequiredheaderSent automatically by browser.
200TOTP enabled
"success": true, "message": "TOTP enabled successfully!"
400Setup not started or wrong code
"error": "Invalid code. Try again."
429Rate limit
"error": "Too Many Requests"
// 6-digit code from authenticator app
···
POST /auth/totp/verify Validate TOTP code at login
Parameters
Responses
Try It

tempToken = base64(email). Generated server-side after your password check. JS: btoa(email). PHP: base64_encode($email).

NameTypeRequiredSourceDescription
AuthorizationstringrequiredheaderBearer <token> — API token created via /admin/tokens.
tempTokenstringrequiredbodyBase64-encoded email. Produced server-side after successful password check.
tokenstringrequiredbody6-digit TOTP code from the user's authenticator app.
OriginstringrequiredheaderSent automatically by browser. Scopes user lookup to this origin.
200Authentication complete
"success": true, "user": { "email": "user@example.com" }
401Replay attack blocked
"error": "Code already used. Wait for a new one."
401Invalid code
"error": "Invalid or expired code"
404User not found
"error": "User not found"
429Rate limit exceeded
"error": "Too Many Requests", "message": "Too many code verification attempts. Please wait before retrying."
403Origin not allowed
"error": "Forbidden"
// Auto base64-encoded as tempToken
···
POST /auth/totp/disable Remove TOTP from account
Parameters
Responses
Try It

Disables TOTP on the (email, origin) account. Requires a valid current code to prevent unauthorised removal.

NameTypeRequiredSourceDescription
AuthorizationstringrequiredheaderBearer <token> — API token created via /admin/tokens.
emailstringrequiredbodyUser email.
tokenstringrequiredbodyCurrent 6-digit TOTP code to confirm this action.
OriginstringrequiredheaderSent automatically by browser.
200TOTP disabled
"success": true, "message": "TOTP disabled."
401Wrong code
"error": "Invalid code"
404User not found
"error": "User not found"
429Rate limit
"error": "Too Many Requests"
···