Email Code Authentication
Overview
Email Code authentication sends a one-time verification code to the user’s email address. The user enters the code to complete authentication — no password needed.
This is a two-step flow:
- Send — The app requests a code be sent to an email address
- Verify — The user enters the received code, and the SDK verifies it with the server
Send Code
Request a verification code:
if (error) { console.error('Failed to send code:', error.message); return;}
console.log('Code sent successfully');// data: { expiresIn: 600, codeLength: 6 }Send Options
interface EmailCodeSendOptions { /** Code format preference */ format?: 'numeric' | 'alphanumeric';}Rate Limiting
The server enforces rate limits on code sending. If a code was recently sent to the same email, the SDK provides helper methods:
// Check if a code is already pending console.log(`Code already sent. Wait ${remaining}s before resending.`);}Verify Code
After the user receives the code, verify it:
const { data, error } = await auth.emailCode.verify( '123456');
if (error) { console.error('Verification failed:', error.message); return;}
console.log('Authenticated:', data.user);console.log('Session:', data.session);Verify Options
interface EmailCodeVerifyOptions { /** Verification context */ context?: 'login' | 'signup';}Pending Verification Helpers
The SDK tracks pending verification state in memory:
// Check if verification is pending for an email
// Get remaining time until code expires (seconds)
// Clear pending state (e.g., when user wants to change email)These helpers are useful for building UI that shows a countdown timer or prevents premature resending.
Error Handling
Common email code errors:
| Error Code | Meaning | User Action |
|---|---|---|
AR002001 | Invalid email format | Show validation message |
AR002002 | Rate limit exceeded | Show countdown timer |
AR002003 | Code expired | Offer to resend |
AR002004 | Invalid code | Allow retry (limited attempts) |
AR002005 | Too many failed attempts | Wait and try again later |
const { data, error } = await auth.emailCode.verify(email, code);
if (error) { switch (error.code) { case 'AR002003': showMessage('Code expired. Sending a new one...'); await auth.emailCode.send(email); break; case 'AR002004': showMessage('Incorrect code. Please try again.'); break; case 'AR002005': showMessage('Too many attempts. Please wait a moment.'); break; default: showMessage(error.message); }}Complete Example
A full two-step email code login flow:
import { createAuthrim } from '@authrim/web';
const auth = await createAuthrim({ issuer: 'https://auth.example.com', clientId: 'my-app',});
let currentEmail = '';
// Step 1: Send codedocument.getElementById('send-btn').addEventListener('click', async () => { const email = document.getElementById('email-input').value;
const { data, error } = await auth.emailCode.send(email); if (error) { alert(error.message); return; }
currentEmail = email; // Switch UI to code input document.getElementById('email-form').style.display = 'none'; document.getElementById('code-form').style.display = 'block';});
// Step 2: Verify codedocument.getElementById('verify-btn').addEventListener('click', async () => { const code = document.getElementById('code-input').value;
const { data, error } = await auth.emailCode.verify(currentEmail, code); if (error) { alert(error.message); return; }
// Authenticated window.location.href = '/dashboard';});
// Back button (change email)document.getElementById('back-btn').addEventListener('click', () => { auth.emailCode.clearPendingVerification(currentEmail); document.getElementById('code-form').style.display = 'none'; document.getElementById('email-form').style.display = 'block';});With Countdown Timer
async function sendCode(email) { const { data, error } = await auth.emailCode.send(email); if (error) return;
// Start countdown const timer = setInterval(() => { const remaining = auth.emailCode.getRemainingTime(email); if (remaining <= 0) { clearInterval(timer); document.getElementById('resend-btn').disabled = false; document.getElementById('countdown').textContent = ''; } else { document.getElementById('countdown').textContent = `Resend in ${remaining}s`; document.getElementById('resend-btn').disabled = true; } }, 1000);}Next Steps
- Passkey Authentication — WebAuthn-based passwordless login
- Social Login — Third-party identity providers
- Session Management — Working with sessions after login
- Error Handling — Comprehensive error handling guide