رفتن به محتوا

ورود یکپارچه

ورود یکپارچه به یک ارائه‌دهندهٔ هویت (IdP) بیرونی اجازه می‌دهد تصمیم بگیرد چه کسی می‌تواند به سرور Control Center شما وارد شود. دو پروتکل پشتیبانی می‌شود — SAML 2.0 و OpenID Connect — و هر دو به یک جا می‌رسند: یک اعتبارنامهٔ تازه‌ساختهٔ دستگاه که در همهٔ مراحل بعدی از یک دعوت یا جفت‌سازی با QR قابل تشخیص نیست.

ورودهای SAML از طریق مرورگر انجام می‌شوند. IdP هیچ‌وقت اتصالی به سرور شما باز نمی‌کند؛ مرورگر کاربر همه‌چیز را حمل می‌کند:

browser ──> /saml/login ──> IdP ──POST SAMLResponse──> /saml/acs
│ verify
▼
provision user (maybe)
│
▼
browser handoff: device PSK in the URL
fragment (never a query parameter)

چون مرورگر حامل است، سروری پشت NAT برای ورود بدون مشکل کار می‌کند: localhost، LAN، Tailscale، VPN یا یک تونل همه جواب می‌دهند — فقط مرورگر کاربر باید به نشانی ACS برسد. رلهٔ WebSocket که کنترل از راه دور تلفن از آن استفاده می‌کند نمی‌تواند رفت‌وبرگشت HTTP را حمل کند؛ به همین دلیل نقطه‌های ورود SSO همیشه مبدأ HTTP سرور را هدف می‌گیرند.

OpenID Connect همین ساختار را با یک رفت‌وبرگشت authorization code و PKCE دنبال می‌کند؛ ادعاها روی TLS از نقطهٔ پایانی توکن صادرکننده خوانده می‌شوند، پس مرورگر اصلاً دادهٔ هویت را تأمین نمی‌کند.

Control Center مسئولیت را عمداً تقسیم می‌کند:

قطعه کجا چه چیزی را در اختیار دارد
کتابخانهٔ بومی cc_saml packages/cc_natives/native/saml/ تأیید XML-DSig، کانونیکال‌سازی، اعتبارسنجی پروفایل SAML — واگذارشده به crate ثابت‌شدهٔ saml با Rust خالص در پشت یک C ABI بی‌حالت
SamlService / OidcService cc_server_core وضعیت ورود (ردیاب‌های درخواست در انتظار، حذف تکراری بازپخش)، تنظیمات سیاست اعتبارسنجی، فراخوانی مشترک تأمین
SsoProvisioner cc_server_core یافتن یا ساختن کاربر، سنجاق‌کردن subject ارائه‌دهنده، اعطای عضویت زیر سیاست عضویت خودکار
ScimService cc_server_core سطح push مربوط به SCIM 2.0 (چرخهٔ عمر تأمین و لغو تأمین)
SsoSettingsService cc_server_core ردیف‌های اتصال ذخیره‌شده، اعمال مجدد زنده، توکن SCIM

عمداً هیچ جایگزین رمزنگاری SAML تمام‌Dart وجود ندارد: XML-DSig و کانونیکال‌سازی دست‌ساز دقیقاً همان جایی است که آسیب‌پذیری‌های signature wrapping زندگی می‌کنند؛ پس نبودِ کتابخانهٔ cc_saml هم ورود SAML و هم بالا آمدن سرور را رد می‌کند. کتابخانهٔ بومی عمداً بی‌حالت است — وضعیت میان درخواست‌ها در سرویس‌های Dart می‌ماند، یک‌بارمصرف و کوتاه‌عمر.

درون کتابخانهٔ بومی تأییدشده و سرویس، به ترتیب:

  1. امضای assertion (همیشه لازم؛ امضای پاکت پاسخ بسته به پیکربندی اختیاری است) — از نظر ساختاری در برابر signature wrapping مقاوم است، چون بار دادهٔ اعتبارسنجی‌شده به عنصر تأییدشده گره خورده،
  2. issuer با IdP پیکربندی‌شده مطابقت دارد،
  3. audience همین ارائه‌دهندهٔ سرویس را نام می‌برد،
  4. destination همان URL مربوط به ACS ماست،
  5. InResponseTo با یک AuthnRequest در انتظار که خودمان صادر کرده‌ایم مطابقت دارد (پاسخ‌های ناخواسته و آغازشده از IdP به‌طور پیش‌فرض خاموش هستند)،
  6. پنجره‌های lifetime در محدودهٔ انحراف ساعت می‌مانند (پیش‌فرض 90 ثانیه) و
  7. شناسهٔ assertion هرگز قبلاً دیده نشده باشد (کش بازپخش).

شکست‌ها به‌صورت کدهای نوع‌دار برمی‌گردند — signature، expired، audience، destination، issuer، request-match — و نقطه‌های پایانی با خطاهای عمومی پاسخ می‌دهند، تا مهاجم چیزی دربارهٔ این‌که چرا یک جعل شکست خورده یاد نگیرد.

اولین ورود SSO، subject تغییرناپذیر ارائه‌دهنده (issuer به‌علاوهٔ SAML NameID / OIDC sub یا SCIM externalId) را روی حساب سنجاق می‌کند. از آن پس، این subject است — نه ایمیل — که ورود را شناسایی می‌کند. اگر کسی بعداً همان ایمیل را از همان IdP یا IdP دیگری ارائه کند، حساب سنجاق‌شده او را رد می‌کند. همین است که نمی‌گذارد ایمیلی بازیافتی نزد یک ارائه‌دهنده به تصاحب حساب تبدیل شود.

تأمین JIT هنگام ورود رخ می‌دهد (SsoProvisioner). SCIM یک سطح push جداگانه است (ScimService) که همان subject را روی ردیف کاربر سنجاق می‌کند؛ عضویت‌های فضای کاری را اعطا نمی‌کند. لغو تأمین — SCIM active: false یا DELETE — اگر حساب مالک یک فضای کاری باشد رد می‌کند (اول انتقال دهید). در غیر این صورت، ابتدا هر اعتبارنامهٔ دستگاه را لغو می‌کند (نشست‌ها از طریق پایش دستگاه ظرف چند ثانیه می‌افتند)، هر عضویت فضای کاری را برمی‌دارد و حساب را غیرفعال مهر می‌زند. ردیف کاربر باقی می‌ماند: انتساب دائمی است. فعال‌سازی مجدد ورود را برمی‌گرداند اما هرگز عضویت‌ها را دوباره نمی‌دهد.

  • نگاشت گروه→نقش هنگام ورود انجام می‌شود بر پایهٔ ویژگی‌های SAML / ادعاهای OIDC — گروه‌های SCIM که push می‌شوند ذخیره نمی‌شوند.
  • نقش مالک از مسیر SSO قابل دسترسی نیست — نه به‌عنوان نقش پیش‌فرض و نه از طریق نگاشت گروه.
  • رلهٔ WebSocket هرگز کانال SSO نیست؛ تلفن‌هایی که سرور را فقط از طریق رله می‌بینند نمی‌توانند یک رفت‌وبرگشت مرورگری را با آن کامل کنند.