توضیح‌نامه‌ی ۰۸

ورود با جمهور

نخستین بار که تراز، سونمای مدنی یا هر پلتفرم دیگری که با جمهور یکپارچه شده را باز می‌کنید، ایمیلی تایپ نمی‌کنید. رمز عبوری انتخاب نمی‌کنید. شماره‌ی تلفنی نمی‌دهید. یک کد QR را با کیف پول جمهور اسکن می‌کنید، یک صفحه‌ی رضایت را تایید می‌کنید، و وارد شده‌اید.

«ورود با جمهور» یک سامانه‌ی SSO مبتنی بر OAuth2 است — از نظر شکل شبیه «ورود با گوگل» — اما با سه تفاوت عمدی: اعتبارنامه یک کیف پول روی گوشی شماست (که به‌دلخواه با یک هویت ZK مبتنی بر گذرنامه پشتیبانی می‌شود)، پلتفرم شریک هرگز نمی‌داند که شما در دیگر شرکا چه کسی هستید، و هیچ پایگاه داده‌ی متمرکزی برای احضار قضایی وجود ندارد.

دو لایه از کاربر جمهور

همه‌ی شرکای جمهور لازم نیست بدانند شما شهروند ایرانی‌اید. به همین دلیل، کیف پول دو حالت دارد و جریان SSO هر دو را پوشش می‌دهد:

نصب اپلیکیشن جمهور

کیف پول BabyJubjub به‌همراه تصدیق دستگاه ساخته می‌شود
  • کلید محلی روی دستگاه تولید می‌شود
  • App Attest / Play Integrity تایید می‌شود
  • هنوز نه گذرنامه‌ای، نه هویتی روی زنجیره

کاربر تصدیق‌شده

حالت پیش‌فرض پس از نصب
  • می‌تواند به شرکایی که شهروندی را لازم ندارند وارد شود
  • به‌ازای هر شریک یک موضوع زوجی ps_… می‌گیرد
  • بسته به دستگاه، در برابر مزارع ربات مقاوم است
  • به شرکایی که zk_required = true دارند نمی‌تواند وارد شود

کاربر دارای هویت ZK

پس از اسکن گذرنامه یا کارت ملی هوشمند
  • به همه‌ی شرکا، از جمله zk_required = true، وارد می‌شود
  • همان موضوع زوجی قبلی — ارتقا برای شرکای موجود ناپیداست
  • رای‌گیری روی زنجیره و ویژگی‌های شهروندی فعال می‌شود
  • تایید zk_verified به‌صورت زنده از /v1/tokens/validate بازمی‌گردد

چرا اهمیت دارد؟ بیش‌تر شرکا در واقع به ملیت نیاز ندارند. یک انجمن محله‌ای، اتحادیه‌ی مستأجران، صنف توسعه‌دهنده‌های نرم‌افزار، جامعه‌ی هواداران، گفت‌وگوی دارندگان بلیط یک رویداد — هیچ‌کدام لازم نیست بدانند شما ایرانی هستید. آن‌ها باید بدانند که همان انسان بازمی‌گردد، و این‌که ساختن حساب آن‌قدر پرهزینه باشد که مزرعه‌ی ربات نتواند آن‌ها را غرق کند. یک کیف پول تصدیق‌شده به‌تنهایی همین را می‌دهد. دروازه‌ی گذرنامه‌ی ZK روی آن قرار می‌گیرد، و وقتی شریک واقعن به آن نیاز داشته باشد در دسترس است.

از نگاه شریک، این کلید به اندازه‌ی یک boolean در کلاینت ثبت‌شده‌ی اوست: zk_required = true یا false. کیف پول آن را اعمال می‌کند؛ شرکا لازم نیست کد راستی‌آزمایی بنویسند.

چرا یک SSO ویژه‌ی جمهور لازم است

ورود، یکی از بزرگ‌ترین سطوح نظارت در اینترنت امروز است. هر دکمه‌ی «ورود با X» در سکوت یک حساب را به یک شماره‌ی تلفن، یک ایمیل، یک دستگاه و یک اثر انگشت رفتاری گره می‌زند که ارائه‌دهنده‌ی هویت سپس آن را می‌فروشد، نشت می‌دهد یا در پاسخ به درخواست تحویل می‌دهد. برای یک سکوی مدنی ایرانی، این از هر زاویه‌ای مدل تهدید اشتباهی است: حقوقی (کدام حوزه‌ی قضایی آن را ذخیره می‌کند)، تجاری (چه کسی از آن سود می‌برد)، و سیاسی (چه کسی می‌تواند افشای آن را الزامی کند).

پس جمهور ورود را به همان شکلی می‌سازد که رای‌گیری را:

دست‌دادن، از ابتدا تا انتها

کاربر

سایت شریک

  • «ورود با جمهور»
  • باز می‌کند /v1/authorize
  • PKCE code_challenge

کیف پول جمهور

  • nonce را امضا می‌کند (BabyJubjub)
  • App Attest / Play Integrity
  • صفحه‌ی رضایت
وارد شد

شریک یک JWT می‌گیرد با
sub = pairwise subject

آن‌چه شریک نمی‌داند:
نشانی کیف پول، گذرنامه یا اطلاعات شخصی

به‌طور مشخص، پشت آن یک ضربه‌ی انگشت، شش گام اتفاق می‌افتد:

  1. سایت شریک ← /v1/authorize. اپلیکیشن وب شریک کاربر را به sso.jomhoor.org/v1/authorize هدایت می‌کند (یا روی موبایل یک Universal Link باز می‌کند) همراه با client_id، redirect_uri، و یک code_challenge از نوع PKCE.
  2. sso-svc یک nonce صادر می‌کند و کاربر را از راه یک پیوند عمیق به کیف پول جمهور می‌فرستد.
  3. کیف پول دستگاه را تصدیق می‌کند. کیف پول Apple App Attest (روی iOS) یا Google Play Integrity (روی اندروید) را فرا می‌خواند تا اثبات کند درخواست از یک اپلیکیشن جمهور دست‌نخورده روی یک دستگاه روت‌نشده می‌آید. در نسخه‌ی تولیدی، این کار اجباری است.
  4. کاربر صفحه‌ی رضایت را می‌بیند — نام شریک، لوگوی شریک، و این‌که چه چیزی به اشتراک گذاشته می‌شود (هیچ چیز جز یک شناسه‌ی زوجی).
  5. کیف پول nonce را امضا می‌کند با کلید BabyJubjub کاربر و به /v1/authorize/verify POST می‌کند. sso-svc یک code یک‌بارمصرف بازمی‌گرداند.
  6. شریک کد را تبادل می‌کند در /v1/tokens/exchange (همراه با client_secret خود و code_verifier مربوط به PKCE) و یک JWT امضا‌شده دریافت می‌کند.

JWT واقعن چه چیزی را حمل می‌کند

JWT صادرشده به شریک

امضای sso-svc، ES256
  • sub — موضوع زوجی (ps_…)
  • client_id — این برای کدام شریک است
  • token_typeaccess یا refresh
  • iat، exp

درون توکن

  • موضوع زوجی
  • شناسه‌ی شریک
  • نوع توکن، بازه‌ی اعتبار

درون توکن نیست

  • نشانی کیف پول
  • کلید عمومی
  • داده‌ی گذرنامه / INID
  • ایمیل، تلفن، نام
  • پرچم zk_verified

موضوع زوجی به این شکل ساخته می‌شود: HMAC-SHA256(server_secret, walletID:clientID). یک کیف پول واحد در دو شریک متفاوت، دو رشته‌ی ps_… نامرتبط تولید می‌کند؛ حتی اگر دو شریک بخواهند تبانی کنند، نمی‌توانند پروفایل کاربر را ادغام کنند.

پرچم zk_verified عمدن درون توکن قرار داده نمی‌شود. اگر شریکی بخواهد وضعیت اعتماد را به‌صورت زنده بداند، در همان لحظه‌ای که اهمیت دارد /v1/tokens/validate را فرامی‌خواند — که نمایی تازه از {valid, subject, client_id, assertions} بازمی‌گرداند. این را به این دلیل انتخاب کردیم که لغو دسترسی و تغییر assertions بلافاصله اعمال شود، نه این‌که منتظر منقضی شدن توکن بمانیم.

چرا تصدیق اپلیکیشن اجباری است

کیف پول روی یک گوشی روت‌شده، کیف پولی است که می‌تواند در سکوت بیرون کشیده شود. کیف پول در یک نسخه‌ی دست‌کاری‌شده، کیف پولی است که می‌توان منطق تصدیق آن را دور زد. ما هر دو را رد می‌کنیم. در محیط تولیدی، sso-svc حتی شروع به کار نمی‌کند مگر این‌که تصدیق فعال باشد.

یعنی جمهور در حال حاضر نمی‌تواند کاربران را روی دستگاه‌های هواوی بدون Google Mobile Services، ROMهای سفارشی یا گوشی‌های جیلبریک‌شده وارد کند. می‌پذیریم که این یک محرومیت واقعی است. در مقابل، اعتمادی که به شرکا اعطا می‌کنیم بر چیزی استوارتر از «کیف پول می‌گوید» بنا شده.

برای شرکا — تکیه بر جمهور به نهادها چه می‌دهد

دروازه‌ی خود را انتخاب کنید. بیش‌تر شرکا با حالت پیش‌فرض کیف پول تصدیق‌شده کار می‌کنند؛ سکوهای مدنی که به شهروندی نیاز دارند پرچم zk_required = true را فعال می‌کنند. در هر دو حالت، SSO جمهور این‌ها را به شما می‌دهد:

چطور یکپارچه شویم

  1. سکوی خود را به‌عنوان یک sso_client ثبت کنید. ما client_secret شما را با bcrypt هش می‌کنیم، URLهای بازگشت، نام نمایشی، نشانی لوگو و پرچم zk_required شما را در یک ثبت کلاینت عمومی کوچک نگه می‌داریم. در GET /v1/clients/{id} در دسترس است — صفحه‌ی رضایت از روی همین رندر می‌شود.
  2. یک دکمه‌ی «ورود با جمهور» در صفحه‌ی ورود خود اضافه کنید. این دکمه /v1/authorize را با client_id، redirect_uri و یک code_challenge از نوع PKCE فرامی‌خواند (base64url بدون padding، S256).
  3. در callback، code را با client_secret و code_verifier منطبق در /v1/tokens/exchange تبادل کنید. یک توکن دسترسی و یک توکن نوسازی دریافت می‌کنید.
  4. هر زمان به بررسی زنده‌ی وضعیت اعتماد نیاز داشتید، /v1/tokens/validate را فرابخوانید.

یکپارچه‌سازی‌های مرجع، متن‌باز هستند: تراز (شاخه‌ی مشورت مبتنی بر Agora) و سونمای مدنی. پروتکل، OAuth2 استاندارد auth-code + PKCE است؛ اگر «ورود با گوگل» را یکپارچه کرده‌اید، این را هم می‌توانید.

این SSO چه چیزی نیست

چه چیزی را هنوز حل نکرده‌ایم

یک شکاف صادقانه باقی مانده است:

  1. حاکمیت ریشه‌ی اعتماد. ریشه‌ی ICAO که اثبات‌های گذرنامه‌ی ما در برابر آن بررسی می‌شوند، هنوز در StateKeeper راریمو زندگی می‌کند. M6 (در توضیح‌نامه‌ی ۰۶ پوشش داده شده) آن را زیر کلیدهای ادمین جمهور می‌آورد. تا فرود M6، عمیق‌ترین لایه‌ی اعتماد زیر SSO از سوی شخص دیگری اداره می‌شود.

ارتقای ZK هنگام ورود و بازیابی مبتنی بر nullifier (M5) در ۱۸ مه ۲۰۲۶ به تولید رسید: شرکایی که zk_required=true دارند، پیش از صفحه‌ی رضایت یک اثبات تازه‌ی query-proof از INID می‌طلبند، و کاربری که کیف پول را دوباره نصب کرده، می‌تواند با اثبات همان nullifier، موضوع‌های زوجی پیشین خود را دوباره به کیف پول تازه بچسباند — پس شناسه‌های به‌ازای هر شریک، بدون افشای گذرنامه‌ی زیرین، از پاک‌شدن دستگاه جان به در می‌برند.

تا بسته‌شدن حاکمیت ریشه‌ی اعتماد، «ورود با جمهور» در حال حاضر خصوصی‌ترین راه ورود به یک سکوی مدنی روی اینترنت آزاد است: بدون رمز عبور، بدون ایمیل، بدون شماره‌ی تلفن، بدون شناسه‌ی بین‌سایتی، و بدون پایگاه داده‌ی متمرکزی که توقیف شود. هر چه فراتر از این، تکرار و بهبود است.

پایان مجموعه

این آخرین متن در مجموعه‌ی توضیح‌نامه‌هاست. اگر از ۰۱ تا ۰۸ را خوانده‌اید، اکنون درباره‌ی کارکرد واقعی جمهور بسیار بیش‌تر از بیش‌تر کسانی که درباره‌اش نوشته‌اند می‌دانید.

اگر چیزی در این‌جا اشتباه، نامفهوم یا اغراق‌شده است، لطفن در مخزن کد issue یا PR باز کنید. صداقت درباره‌ی محدودیت‌ها، پیش‌شرط اعتماد درباره‌ی قوت‌هاست.


→ بازگشت به اسناد · ← قبلی: پشته‌ی حاکمیتی و M6