احراز هویت

صفحات احراز هویت در قالب، رابط کامل و رفتار واقعی دارند اما به بک‌اند وصل نیستند. این بخش توضیح می‌دهد چه چیزی آماده است و برای وصل شدن چه باید کرد.

صفحات موجود

صفحهمسیرنکته
ورودauth/login.htmlدو ستونه با پنل معرفی
ورود سادهauth/login-minimal.htmlبدون پنل کنار، تمرکز روی فرم
ورود دو ستونهauth/login-split.htmlچیدمان تبلیغاتی متفاوت
ثبت‌نامauth/register.htmlاعتبارسنجی کامل + قدرت گذرواژه
بازیابی گذرواژهauth/forgot-password.htmlارسال پیوند
بازنشانیauth/reset-password.htmlگذرواژه جدید + تکرار
تأیید ایمیلauth/verify-email.htmlکد ۶ رقمی (OTP)
ورود دو مرحله‌ایauth/two-factor.htmlکد برنامه احراز هویت
قفل صفحهauth/lock-screen.htmlباز کردن با گذرواژه
خروجauth/logout.htmlتأیید خروج
خطای ورودauth/error.htmlحالت خطا

همه صفحات از پوسته app-body--auth استفاده می‌کنند: بدون سایدبار، با دکمه‌های تم/جهت/زبان و میان‌بر «ورود به دمو».

چه چیزی واقعی کار می‌کند؟

  • اعتبارسنجی همه فیلدها (ایمیل، شماره، کد ملی، گذرواژه، تطابق تکرار)
  • ورودی‌های کد یک‌بار‌مصرف با پرش خودکار بین خانه‌ها و چسباندن کد
  • حالت بارگذاری دکمه و پیام‌های موفقیت/خطا
  • انتقال به داشبورد پس از موفقیت (شبیه‌سازی‌شده)
  • محدودسازی و دکمه‌های «ورود با گوگل/گیت‌هاب» که در دمو پیام اطلاع می‌دهند

وصل کردن به API واقعی

  1. یک سرویس احراز هویت بسازید:
// src/services/auth.service.js
import { call } from './client.js';

export const authService = {
  login: (credentials) => call('post', 'auth/login', { body: credentials, resolver: () => ({ token: 'demo', user: { name: 'سارا محمدی' } }) }),
  register: (payload) => call('post', 'auth/register', { body: payload }),
  forgot: (email) => call('post', 'auth/forgot', { body: { email } }),
  verify: (code) => call('post', 'auth/verify', { body: { code } }),
  logout: () => call('post', 'auth/logout'),
};
  1. در src/js/pages/content.js داخل initAuth()، هندلر submit را به آن وصل کنید:
const { authService } = await import('../../services/auth.service.js');

on($('[data-auth-form]', node), 'submit', async (event) => {
  event.preventDefault();
  const form = event.currentTarget;
  const button = $('[data-submit]', form);
  button.classList.add('is-loading');
  try {
    const session = await authService.login(collectValues(form));
    localStorage.setItem('nova:token', session.token);
    window.location.assign('dashboards/analytics.html');
  } catch (error) {
    toast.danger('ورود ناموفق', error.message);
  } finally {
    button.classList.remove('is-loading');
  }
});
  1. توکن را در client.js به هدرها اضافه کنید:
const headers = { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) };
  1. برای مسیرهای محافظت‌شده، در بالای main.js بررسی کنید که توکن وجود دارد و در غیر این صورت به auth/login.html هدایت کنید. (در نسخه دمو، این بررسی غیرفعال است تا همه صفحات آزادانه قابل مشاهده باشند.)

نکات امنیتی

  • گذرواژه را هرگز در localStorage نگه ندارید؛ فقط توکن.
  • مسیرهای auth/* را در سمت سرور هم محافظت کنید.
  • برای کد یک‌بار‌مصرف، انقضا و تعداد تلاش را در سرور کنترل کنید.
  • در فرم‌های واقعی از CSRF token استفاده کنید.
نکته: قالب هیچ سرویس احراز هویت بیرونی نصب نمی‌کند (بدون Firebase/Supabase) تا انتخاب بک‌اند آزاد بماند
هشدار: در حالت دمو هیچ داده‌ای از کاربر ذخیره نمی‌شود؛ چیزی که وارد می‌کنید فقط در همان مرورگر و در حافظه صفحه می‌ماند

Authentication

The template's authentication pages have a complete UI and real behaviour, but they are not connected to a backend. This section explains what is ready and what you need to do to connect them.

Available pages

PagePathNotes
Sign inauth/login.htmlTwo columns with an intro panel
Minimal sign-inauth/login-minimal.htmlNo side panel, focused on the form
Split sign-inauth/login-split.htmlA different promotional layout
Sign upauth/register.htmlFull validation + password strength
Forgot passwordauth/forgot-password.htmlSends a link
Reset passwordauth/reset-password.htmlNew password + confirmation
Verify emailauth/verify-email.html6-digit code (OTP)
Two-factor sign-inauth/two-factor.htmlAuthenticator app code
Lock screenauth/lock-screen.htmlUnlock with password
Sign outauth/logout.htmlSign-out confirmation
Sign-in errorauth/error.htmlError state

All pages use the app-body--auth shell: no sidebar, with theme/direction/language buttons and a "Sign in to demo" shortcut.

What actually works?

  • Validation of every field (email, phone, national ID, password, matching confirmation)
  • One-time code inputs with automatic focus jumps between boxes and code pasting
  • Button loading state and success/error messages
  • Redirect to the dashboard after success (simulated)
  • Rate limiting and "Sign in with Google/GitHub" buttons that show an info message in the demo

Connecting to a real API

  1. Create an authentication service:
// src/services/auth.service.js
import { call } from './client.js';

export const authService = {
  login: (credentials) => call('post', 'auth/login', { body: credentials, resolver: () => ({ token: 'demo', user: { name: 'Sara Mohammadi' } }) }),
  register: (payload) => call('post', 'auth/register', { body: payload }),
  forgot: (email) => call('post', 'auth/forgot', { body: { email } }),
  verify: (code) => call('post', 'auth/verify', { body: { code } }),
  logout: () => call('post', 'auth/logout'),
};
  1. In src/js/pages/content.js, inside initAuth(), wire the submit handler to it:
const { authService } = await import('../../services/auth.service.js');

on($('[data-auth-form]', node), 'submit', async (event) => {
  event.preventDefault();
  const form = event.currentTarget;
  const button = $('[data-submit]', form);
  button.classList.add('is-loading');
  try {
    const session = await authService.login(collectValues(form));
    localStorage.setItem('nova:token', session.token);
    window.location.assign('dashboards/analytics.html');
  } catch (error) {
    toast.danger('Sign-in failed', error.message);
  } finally {
    button.classList.remove('is-loading');
  }
});
  1. Add the token to the headers in client.js:
const headers = { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) };
  1. For protected routes, check at the top of main.js that a token exists and otherwise redirect to auth/login.html. (In the demo build this check is lenient so every page can be browsed freely.)

Security notes

  • Never keep the password in localStorage; only the token.
  • Protect the auth/* routes on the server side too.
  • For one-time codes, enforce expiry and attempt limits on the server.
  • Use a CSRF token in real forms.
Tip: the template does not install any external authentication service (no Firebase/Supabase), so your choice of backend stays open
Warning: in demo mode no user data is stored; whatever you enter stays only in that browser and in the page's memory

المصادقة

لصفحات المصادقة في القالب واجهة كاملة وسلوك حقيقي، لكنها غير مرتبطة بواجهة خلفية. يشرح هذا القسم ما هو جاهز وما يجب فعله للربط.

الصفحات المتوفرة

الصفحةالمسارملاحظة
تسجيل الدخولauth/login.htmlعمودان مع لوحة تعريفية
دخول مبسّطauth/login-minimal.htmlبلا لوحة جانبية، التركيز على النموذج
دخول بعمودينauth/login-split.htmlتخطيط ترويجي مختلف
إنشاء حسابauth/register.htmlتحقق كامل + قوة كلمة المرور
استعادة كلمة المرورauth/forgot-password.htmlإرسال رابط
إعادة التعيينauth/reset-password.htmlكلمة مرور جديدة + تأكيدها
تأكيد البريدauth/verify-email.htmlرمز من ٦ أرقام (OTP)
الدخول بخطوتينauth/two-factor.htmlرمز تطبيق المصادقة
قفل الشاشةauth/lock-screen.htmlفتح بكلمة المرور
تسجيل الخروجauth/logout.htmlتأكيد الخروج
خطأ الدخولauth/error.htmlحالة الخطأ

تستخدم جميع الصفحات الهيكل app-body--auth: بلا شريط جانبي، مع أزرار السمة/الاتجاه/اللغة واختصار «الدخول إلى العرض التجريبي».

ما الذي يعمل فعلاً؟

  • التحقق من جميع الحقول (البريد، الرقم، الرقم الوطني، كلمة المرور، تطابق التأكيد)
  • حقول الرمز لمرة واحدة مع الانتقال التلقائي بين الخانات ولصق الرمز
  • حالة تحميل الزر ورسائل النجاح/الخطأ
  • الانتقال إلى لوحة التحكم بعد النجاح (محاكاة)
  • تحديد المحاولات وأزرار «الدخول بـ Google/GitHub» التي تعرض رسالة إعلامية في العرض التجريبي

الربط بـ API حقيقية

  1. أنشئ خدمة مصادقة:
// src/services/auth.service.js
import { call } from './client.js';

export const authService = {
  login: (credentials) => call('post', 'auth/login', { body: credentials, resolver: () => ({ token: 'demo', user: { name: 'سارا محمدي' } }) }),
  register: (payload) => call('post', 'auth/register', { body: payload }),
  forgot: (email) => call('post', 'auth/forgot', { body: { email } }),
  verify: (code) => call('post', 'auth/verify', { body: { code } }),
  logout: () => call('post', 'auth/logout'),
};
  1. في src/js/pages/content.js داخل initAuth()، اربط معالج الإرسال بها:
const { authService } = await import('../../services/auth.service.js');

on($('[data-auth-form]', node), 'submit', async (event) => {
  event.preventDefault();
  const form = event.currentTarget;
  const button = $('[data-submit]', form);
  button.classList.add('is-loading');
  try {
    const session = await authService.login(collectValues(form));
    localStorage.setItem('nova:token', session.token);
    window.location.assign('dashboards/analytics.html');
  } catch (error) {
    toast.danger('فشل تسجيل الدخول', error.message);
  } finally {
    button.classList.remove('is-loading');
  }
});
  1. أضف الرمز إلى الترويسات في client.js:
const headers = { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) };
  1. للمسارات المحمية، تحقّق في أعلى main.js من وجود الرمز وإلا فأعد التوجيه إلى auth/login.html. (في النسخة التجريبية هذا التحقق متساهل لتكون كل الصفحات قابلة للتصفح بحرية.)

ملاحظات أمنية

  • لا تحفظ كلمة المرور أبداً في localStorage؛ الرمز فقط.
  • احمِ مسارات auth/* من جهة الخادم أيضاً.
  • للرمز لمرة واحدة، تحكّم في مدة الصلاحية وعدد المحاولات على الخادم.
  • استخدم رمز CSRF في النماذج الحقيقية.
ملاحظة: لا يثبّت القالب أي خدمة مصادقة خارجية (بلا Firebase/Supabase) ليبقى اختيار الواجهة الخلفية حراً
تحذير: في الوضع التجريبي لا تُحفظ أي بيانات للمستخدم؛ ما تدخله يبقى في ذلك المتصفح وفي ذاكرة الصفحة فقط