Skip to content

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:

  1. Send — The app requests a code be sent to an email address
  2. Verify — The user enters the received code, and the SDK verifies it with the server

Send Code

Request a verification code:

const { data, error } = await auth.emailCode.send('[email protected]');
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
if (auth.emailCode.hasPendingVerification('[email protected]')) {
const remaining = auth.emailCode.getRemainingTime('[email protected]');
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
auth.emailCode.hasPendingVerification('[email protected]'); // boolean
// Get remaining time until code expires (seconds)
auth.emailCode.getRemainingTime('[email protected]'); // number
// Clear pending state (e.g., when user wants to change email)
auth.emailCode.clearPendingVerification('[email protected]');

These helpers are useful for building UI that shows a countdown timer or prevents premature resending.

Error Handling

Common email code errors:

Error CodeMeaningUser Action
AR002001Invalid email formatShow validation message
AR002002Rate limit exceededShow countdown timer
AR002003Code expiredOffer to resend
AR002004Invalid codeAllow retry (limited attempts)
AR002005Too many failed attemptsWait 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 code
document.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 code
document.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