One-Time Password Authentication
One-Time Password (OTP) authentication provides a passwordless login flow where users receive a temporary code via email.
Basic Usage
The context API provides two main methods for OTP authentication:
// Request an OTP code
const otpData = api.requestOTP(email)
// Sign in with the OTP code
const authData = api.signInWithOTP(otpData.otpId, code)
Implementation Example
Here's a complete OTP login implementation:
<<%='script server'%>>
let error = null
let otpId = request.body().otpId || null
const { mode, otpCode, identity } = {
mode: 'otp-request',
...request.body()
}
if (request.method === 'POST') {
switch (mode) {
case 'otp-request':
try {
const res = requestOTP(identity)
otpId = res.otpId
} catch (e) {
error = e.message
}
break
case 'otp-confirm':
try {
const res = signInWithOTP(otpId, otpCode)
redirect('/', {
message: 'Login successful'
})
} catch (e) {
error = e.message
}
break
}
}
</script>
<% if (error) { %>
<mark><%= error %></mark>
<% } %>
<% if (!otpId) { %>
<!-- Step 1: Request OTP -->
<h3>Request OTP Code</h3>
<form method="post">
<input type="hidden" name="mode" value="otp-request" />
<label>Email</label>
<input name="identity" required type="email" />
<button type="submit">Send OTP Code</button>
</form>
<% } else { %>
<!-- Step 2: Verify OTP -->
<h3>Enter OTP Code</h3>
<p>Please check your email for the OTP code and enter it below.</p>
<form method="post">
<input type="hidden" name="mode" value="otp-confirm" />
<input type="hidden" name="otpId" value="<%= otpId %>" />
<input type="hidden" name="identity" value="<%= identity %>" />
<input type="text" name="otpCode" placeholder="Enter OTP code" required />
<button type="submit">Verify & Login</button>
</form>
<!-- Allow requesting a new code -->
<form method="post">
<input type="hidden" name="mode" value="otp-request" />
<input type="hidden" name="identity" value="<%= identity %>" />
<button type="submit">Resend OTP code</button>
</form>
<% } %>
API Reference
requestOTP()
requestOTP(
email: string,
options?: {
collection?: string // defaults to "users"
}
): OTPResponse
The requestOTP()
method:
- Creates a temporary user if one doesn't exist
- Generates and sends an OTP code via email
- Returns an OTP response containing the OTP ID
signInWithOTP()
signInWithOTP(
otpId: string,
code: string,
options?: {
collection?: string // defaults to "users"
}
): AuthData
The signInWithOTP()
method:
- Validates the OTP code
- Authenticates the user
- Sets the
pb_auth
cookie - Returns the auth data containing the token and user record
Configuration
Enable OTP authentication in the PocketBase Admin UI:
- Go to Settings > Auth Options
- Enable "Allow authentication with password"
- Configure your SMTP settings in Settings > Mail Settings
Error Handling
Common OTP errors to handle:
- Invalid email address
- Invalid or expired OTP code
- Rate limiting errors
- SMTP configuration errors
Always wrap OTP operations in try/catch blocks and provide clear error messages to users.
Security Considerations
- Implement rate limiting for OTP requests
- Set appropriate OTP expiration times
- Use secure email delivery
- Consider implementing account lockout after failed attempts
- Log and monitor OTP usage patterns