otp-service

שליחת קוד אימות במייל מהכתובת otp@ivr.top. הקוד נוצר אצלנו ומוחזר בתשובה, ואתם אחראים לשמור אותו ולאמת אותו מול המשתמש.

שליחת קוד

POST https://otp-verify-mmf.ivr.top/api/v1/otp/send

כותרות:

הקריאה חייבת להגיע מהשרת שלכם, מכתובת ה-IP שאושרה מראש.

גוף הבקשה:

שדה חובה ברירת מחדל תיאור
to כן כתובת המייל של המשתמש
appName לא IVR שם המותג. הנושא יהיה: Your <appName> verification code
action לא sign in הפעולה שבמייל: Use this code to <action>.
origin לא https://ivr.top כתובת האתר שלכם (https בלבד). מיועדת לקשירת הקוד לדומיין, וחשוב שתהיה הכתובת שבה המשתמש מזין את הקוד
expiryMinutes לא 10 תוקף הקוד בדקות (1 עד 60), מופיע בטקסט המייל

תשובה (200):

{
  "challengeId": "5d0ea1b1-01cd-40b2-ac62-d1660584ac5b",
  "code": "048291",
  "messageId": "<5d0ea1b1-...@ivr.top>",
  "expiresAt": "2026-10-28T12:41:25.802Z"
}

שגיאות:

קוד משמעות
400 קלט לא תקין (error אומר איזה שדה)
401 טוקן חסר או שגוי
403 הקריאה לא מגיעה מ-IP מורשה
502 השליחה נכשלה. אין קוד בתשובה, אפשר לנסות שוב
const res = await fetch('https://otp-verify-mmf.ivr.top/api/v1/otp/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'X-API-Token': process.env.OTP_API_TOKEN },
  body: JSON.stringify({ to: email, appName: 'Acme', action: 'sign in to Acme', origin: 'https://app.acme.com' }),
});
if (!res.ok) throw new Error(`otp send failed: ${res.status}`);
const { challengeId, code, expiresAt } = await res.json();

אימות מול הלקוח (הדפדפן או האפליקציה)

השירות רק שולח את הקוד, ולכן האימות עצמו נעשה בשרת שלכם:

  1. אחרי הקריאה ל-API שמרו אצלכם challengeId, hash של code (למשל SHA-256), expiresAt ומונה ניסיונות.
  2. החזירו ללקוח רק את challengeId, לעולם לא את code. הקוד שחוזר מהשירות מיועד לשרת שלכם בלבד, ואם תעבירו אותו לדפדפן כל אחד יוכל לעקוף את האימות.
  3. הלקוח שולח לשרת שלכם את challengeId ואת הקוד שהמשתמש הקליד.
  4. השרת שלכם בודק: לא פג תוקף, לא עברו 3 עד 5 ניסיונות, וה-hash תואם (בהשוואה crypto.timingSafeEqual). בהצלחה מוחקים את הרשומה, כך שקוד עובד פעם אחת בלבד.
  5. את challengeId ואת הקוד שולחים ב-body של בקשת POST, לא ב-URL.

שדה הקלט בלקוח. התכונה autocomplete="one-time-code" גורמת ל-iOS, ל-Safari, ל-Chrome ולמנהלי סיסמאות להציע את הקוד מהמייל בלחיצה:

<input
  type="text"
  inputmode="numeric"
  autocomplete="one-time-code"
  maxlength="6"
  pattern="\d{6}"
  name="otp_code"
  required
/>

באפליקציית iOS נייטיב משתמשים ב-textContentType = .oneTimeCode, ובאנדרואיד נייטיב ב-autofillHints="smsOTP".

מה המשתמש יקבל

מייל באנגלית מ-otp@ivr.top: הקוד בשורה הראשונה, אחריו משפט הפעולה, התוקף והערת אבטחה. אפשר לבקש קוד חדש בכל עת, וכל קריאה יוצרת קוד חדש ו-challengeId חדש. כדאי להגביל בצד שלכם את קצב הבקשות לכל משתמש, כי השירות לא מגביל קצב.