Playground API
DocsStatsBlogStudio
Documentation Tree
Technical BlogFeature Deep Dives
  • Introduction
  • Quickstart
    5 min
  • How It Works
  • Recipes & Cookbooks
  • Platform Comparisons
  • Real-World Showcase
  • Interactive Studio
    Studio
  • GraphiQL IDE
    IDE
  • Session Quotas & Activity
  • Network Chaos Simulator
  • Atomic Sandbox Reset
  • Overview & Models
    Hub
  • Users Resource
  • Posts Resource
  • Comments Resource
  • Todos Resource
  • Custom Collections
    Custom
  • Multipart File Uploads
    Upload
  • Dynamic SVG Avatars
    SVG
  • Image Thumbnails
    CDN
  • Relational Filtering
  • Full-Text Search
  • Dynamic Sorting
  • Offset Pagination
  • Cursor Pagination
    Scroll
  • CSV & Excel Export & Import
    IO
  • Custom Collections
    CRUD
  • Overview & Architecture
    Hub
  • JWT Auth Flow
  • Refresh Token Rotation
    Mutex
  • RBAC Permission Matrix
    Roles
  • Expiry Simulation
  • Clock Skew Drift
  • Password Recovery Loop
  • Dual-Mode Sandboxing
  • GraphiQL IDE
    IDE
  • Relational Queries
  • Stateful Mutations
  • Realtime Subscriptions
  • Overview & Flowcharts
    Hub
  • Hosted Checkout
    Stripe
  • Payment Intents API
  • 3DS Challenge Modal
    Modal
  • Customers Vault
  • Charges & Refunds
  • Test Cards Catalog
  • Overview & Channels
    Hub
  • Virtual Email Mailbox
    Mailtrap
  • Virtual SMS Terminal
    Phone
  • In-App Notifications
  • Message Dispatcher
  • Realtime Studio
    Studio
  • Native WebSocket (/ws)
  • Socket.io Gateway
  • Presence & Echo Bot
  • Server-Sent Events (SSE)
    SSE
  • Analytics Telemetry
  • Webhook Subscriptions
  • HMAC SHA-256 Signatures
  • Delivery Logs
  • Manual Retry Simulator
  • Network Latency Delay
  • HTTP Status Codes
  • Rate-Limit Simulator
    429
  • Flaky Network & Jitter
    Chaos
  • Session Quotas & Activity
  • JSON Snapshots
    JSON
  • Headless CI/CD Testing
    CI
  • Mobile QR Code Sync
  • System Metrics & Health
  • Atomic Sandbox Reset
  • Official TypeScript SDK
  • Multi-Language Generators
  • DevTools Extension
  • OpenAPI 3.1 Spec
    JSON
  • Postman Collection v2.1
  • Bruno Collection
  • Insomnia Workspace
  • TypeScript .d.ts
    .d.ts
  • AI Prompt Rules
    Rules
  • Context Index (llms.txt)
  • Full Schema (llms-full.txt)
  • Manifest (product.json)
  • All Feature Articles
    Blog
  • React CRUD Without Backend
    Deep Dive
  • Why Static APIs Fail
  • Mocking Stateful Auth
  • WebSockets & SSE Guide
Technical Blog
Articles

In-depth articles explaining stateful mock APIs, WebSockets, payments, and frontend resilience.

Read Articles
PreviousClock Skew Drift
NextDual-Mode Sandboxing
Auth & Security

Password Recovery & Reset Loop

Test end-to-end account recovery flows with real-time virtual email delivery. Initiating a password reset triggers an authentic HTML recovery email delivered straight into your isolated Virtual Mailbox without third-party email service credentials.

End-to-End Recovery Flow

Execute the complete password reset lifecycle in 3 intuitive steps:

1

Step 1: Request Recovery Link (/auth/forgot-password)

Submits the user email address. The backend generates a secure single-use recovery token and renders an email:

Dispatch Reset Link to admin@example.com

POST
response.json
1
{
2
// Click "Send" above to execute this request against the live server.
3
}
2

Step 2: Inspect Dispatched Email in Virtual Inbox

Navigate to the virtual mailbox to view the rendered HTML email template, extract the recovery token, or copy the direct password reset URL.

Open Virtual Mailbox (/docs/inbox/email-mailbox)
3

Step 3: Submit New Password (/auth/reset-password)

Submits the reset token from the email along with the updated password:

Complete Password Reset

POST
response.json
1
{
2
// Click "Send" above to execute this request against the live server.
3
}

Recovery Security Best Practices

Critical defensive patterns modeled by the Playground API authentication gateway:

01

Email Enumeration Defense

The /auth/forgot-password endpoint returns HTTP 200 regardless of whether the email exists, preventing user enumeration.

02

Strict Token Expiration

Reset tokens expire after 15 minutes. Once consumed to update a password, the token is permanently invalidated.

03

Automatic Session Invalidation

Upon successful password reset, all existing refresh token families and active sessions are revoked across all client devices.

Frontend Recovery Recipes

Production-ready React 19 hooks and Next.js Server Action patterns:

passwordRecovery.ts
1
// React 19 Custom Password Reset Hook
2
import { useState } from 'react';
3
4
export function usePasswordRecovery() {
5
const [loading, setLoading] = useState(false);
6
const [status, setStatus] = useState<'idle' | 'email_sent' | 'reset_success' | 'error'>('idle');
7
const [errorMessage, setErrorMessage] = useState('');
8
9
// 1. Initiate password reset (sends email to virtual mailbox)
10
const requestReset = async (email: string) => {
11
setLoading(true);
12
setErrorMessage('');
13
try {
14
const res = await fetch('https://playground.nileslabs.com/api/v1/auth/forgot-password', {
15
method: 'POST',
16
headers: { 'Content-Type': 'application/json' },
17
body: JSON.stringify({ email }),
18
});
19
20
if (!res.ok) throw new Error('Password reset request failed');
21
setStatus('email_sent');
22
} catch (err: any) {
23
setErrorMessage(err.message);
24
setStatus('error');
25
} finally {
26
setLoading(false);
27
}
28
};
29
30
// 2. Submit new password with received token
31
const completeReset = async (token: string, newPassword: string) => {
32
setLoading(true);
33
setErrorMessage('');
34
try {
35
const res = await fetch('https://playground.nileslabs.com/api/v1/auth/reset-password', {
36
method: 'POST',
37
headers: { 'Content-Type': 'application/json' },
38
body: JSON.stringify({ token, new_password: newPassword }),
39
});
40
41
if (!res.ok) throw new Error('Invalid or expired reset token');
42
setStatus('reset_success');
43
} catch (err: any) {
44
setErrorMessage(err.message);
45
setStatus('error');
46
} finally {
47
setLoading(false);
48
}
49
};
50
51
return { requestReset, completeReset, loading, status, errorMessage };
52
}