توضیحنامهی ۰۸
ورود با جمهور
نخستین بار که تراز، سونمای مدنی یا هر پلتفرم دیگری که با جمهور یکپارچه شده را باز میکنید، ایمیلی تایپ نمیکنید. رمز عبوری انتخاب نمیکنید. شمارهی تلفنی نمیدهید. یک کد 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» در سکوت یک حساب را به یک شمارهی تلفن، یک ایمیل، یک دستگاه و یک اثر انگشت رفتاری گره میزند که ارائهدهندهی هویت سپس آن را میفروشد، نشت میدهد یا در پاسخ به درخواست تحویل میدهد. برای یک سکوی مدنی ایرانی، این از هر زاویهای مدل تهدید اشتباهی است: حقوقی (کدام حوزهی قضایی آن را ذخیره میکند)، تجاری (چه کسی از آن سود میبرد)، و سیاسی (چه کسی میتواند افشای آن را الزامی کند).
پس جمهور ورود را به همان شکلی میسازد که رایگیری را:
- اعتبارنامه روی گوشی کاربر تولید میشود — یک کیف پول BabyJubjub هنگام نصب اپلیکیشن، که وقتی یک شریک به ملیت نیاز داشته باشد بهدلخواه با یک اثبات ZK گذرنامهی بیومتریک ایرانی یا کارت ملی هوشمند ارتقا مییابد.
- شناسهای که به هر شریک داده میشود زوجی است — همان کاربر در شرکای متفاوت، شناسههایی که از نظر ریاضی بههم متصلشدنی نیستند.
- سرویس ورود (
sso-svc) دادهی گذرنامه، نشانی کیف پول یا اطلاعات شخصی را ذخیره نمیکند — و JWT صادرشده نیز هیچکدام را حمل نمیکند.
دستدادن، از ابتدا تا انتها
سایت شریک
- «ورود با جمهور»
- باز میکند
/v1/authorize - PKCE
code_challenge
کیف پول جمهور
- nonce را امضا میکند (BabyJubjub)
- App Attest / Play Integrity
- صفحهی رضایت
شریک یک JWT میگیرد باsub = pairwise subject
آنچه شریک نمیداند:
نشانی کیف پول، گذرنامه یا اطلاعات شخصی
بهطور مشخص، پشت آن یک ضربهی انگشت، شش گام اتفاق میافتد:
- سایت شریک ←
/v1/authorize. اپلیکیشن وب شریک کاربر را بهsso.jomhoor.org/v1/authorizeهدایت میکند (یا روی موبایل یک Universal Link باز میکند) همراه باclient_id،redirect_uri، و یکcode_challengeاز نوع PKCE. sso-svcیک nonce صادر میکند و کاربر را از راه یک پیوند عمیق به کیف پول جمهور میفرستد.- کیف پول دستگاه را تصدیق میکند. کیف پول Apple App Attest (روی iOS) یا Google Play Integrity (روی اندروید) را فرا میخواند تا اثبات کند درخواست از یک اپلیکیشن جمهور دستنخورده روی یک دستگاه روتنشده میآید. در نسخهی تولیدی، این کار اجباری است.
- کاربر صفحهی رضایت را میبیند — نام شریک، لوگوی شریک، و اینکه چه چیزی به اشتراک گذاشته میشود (هیچ چیز جز یک شناسهی زوجی).
- کیف پول nonce را امضا میکند با کلید BabyJubjub کاربر و به
/v1/authorize/verifyPOST میکند.sso-svcیکcodeیکبارمصرف بازمیگرداند. - شریک کد را تبادل میکند در
/v1/tokens/exchange(همراه باclient_secretخود وcode_verifierمربوط به PKCE) و یک JWT امضاشده دریافت میکند.
JWT واقعن چه چیزی را حمل میکند
JWT صادرشده به شریک
امضایsso-svc، ES256
sub— موضوع زوجی (ps_…)client_id— این برای کدام شریک استtoken_type—accessیاrefreshiat،exp
درون توکن
- موضوع زوجی
- شناسهی شریک
- نوع توکن، بازهی اعتبار
درون توکن نیست
- نشانی کیف پول
- کلید عمومی
- دادهی گذرنامه / INID
- ایمیل، تلفن، نام
- پرچم
zk_verified
موضوع زوجی به این شکل ساخته میشود: HMAC-SHA256(server_secret, walletID:clientID). یک کیف پول واحد در دو شریک متفاوت، دو رشتهی ps_… نامرتبط تولید میکند؛ حتی اگر دو شریک بخواهند تبانی کنند، نمیتوانند پروفایل کاربر را ادغام کنند.
پرچم zk_verified عمدن درون توکن قرار داده نمیشود. اگر شریکی بخواهد وضعیت اعتماد را بهصورت زنده بداند، در همان لحظهای که اهمیت دارد /v1/tokens/validate را فرامیخواند — که نمایی تازه از {valid, subject, client_id, assertions} بازمیگرداند. این را به این دلیل انتخاب کردیم که لغو دسترسی و تغییر assertions بلافاصله اعمال شود، نه اینکه منتظر منقضی شدن توکن بمانیم.
چرا تصدیق اپلیکیشن اجباری است
کیف پول روی یک گوشی روتشده، کیف پولی است که میتواند در سکوت بیرون کشیده شود. کیف پول در یک نسخهی دستکاریشده، کیف پولی است که میتوان منطق تصدیق آن را دور زد. ما هر دو را رد میکنیم. در محیط تولیدی، sso-svc حتی شروع به کار نمیکند مگر اینکه تصدیق فعال باشد.
- iOS: Apple App Attest. باینری اپلیکیشن را در برابر شناسهی بستهی امضاشده از سوی اپل بررسی میکند و دستگاههای جیلبریکشده را رد میکند.
- اندروید: Google Play Integrity. امضای APK، وضعیت بوتلودر، و اینکه دستگاه از Play Protect عبور میکند را تایید میکند.
- حالت شکست: کیف پول یک صفحهی «دستگاه پشتیبانی نمیشود» نمایش میدهد و از ورود ابتدایی خودداری میکند. این پاسخ درست است؛ باگ نیست.
یعنی جمهور در حال حاضر نمیتواند کاربران را روی دستگاههای هواوی بدون Google Mobile Services، ROMهای سفارشی یا گوشیهای جیلبریکشده وارد کند. میپذیریم که این یک محرومیت واقعی است. در مقابل، اعتمادی که به شرکا اعطا میکنیم بر چیزی استوارتر از «کیف پول میگوید» بنا شده.
برای شرکا — تکیه بر جمهور به نهادها چه میدهد
دروازهی خود را انتخاب کنید. بیشتر شرکا با حالت پیشفرض کیف پول تصدیقشده کار میکنند؛ سکوهای مدنی که به شهروندی نیاز دارند پرچم zk_required = true را فعال میکنند. در هر دو حالت، SSO جمهور اینها را به شما میدهد:
- یک حساب به ازای هر دستگاه، نه به ازای هر ایمیل. موضوع زوجی کیف پول به این معناست که یک کاربر واحد نمیتواند در سکوی شما دو حساب در سکوت بسازد. با
zk_required = true، یکتایی قویتر است: یک گذرنامه، یک حساب. - هیچ اطلاعات شخصیای برای ذخیره، نشت، یا تحویل قضایی. پایگاه دادهی شما رشتههای
ps_…را نگه میدارد. حتی اگر سکوی شما توقیف شود، این رشتهها به کیف پول یا گذرنامه قابل ردیابی نیستند. - عدم پیوند میان شرکا. حتی اگر دو پلتفرم شریک هر دو با جمهور یکپارچه شوند، یک کاربر واحد دو موضوع نامرتبط میگیرد — برای حریم خصوصی مفید است و سقف سختی برای نقشههای دلالهای داده میگذارد.
- انتخاب سطح اعتماد.
zk_required = falseرا برای انجمنهای عمومی که فقط به مقاومت در برابر سیبیل از راه تصدیق دستگاه نیاز دارند بگذارید؛zk_required = trueرا برای همهپرسی، مجمع شهروندی، سکوی مشورت، یا هر چیزی که حقوقن به ملیت ایرانی راستیآزماییشده نیاز دارد. - ارتقای جزییات ZK (نقطهی عطف ۵). برای شرکایی که به چیزی بیشتر از «ایرانی راستیآزماییشده» نیاز دارند — مثلن «ایرانی راستیآزماییشده، زن، بین ۱۸ تا ۳۵ سال، که در این همهپرسی هرگز رای نداده» — کیف پول میتواند هنگام ورود یک اثبات ZK تازه تولید کند.
چطور یکپارچه شویم
- سکوی خود را بهعنوان یک
sso_clientثبت کنید. ماclient_secretشما را با bcrypt هش میکنیم، URLهای بازگشت، نام نمایشی، نشانی لوگو و پرچمzk_requiredشما را در یک ثبت کلاینت عمومی کوچک نگه میداریم. درGET /v1/clients/{id}در دسترس است — صفحهی رضایت از روی همین رندر میشود. - یک دکمهی «ورود با جمهور» در صفحهی ورود خود اضافه کنید. این دکمه
/v1/authorizeرا باclient_id،redirect_uriو یکcode_challengeاز نوع PKCE فرامیخواند (base64url بدون padding، S256). - در callback،
codeرا باclient_secretوcode_verifierمنطبق در/v1/tokens/exchangeتبادل کنید. یک توکن دسترسی و یک توکن نوسازی دریافت میکنید. - هر زمان به بررسی زندهی وضعیت اعتماد نیاز داشتید،
/v1/tokens/validateرا فرابخوانید.
یکپارچهسازیهای مرجع، متنباز هستند: تراز (شاخهی مشورت مبتنی بر Agora) و سونمای مدنی. پروتکل، OAuth2 استاندارد auth-code + PKCE است؛ اگر «ورود با گوگل» را یکپارچه کردهاید، این را هم میتوانید.
این SSO چه چیزی نیست
- یک سرویس پروفایل نیست. هیچ endpoint از نوع
/userinfoوجود ندارد که نام، ایمیل یا آواتار برگرداند. ما این دادهها را نداریم. - سرویس خروج یکپارچه نیست. خروج از یک شریک شما را از سایرین خارج نمیکند. هر نشست مختص به شریک خود است.
- سرویس امانتدار کیف پول نیست.
sso-svcهرگز کلید کیف پول شما را نمیبیند. اگر کیف پول را دوباره نصب کنید، گذرنامهی خود را از نو میخوانید و سازوکار بازیابی با اثبات همان nullifier، موضوعهای زوجی پیشین بهازای هر شریک را به کیف پول تازه میچسباند — خودِ گذرنامه هرگز افشا نمیشود. - فدراتیو نیست. دیگر ارائهدهندگان هویت نمیتوانند بهجای شما «به جمهور وارد شوند». زنجیرهی اعتماد در گذرنامه و تصدیق دستگاه شما به پایان میرسد.
چه چیزی را هنوز حل نکردهایم
یک شکاف صادقانه باقی مانده است:
- حاکمیت ریشهی اعتماد. ریشهی ICAO که اثباتهای گذرنامهی ما در برابر آن بررسی میشوند، هنوز در
StateKeeperراریمو زندگی میکند. M6 (در توضیحنامهی ۰۶ پوشش داده شده) آن را زیر کلیدهای ادمین جمهور میآورد. تا فرود M6، عمیقترین لایهی اعتماد زیر SSO از سوی شخص دیگری اداره میشود.
ارتقای ZK هنگام ورود و بازیابی مبتنی بر nullifier (M5) در ۱۸ مه ۲۰۲۶ به تولید رسید: شرکایی که zk_required=true دارند، پیش از صفحهی رضایت یک اثبات تازهی query-proof از INID میطلبند، و کاربری که کیف پول را دوباره نصب کرده، میتواند با اثبات همان nullifier، موضوعهای زوجی پیشین خود را دوباره به کیف پول تازه بچسباند — پس شناسههای بهازای هر شریک، بدون افشای گذرنامهی زیرین، از پاکشدن دستگاه جان به در میبرند.
تا بستهشدن حاکمیت ریشهی اعتماد، «ورود با جمهور» در حال حاضر خصوصیترین راه ورود به یک سکوی مدنی روی اینترنت آزاد است: بدون رمز عبور، بدون ایمیل، بدون شمارهی تلفن، بدون شناسهی بینسایتی، و بدون پایگاه دادهی متمرکزی که توقیف شود. هر چه فراتر از این، تکرار و بهبود است.
پایان مجموعه
این آخرین متن در مجموعهی توضیحنامههاست. اگر از ۰۱ تا ۰۸ را خواندهاید، اکنون دربارهی کارکرد واقعی جمهور بسیار بیشتر از بیشتر کسانی که دربارهاش نوشتهاند میدانید.
اگر چیزی در اینجا اشتباه، نامفهوم یا اغراقشده است، لطفن در مخزن کد issue یا PR باز کنید. صداقت دربارهی محدودیتها، پیششرط اعتماد دربارهی قوتهاست.