CAS Development

از متن باز سامان - مدیریت دانش

معرفی

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

بسیاری از سازمانها جهت حل این مشکل از سرویس‌هایی بر پایه LDAP استفاده می‌کنند تا هویت کاربران یکپارچه شود و از تعدد نام کاربری و رمز عبور جلوگیری شود. کارکرد این سرویس نیازمند اتصال همه سامانه‌های نرم‌افزاری به پروتکل LDAP جهت احراز هویت هست. اگر چه مشکل تعدد نام کاربری حل می‌شود اما مشکل دیگری ایجاد می‌شود. تصور کنید که یک کاربر روزانه به ۱۰ سامانه نرم‌افزاری مختلف می‌خواهد متصل شود و رمز کاربر نیز پیچیده باشد. کاربر حداقل ۱۰ بار باید نام کاربری و رمز عبور خود را وارد کند تا بتواند از این سامانه‌ها استفاده کند. اگر این مقدار را با تعداد کابران محاسبه کنیم به حجم بسیار بالایی از ورود خواهیم رسید.

جهت سهولت در ورود و خروج کاربران از سامانه‌های مختلف و حل مشکل فوق، از سرویس‌های SSO یا یکبار ورود استفاده می‌شود. این سرویس‌ها پروتکل‌های مختلفی را اصولاً پوشش می‌دهند که شامل CAS, OAuth2, SAML و یا بصورت وب‌سرویس Restful خواهد بود. سامانه‌ها در صورتی که بر روی یک پروتکل مشترک احراز هویت را انجام دهند توسط Ticket صادره از سرویس SSO می‌توانند اعتبار ورود کاربر را بررسی نموده و در صورتی که ticket مربوطه هنوز معتبر باشد امکان و اجازه ورود کاربر را بدون وارد نمودن نام کاربر و رمز عبور بدهند. در هنگام خروج یک کاربر از یک سامانه نیز با استفاده از SLO یا یکبار خروج و اعلام آن به سرویس SSO می‌توان ticket مربوطه را بی‌اعتبار کرد و دسترسی کاربر از همه سامانه‌ها به جهت امنیت قطع خواهد شد.

در ادامه به نحوه چگونگی اتصال و اعتبارسنجی این سرویس می‌پردازیم.

پروتکل CAS

یکی از پروتکل‌هایی که برای تکنولوژی SSO استفاده می‌گردد، CAS نام دارد که مخفف Central Authentication Service هست. این پروتکل توسط شرکت Apereo ابداع شده است و برای زبانهای مختلف برنامه‌نویسی کتابخانه داشته و استفاده از آن سهولت زیادی نسبت به سایر پروتکل‌ها دارد که دلیل آن کتابخانه‌های خوبی هست که در سمت سرویس‌گیرنده فراهم شده است. کتابخانه‌های CAS محدود به زبانهای برنامه‌نویسی نیستند و در وب‌سرورهایی مانند Apache نیز این کتابخانه‌ها وجود دارند که به نام mod_auth_cas شناخته می‌شود و یا حتی در سیستم‌عامل لینوکس برای PAM نیز کتابخانه pam_cas وجود دارد.

برای دریافت این کتابخانه‌ها بسته به نوع زبان می‌توان از مسیر کلی https://github.com/apereo استفاده نمود. یا به عنوان نمونه طبق جدول زیر می‌توان کتابخانه‌ها را دریافت نمود. مستندات کامل هر کتابخانه نیز در آدرس مربوطه وجود دارد.

زبان برنامه‌نویسی دریافت کتابخانه سمت Client
Java https://github.com/apereo/java-cas-client
Net. https://github.com/apereo/dotnet-cas-client
PHP https://github.com/apereo/phpCAS
Python https://github.com/python-cas/python-cas

همچنین لازم به ذکر است که بسیاری از برنامه‌های متن‌باز مانند Drupal, Mediawiki و … بصورت پیش‌فرض از مدل احراز هویت مبتنی بر CAS استفاده می‌کنند و تنها تنظیماتی که در ادامه این سند ذکر می‌شود برای کارکرد آن‌ها کفایت می‌کند.

کارکرد CAS

در اینجا به نحوه کارکرد CAS می‌پردازیم. در ابتدا اشاره به این نکته ضروری است که سرویس SSO ممکن است به همه برنامه‌ها دسترسی بدهد یا آن‌ را محدود به آدرسهای خاصی کند. بر روی سرویس SSO که در اینجا گفته شده است، دسترسی به آدرسهای مشخصی محدود شده است. بنابراین اگر با خطای زیر مواجه شدید یعنی اینکه دسترسی برای شما برای service URL درخواست شده امکان‌پذیر نیست. در ادامه توضیحات بیشتری در مورد service URL ذکر خواهد شد.
CAS.jpg

در سمت سرویس مدیریت CAS دو نوع دسترسی اصولاً تعریف می‌شود. اول دسترسی اتصال به سرویس SSO و دوم هم سایر پارامترها و اطلاعاتی که از سمت این سرویس در مورد کاربر به درخواست کننده برگشت داده می‌شود.

در سرویس CAS سه قسمت اصلی وجود دارد:

  1. مرورگر کاربر
  2. نرم‌افزار تحت وب
  3. سرور SSO با پشتیبانی از CAS

مرورگر کاربر

مرورگر کاربر نقش ارتباطی از سمت کاربر را بر عهده دارد و ticket دریافت شده از سمت SSO در مرورگر کاربر ذخیره می‌شود و می‌تواند توسط سایر نرم‌افزارهای سازمان که به SSO متصل هستند، از این ticket جهت اعتبارسنجی نشست فعلی استفاده شود.

نرم‌افزار تحت وب

این نرم‌افزار به عنوان یک CAS client تنظیم شده و برای احراز هویت کاربر در صورت عدم وجود ticket در مرورگر به آدرس مشخصی هدایت می‌شود که بعد از ورود صحیح، کاربر مجدداً به صفحه مشخص شده توسط نرم‌افزار ارجاع داده می‌شود. (تقریباً مشابه آنچیزی که در زمان استفاده از کاربر گوگل برای احراز هویت در سایت‌های دیگر مشاهده می‌کنیم)

سرور SSO با پشتیبانی از CAS

این سرویس از قسمت‌های ذیل تشکیل شده است که به تکمیل این فرآیند کمک می‌کند:
  1. ارائه خدمات صفحه ورود و احراز هویت کاربر از یک منبع واحد (دیتابیس، LDAP و غیره)
  2. صدور کوکی TG [۱]جهت عدم نیاز به ورود مجدد کاربر در موارد بعدی که به سمت سرور CAS هدایت می‌شود (هر نرم‌افزار جهت کنترل اعتبار ورود کاربر، مرورگر را به سمت آدرس وب سرویس CAS هدایت میکند و در صورتی که تیکت کاربر معتبر باشد، مجدداً از سمت CAS کاربر به سامانه اصلی هدایت می‌شود. لذا در این فرآیند کاربری که قبلاً وارد شده است نیازی به ورود مجدد ندارد و متوجه این امر نخواهد شد و این همان سهولتی هست که در کنار امنیت برای کاربر به ارمغان می‌آید)
  3. امکان هدایت و برگشت به نرم‌افزار تحت وب با تنظیم ticket=ST-XXX در url مربوطه برای اینکه به عنوان CAS client بتواند تیکت را بررسی کند
  4. اعتبارسنجی تیکت صادر شده توسط کتابخانه CAS برای اطمینان نرم‌افزار از صحت ورود کاربر و اعتبار تیکت آن

نحوه اتصال با CAS

در شکل ذیل نحوه اتصال به سرویس CAS مشاهده می‌شود تا بتوانیم بهتر فرآیند آن را درک کنیم.
CAS2.jpg

برای مشاهده دیاگرام‌های دقیق‌تر و بهمراه کد‌های HTTP مربوطه می‌توان به لینک زیر مراجعه کرد

https://apereo.github.io/cas/5.2.x/protocol/CAS-Protocol.html

Initial request (مرحله یک)

  1. نرم‌افزار sampleapp به عنوان CAS client تنظیم شده است تا مثلاً روی آدرس test/ احراز هویت را انجام دهد.
  2. کاربر از طریق مرورگر به test/ متصل می‌شود.
  3. اگر مرورگر در حال حاضر بر روی نرم‌افزار sampleapp هیچ نشستی نداشته باشد، sampleapp کنترل را بدست کتابخانه CAS می‌دهد.
  4. اگر کتابخانه CAS پارامتر تیکت را در درخواست مشاهده نکند، کاربر را به صفحه ورود CAS هدایت می‌کند و در انتهای آن عبارت service=url_to_return_to را اضافه می‌کند که این مقدار برابر آدرسی هست که قرار هست بعد از ورود صحیح، کاربر مجدداً به سمت آن هدایت شود.در مثال مد نظر ما مثلاً آدرس http://localhost:8080/sampleapp/test خواهد بود که url نهایی به شکل ذیل هست:

https://accounts.example.com/cas/login?service=http://localhost:8080/sampleapp/test  

اگر این آدرس http://localhost:8080/sampleapp/test در سیستم مدیریت CAS به عنوان آدرس مجاز تعریف نشده باشد پیام Application Not Authorized to Use CAS دیده می‌شود. لذا حتماً بایستی آدرس مد نظر نرم‌افزار خود را به مدیر سیستم اعلام کنید تا در سرویس CAS تعریف شده و دسترسی شما مجاز باشد.

هدایت به صفحه ورود CAS (مرحله دو)

  1. کاربر به صفحه ورود CAS جهت احراز هویت انتقال داده می‌شود. فرم ورود مربوط به صفحه CAS روی مرورگر کاربر نمایش داده خواهد شد.
  2. در این مرحله کاربر می‌بایست نام کاربری و رمز عبور خود را واردکند. در سمت راست صفحه نیز نام و توضیحات برنامه‌ای که کاربر از آن به سمت صفحه ورود هدایت شده است نمایش داده می‌شود. مانند تصویر زیر:
    در تصویر فوق ما از نرم‌افزاری با عنوان CAS Management به این صفحه هدایت شده‌ایم. این موارد توسط مدیر سیستم به عنوان نام و توضیحات نرم‌افزار مجاز تعریف شده، تعیین می‌شود.
    تصویر صفحه ورود اصلی کاربران

بررسی TGT در مرورگر (مرحله سه)

  • در این مرحله مقدار CASTGC cookie که در سمت سرور با نام TGT تولید شده است چک می‌شود. اگر چنین مقداری در مرورگر در همان لحظه وجود داشته باشد، یعنی اینکه کاربر توسط CAS قبلاً احراز هویت شده است و از اینجا به مرحله شش خواهد رفت و به نرم‌افزار مجاز با مشخص نمودن مقدار service ticket برگشت داده خواهد شد.
  • اگر هیچ CASTGC وجود نداشته باشد، صفحه ورود CAS در مرورگر نمایش داده خواهد شد.

ارسال صفحه ورود به مرورگر توسط CAS (مرحله چهار)

یکی از خوبی‌های این قسمت این مسأله هست که برنامه‌ها نیازی به نمایش صفحه ورود به کاربرها ندارند و همه نرم‌افزارهای سازمان از یک صفحه ورود یکسان استفاده می‌کنند. مشابه آنچه در سیستم SSO گوگل با آدرس https://accounts.google.com مشاهده می‌کنید.
  • عدم نیاز به مدیریت صفحه ورود توسط هر نرم‌افزار
  • عدم نیاز به اتصال به سیستم‌های بانک اطلاعاتی و یا LDAP و غیره جهت احراز هویت توسط هر نرم‌افزار
  • عدم اطلاع از رمز عبور کاربر توسط هر نرم‌افزار. رمز وارد شده توسط کاربر فقط در اختیار مرورگر و سرویس CAS هست که امنیت بالاتری را خواهد داشت

ارسال اطلاعات ورود به سرویس CAS (مرحله پنج)

  • سرویس CAS اطلاعاتی که با متود POST توسط مرورگر به آن ارسال شده است را چک می‌کند و اگر احراز هویت انجام نشود مجدداً صفحه ورود را به کاربر نشان می‌دهد.
  • تعداد کمی احراز هویت اشتباه در زمان کوتاه باعث قف شدن کاربر می‌شود و سایر احراز هویت‌های بعدی تا ۱۵ دقیقه بدون موفقیت خواهد بود تا از حملات تحت وب جلوگیری شود.

برگشت کاربر به صفحه نرم‌افزار (مرحله شش)

  • یک ticket granting ticket که به آن TGT می‌گوییم و به عنوان نمونه مشابه رشته ذیل هست توسط سرویس CAS سمت سرور ذخیره خواهد شد و روی مرورگر نیز یک کوکی با نام CASTGC تنظیم می‌شود.
TGT-1-wKQjkOhweJE6MMTNCqTwv6WojMDBL61GISejnyCfigrMFCumYu-accounts.example.com*
  • یک service ticket صادر می‌شود و به عنوان یک پارامتر به آدرس نرم‌افزار ارائه شده در زمان هدایت به CAS برگشت داده می‌شود. (در مرحله یک توضیح داده شده است) این تیکت مشابه زیر خواهد بود. در این مثال فرض شده است که آدرس نرم‌افزار ما http://localhost:8080/sampleapp/test هست
ST-1-bdgbwHIReBonmaudvxJl-accounts.example.com

درخواست مجدد مرورگر برای اتصال به نرم‌افزار بهمراه CAS service ticket (مرحله هفت)

  • در حال حاضر هنوز نشست نرم‌افزار کامل برقرار نشده است. در این مرحله کتابخانه CAS وارد عمل کنترل می‌شود.
  • کتابخانه CAS پارامتر تیکت را در url مشاهده می‌کند و می‌تواند آن را با سرویس CAS چک کند.
  • CAS service ticket تنها یکبار معتبر خواهد بود و کتابخانه CAS می‌تواند از آن ظرف ۹۰ ثانیه استفاده کند و صحت آن را چک کند یا اینکه آن expire خواهد شد و عملیات مرحله شش دوباره می‌بایست انجام شود.

چک صحت CAS service ticket (مرحله هشت)

  • کتابخانه CAS برای چک کردن تیکت آماده می‌شود و درخواست زیر را به عنوان نمونه بر حسب آدرس نرم‌افزار ارسال می‌کند:
https://accounts.example.com/cas/p3/serviceValidate?ticket=ST-1-bdgbwHIReBonmaudvxJl-counts.example.com&service=http%3A%2F%2Flocalhost%3A8080%2Fsampleapp%2Ftest%2F  

در صورتی که این تیکت از سمت سرور CAS تأیید شود، کد ۲۰۰ به سمت مرورگر برگشت داده می‌شود.

جواب سرویس CAS به چک صحت ticket (مرحله نه)

  • در ذیل یک نمونه جواب CAS را مشاهده می‌کنیم. به مقادیر برگشت داده شده مانند email, lastname, firstname و غیره در تگ cas:attributes توجه کنید. این‌ها همان پارامترهایی از کاربر هستند که به نرم‌افزار مربوطه مجوز مشاهده آن‌ها داده شده است. لذا بسته به نیاز هر برنامه می‌بایست به مدیر سیستم درخواست دهید تا پارامترهای مورد نیاز را در سمت سیستم مدیریت CAS تعریف

کند.

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>mohsen</cas:user>
<cas:attributes>
<cas:email>ali@mbs.co.ir</cas:email>
<cas:lastname>Ahmadi</cas:lastname>
<cas:firstname>Ali</cas:firstname>
<cas:fullname>Ali Ahmadi</cas:fullname>
<cas:uid>1001</cas:uid>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>

ارسال صفحه نرم‌افزار (مرحله ده)

  • در این مرحله کاربر به صفحه نهایی هدایت می‌شود و می‌تواند از نرم‌افزار sampleapp استفاده کند.

تنظیمات CAS client

در کتابخانه‌های زبانهایی که برنامه CAS client را دارند، فایل تنظیماتی بسته به نوع زبان وجود دارد که آدرس سرویس‌دهنده و سایر پارامترهای مربوطه را می‌توان در آن تنظیم نمود. جهت این مسأله به مستندات کتابخانه CAS مربوطه می‌توان رجوع کرد. در زمان ارتباط با سرویس CAS اطلاعات مربوط به اتصال و آدرس آن توسط مدیر سیستم در اختیار شما قرار خواهد گرفت.

نحوه اتصال با RESTful

پروتکل REST این امکان را به سایر برنامه ها می دهد که به جای استفاده از پروتکلهای مورد پشتیبانی از وب سرویس با متود RESTful جهت ارتباط با سرویس SSO بهره بگیرند. این مسئله برای برنامک‌های بر روی گوشی‌های هوشمند هم مهم و حائز اهمیت هست.

در ذیل نحوه تعامل با این وب سرویس آورده شده است. بدیهی هست که آدرس دامنه سرویس دهنده هم باید لحاظ شود.

درخواست یک TGT

POST /cas/v1/tickets HTTP/1.0

username=a.ahmadi&password=password&additionalParam1=paramvalue

پاسخ موفق

201 Created
Location: http://accounts.mbsco.ir/cas/v1/tickets/{TGT  id}

پاسخ ناموفق

اگر اطلاعات احراز هویت صحیح نباشد، CAS با خطای 400 پاسخ می دهد و اگر درخواست به گونه‌ای ارسال شود که پشتیبانی نشود با خطای 415 پاسخ خواهد داد.

JWT Ticket Granting Tickets

TGT ای که توسط پروتکل REST ایجاد شده به عنوان JWT هم می‌تواند صادر شود. البته این قابلیت بایستی از سمت سرویس دهنده SSO فعال گردد و طبق سیاست سازمان انجام خواهد شد.

برای درخواست اعطای TGT به عنوان JWT بعدی ، مطمئن شوید که درخواست POST با موارد زیر مطابقت دارد. به گزینه token=true توجه کنید.

POST /cas/v1/tickets HTTP/1.0

username=battags&password=password&token=true&additionalParam1=paramvalue

پارامتر توکن به عنوان پارامتر درخواست یا یک هدر درخواست ارسال می شود. قسمت پاسخ شامل TGT به عنوان یک JWT خواهد بود. توجه داشته باشید که JWT ارسال شده، امضاء و رمزگذاری شده است.

درخواست یک Service Ticket

برای درخواست یک تیکت ST باید درخواستی با فرمت زیر ارسال کنید.

POST /cas/v1/tickets/{TGT id} HTTP/1.0

service={form encoded parameter for the service url}

پاسخ موفق اگر پاسخ موفقی دریافت کنید مطابق با الگوی زیر خواهد بود.

200 OK
ST-1-FFDFHDSJKHSDFJKSDHFJKRUEYREWUIFSD2132

اعتبار سنجی Service Ticket

اعتبار سنجی Service Ticket از طریق پروتکل CAS و با استفاده از آدرس p3/ServiceValidate/ استفاده می‌شود.

GET /cas/p3/serviceValidate?service={service url}&ticket={service ticket}

پاسخ ناموفق

CAS یک خطای 400 Bad Request ارسال می کند. اگر هم یک نوع درخواست نادرست ارسال شود خطای 415 Unsupported Media Type ارسال می کند.

logout

با حذف تیکت صادر شده، نشست SSO پایان می یابد.

DELETE /cas/v1/tickets/TGT-fdsjfsdfjkalfewrihfdhfaie HTTP/1.0

وضعیت تیکت

وضعیت تیکت را بررسی کنید و مطمئن شوید که هنوز معتبر است و منقضی نشده است.

GET /cas/v1/tickets/TGT-fdsjfsdfjkalfewrihfdhfaie HTTP/1.0

پاسخ موفق

200 OK

پاسخ ناموفق

404 NOT FOUND

متود users

از نسخه ۵.۳ به بعد می‌توانید با استفاده از یک متود و ارسال پارامترهای مورد نیاز مشخصه‌های کاربر را دریافت کنید:

POST /cas/v1/users HTTP/1.0

username=battags&password=password&token=true&service={service name}

یکبار خروج (SLO)

همانطور که کاربر یک بار در سرویس SSO ورود می‌کند و سپس در سایر سامانه ها بدون ورود مجدد، احراز خواهد شد، در زمان خروج نیز چنین عملی اتفاق خواهد افتاد. همانطور که می‌دانیم نشست ایجاد شده برای کاربر مختص هر سامانه هست و زمانی که کاربر از یک سامانه خارج می‌شود تنها نشست مربوط به همان سامانه از بین می‌رود و کاربر در سایر سامانه‌ها همچنان متصل باقی خواهد ماند. به طور بالقوه چندین برنامه به سرویس SSO متصل هستند و یک نشست داخلی برای کاربر دارند و تمایز بین خروج و خروج یکتا (SLO) براساس تعداد نشست‌هایی است که بر اساس یک عمل خروج به پایان می رسد.

این عملیات به نام SLO یا Single Logout خوانده می‌شود که در ادامه در مورد نحوه انجام آن توضیح خواهیم داد. بدیهی هست که همانطور که در زمان اتصال به SSO برای ورود کاربران سامانه‌ها باید در سمت خود تغییراتی را اعمال نمایند در این قسمت نیز این مسئله بایستی انجام شود.

نکته
دقت کنید که مطالب ذکر شده در این قسمت مربوط به پروتکل CAS هست و با توجه به اینکه پروتکل‌های دیگری مانند OAuth2, WS-Federation, OpenID, SAML, REST در این سرویس پشتیبانی می‌شوند، این مطالب صرفا مربوط به پروتکل CAS هست و سایر پروتکلهای رفتار و روش خود را دارند.


عملیات خروج

عملیات خروج در دو حالت رخ می‌دهد:

  1. خروج از یک برنامه متصل به SSO
  2. خروج مستقیم از سامانه SSO

در حالت عادی این خروج‌ها بر روی یکدیگر هیچ اثری ندارد و هر کدام مستقل هستند. اتمام نشست یک برنامه تاثیری روی نشست سامانه SSO ندارد. این مسئله یکی از دلایل اصلی سردرگمی کاربران جدید و توسعه‌دهندگان سیستم SSO است.

خروج یکباره در CAS تلاش می‌کند تا رابطه بین خروج برنامه و سامانه SSO را برقرار کند و آنها را هم نزدیک کند. هنگامی که CAS برای SLO پیکربندی شده است ، تلاش می کند تا برای هر برنامه ای که درخواست تأیید اعتبار به CAS را در طول جلسه SSO ارسال کرده است ، پیام های خروج را ارسال کند. یعنی درخواست خروج فقط برای سامانه‌هایی که قبلا در طول نشست کاربر در SSO یکبار عملیات تایید تیکت ST را انجام داده‌اند، ارسال می‌شود. پس اگر کاربری در طول آن نشست از سامانه‌هایی استفاده کرده باشد عملا درخواست خروجی هم برای آنها ارسال نمی‌شود. بصورت کلی این سیستم یک تلاش بسیار خوب جهت سازگار کردن خروج‌های کاربر بین سامانه SSO و کلیه‌های سامانه‌هایی هست که به SSO متصل هستند و نتیجه این عملیات رضایتمندی کاربر و سازمان را افزایش خواهد داد.

CAS Logout

برای پروتکل CAS آدرس logout/ مسئول تخریب نشست فعلی کاربر هست. بنابراین اگر کاربری آدرسی (با توجه به نام دامنه اصلی) مطابق نمونه زیر را وارد کند از CAS خارج می‌شود و Ticket او دیگر معتبر نخواهد بود.

https://accounts.mbsco.ir/cas/logout

در اینجا هم امکان برگشت به سامانه اصلی وجود دارد. مشابه زمانی که کاربر به CAS متصل می‌شود. این قابلیت باید بر روی سرویس دهنده فعال باشد. در صورتی که فعال باشد با اضافه نمودن پارامتر service در انتها و تعیین URL مربوطه این عمل انجام خواهد شد. لازم به ذکر است که این آدرس باید در سامانه SSO تعریف شده باشد تا قابل استفاده باشد.

همچنین در زمانی که یک TGT منقضی شود نیز مکانیزم SLO فراخوانی می‌شود. طبق این فرآیند یک notification به برنامه‌ها جهت از بین بردن نشست کاربر ارسال می‌شود و این مسئله محدود به همین هست. پس از اعلام notification به برنامه، این وظیفه آن هست که آن را پیگیری و به درستی نشست کاربر در داخل خودش را نابود کند.

از آنجایی که این عملیات بصورت فراگیر انجام می‌شود، لذا تمام برنامه‌هایی که به SSO متصل هستند و کاربر در آنها نشست فعال از طریق SSO دارد، مطلع می‌شوند و کاربر از آنها قطع خواهد شد. این مسئله می‌تواند منجر به نارضایتی کاربر شود با توجه به اینکه این برنامه‌ها رفتار مستقلی از یکدیگر دارند و شاید کاربر متوجه این موضوع نباشد.

روشهای SLO

از دو روش می‌توان جهت این عملیات استفاده نمود:

Back Channel

سرویس CAS یک درخواست HTTP POST مستقیما به سامانه مربوطه ارسال می‌کند. این روش قدیمی هست و در حال حاضر بهتر است از روش دوم استفاده شود. نمونه داده ارسال شده مشابه ذیل است:

<samlp:LogoutRequest
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    ID="[RANDOM ID]"
    Version="2.0"
    IssueInstant="[CURRENT DATE/TIME]">
    <saml:NameID>@NOT_USED@</saml:NameID>
    <samlp:SessionIndex>[SESSION IDENTIFIER]</samlp:SessionIndex>
</samlp:LogoutRequest>

Front Channel

در این روش CAS یک درخواست AJAX با روش GET و استفاده از فرمت داده JSONP به سامانه مربوطه ارسال می‌کند. رفتار مورد انتظار از هر سامانه غیر معتبر کردن نشست کاربر در همان سامانه هست.

نکته
این روش ممکن است که توسط تمامی سامانه ها قابل استفاده نباشد. البته این مسئله به تکنولوژی‌های مورد استفاده در آن سامانه بستگی دارد که آیا تکنولوژی به روز را پشتیبانی می‌کند یا خیر.

یک نمونه از این داده به شکل زیر است. منظور از service.url آدرس سامانه مورد نظر هست.

curl 'https://service.url?callback=jQuery112409319555380089843_1509437967792&logoutRequest=[BASE64 encoded request]&_=1509437967793'

به عنوان مثال اینجا از ابزار curl جهت call کردن آدرس مربوطه استفاده شده است.

درخواست SLO

این درخواست به URL معرفی شده برای هر سرویس که قسمت مدیریت سرویس‌ها در پنل مدیریت مرکزی SSO ارسال می‌شود. در مورد روش Back Channel مقدار session identifier همان مقدار service ticket ID (تیکت مختص به هر سامانه که در زمان اعتبارسنجی با ST شروع می‌شود) است. این تیکت اختصاصا برای هر سامانه در زمان اعتبار سنجی کاربر تولید می‌شود و یکبار مصرف هم هست. این مقدار برای تطبیق نشست کاربر در CAS با هر برنامه کاربرد دارد و به همین دلیل هم برای هر سامانه بصورت اختصاصی تولید شده است. بنابراین هر سامانه باید آخرین مقدار این تیکت را برای هر کاربر نگهداری کند تا بتواند تشخیص دهد که درخواست CAS مربوط به کدام کاربر هست. این تیکت می‌تواند در دیتابیس یا هر محلی که برنامه صلاح بداند ذخیره شود.

نکته
این قابلیت می‌تواند برای بعضی از سرویسها و برای بعضی دیگر غیرفعال باشد. این مسئله به سیاست‌گذاری سازمان سرویس گیرنده بستگی دارد.


تعریف Endpoint برای نشست‌های مشترک چند محصول

لزوما هر سامانه ممکن است مستقیم نخواهد از CAS استفاده کند و تمایلی به پیاده‌سازی مکانیزم logout نداشته باشد. بدین منظور برای سامانه‌هایی که می‌خواهند درخواست logout به سرویس دیگری ارسال شود این امکان وجود دارد. مثلا ممکن است چندین سامانه سرویس گیرنده از یک شرکت، نشست کاربر را بصورت مشترک استفاده می‌کنند و می‌خواهند یک نقطه واحد logout برای همه سامانه ها داشته باشند. در این صورت لازم هست که برای کلیه سامانه های آن شرکت یک آدرس جهت logout تعریف شود و CAS درخواست را به همان آدرس ارسال می‌کند.

SSO Session vs. Application Session

جهت درک بهتر موضوع مدیریت نشست‌ها در سمت سرویس دهنده SSO ذکر این نکته ضروری هست که نشست کاربر در برنامه سرویس گیرنده با نشست کاربر در سمت SSO کاملا متفاوت هست. نشست کاربر در سمت CAS توسط TicketGrantingTicket یا همان تیکت TGT کنترل می‌شود و TGT id از طریق یک secure cookie بین سرور CAS و مرورگر کاربر به اشتراک گذاشته می‌شود.

زمانی که تایید اعتبار کاربر از طریق یک سرویس انجام می‌شود دیگر CAS هیچ مسوولیتی نسبت به نشست کاربر در آن سامانه ندارد و هیچ ارتباطی تا زمان logout بین آنها وجود نخواهد داشت. بنابراین تمام سیاست‌های هر سامانه برای آن نشست به CAS وابستگی ندارد و خود سامانه مسوول آن هست. توجه داشته باشیم که یک سامانه مستقلا می‌تواند نشست یک کاربر را منقضی کند و مجددا کاربر را با یک تیکت ST جدید اعتبار سنجی کند اما بدیهی هست که تا زمانی که کاربر از CAS خارج نشده باشد این اعتبارسنجی با موفقیت همراه خواهد بود و صرفا یک تیکت ST جدید برای آن سامانه صادر می‌شود.

صحت اتصال سامانه‌ها به SSO

با توجه به اینکه در پیاده‌سازی مکانیزم‌های SSO (بدون در نظر گرفتن نوع پروتکل) جهت اتصال هر سامانه‌ به این سرویس، باید الزاماتی طبق استانداردهای احراز هویت برای برنامه‌های تحت وب انجام شود، در این بخش این موارد ذکر می‌شود. بدیهی هست که این موارد بر طبق استانداردهایی هست که برای احراز هویت برنامه‌های تحت بدون اتصال به SSO هم وجود دارد و جهت حفظ شرایط کارکردی و امنیتی باید در این نوع احراز هویت نیز پیاده‌سازی گردد.

نکته
در ادامه منظور از سامانه برنامه تحت وب مورد استفاده کاربر که به SSO متصل شده است،‌خواهد بود و سرویس SSO با عبارت «سرویس SSO» مشخص می‌شود.

در بندهای ذیل الزاماتی که هر سامانه باید در اتصال با SSO پیاده‌سازی کند را قید کرده‌ایم. لذا مفاهیم بیان شده می‌بایست در سامانه‌ها پیاده‌سازی شود. در غیر اینصورت روش اتصال صحیح و مطابق با استاندارد نخواهد بود.

پس از پیاده‌سازی کامل باید کارکرد سامانه متصل شده به SSO مطابق با web flow ذیل باشد. هم برای اولین ورود و هم برای ورودهایی که کاربر از قبل Ticket دارد.

SSO Web Flow

مدیریت نشست کاربران

در حالت عادی یک برنامه از یک نشست داخلی برای هر کاربر استفاده می‌کند. یعنی در زمان ورود کاربر از طریق صفحه login برای هر کاربر یک نشست کاربری شکل می‌گیرد و اصولا در دیتابیس یا حافظه RAM یا سرویس‌های مانند Redis و غیره ذخیره می‌شود. زمانی که کاربر از طریق SSO وارد می‌شود، یک نشست سمت سرویس SSO وجود دارد و یک نشست به کمک کلید مشترک بین دو سیستم، در سمت برنامه مورد استفاده کاربر، ایجاد می‌شود.

بدیهی است که پس از مکانیزم اولیه شناسایی کاربر توسط SSO، کاربر دیگر نباید به سمت SSO هدایت شود و این امر باید توسط سامانه، مدیریت شود، که در ادامه بصورت کامل توضیح داده خواهد شد. لذا مدیریت نشست کاربران در دو قسمت صورت می‌گیرد. سمت سامانه و سمت سرویس SSO. بنابراین در زمان شناسایی کاربر و خروج کاربر این نکته باید مد نظر قرار گیرد.

نقش کلید مشترک در تشکیل نشست

جهت تشخیص اینکه کدام کاربر وارد یک سامانه شده است، از مشخصه‌های برگشتی که پس از تعیین اعتبار کلید ST صورت خواهد گرفت، استفاده می‌شود. اگر سامانه‌ای فاقد کلید مشترک (به شرط یکتا بودن داده به ازای هر کاربر) با سرویس SSO هست، میبایست پیش‌بینی لازم در این قسمت را داشته باشد و اقدام به ورود داده نماید. با توجه به اینکه کد ملی برای همه افراد در هر نقش و وضعیتی یک کلید یکتای رسمی هست، لذا تقریبا در همه سازمانها این کلید به عنوان کلید مشترک بین سامانه‌ها استفاده می‌شود. تصور کنید که کاربر در یک سامانه با کد پرسنلی وارد می‌شود. الان این کاربر به سرویس SSO متصل شده است و مشخصه‌های مجاز کاربر به آن سامانه داده می‌شود. سامانه می‌تواند از کد ملی (یا کد پرسنلی یا هر فیلد یکتای مشترک) که در مشخصه‌‌های بازگشتی کاربر مشخص است، استفاده کند و کاربر را در دیتابیس محلی خود پیدا کند و برای آن کاربر یک نشست ایجاد کند.

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

لذا در این مرحله ۲ نشست وجود دارد. نشست اول سمت سرویس SSO (که برای همه سامانه‌ها به ازای هر کاربر یکسان هست) و نشست دوم سمت هر سامانه که برای هر سامانه منحصر به خود سامانه است و سامانه‌ دیگری هم به آن دسترسی ندارد. از این مرحله به بعد هر سامانه با نشست محلی کاربر کار می‌کند و نیازی به انجام استعلام از SSO ندارد. البته در صورت نیاز برای مواقع خاص امکان صدور تیکت ST جدید بر اساس تیکت TGC موجود در کوکی مرورگر وجود دارد.

نگهداری تیکت ST برای هر کاربر

هر زمان که یک سامانه بر اساس تیکت اصلی برای یک کاربر اقدام به دریافت تیکت ST نمود، به مدت ۱۰ ثانیه (این مقدار پیش فرض هست و بنابر سیاست سازمان تعیین می‌شود که در اکثر موارد به لحاظ امنیتی همین مقدار لحاظ شده است) فرصت دارد تا این تیکت را اعتبارسنجی کند. در صورت اعتبار سنجی موفق از سمت سرویس SSO این تیکت به عنوان آخرین تیکت اعتبارسنجی شده برای کاربر مشخص و به ازای سامانه مربوطه، در نشست کاربر نگهداری می‌شود.

جهت پیاده‌سازی مکانیزم SLO پس از خروج موفق یک کاربر از سرویس SSO (چه بصورت مستقیم یا غیر مستقیم که توسط یک سامانه دیگر انجام می‌شود) سایر سامانه‌ها نیز باید از این امر مطلع شوند. کلید مشترک برای این اطلاع‌رسانی تیکت ST هست. این تیکت باید بر اساس نام کاربر محلی یا session-id کاربر محلی سامانه در یک دیتابیس یا فضای مناسبی نگهداری شود. در بخش‌های بعدی فرآیند SLO بصورت منطقی تشریح خواهد شد.

ورود خودکار کاربران شناسایی شده در SSO

با توجه به توضیحات بند‌های قبل، در حالتی که یک کاربر از قبل در SSO وارد شده باشد، قابل شناسایی هست. یک سامانه می‌تواند با چک کردن cookie مربوط به کاربر با استفاده از توابع موجود در کتابخانه client ، و از طریق ارتباط مستقیم با سرویس SSO با استفاده از تیکت کاربر درخواست صدور تیکت ST را بدهد و آن را اعتبارسنجی کند. لذا همانند حالت عادی زمانی که یک کاربر وارد یک سامانه می‌شود (منظور وارد کردن هر آدرس معتبری و URL از آن سامانه هست) می‌بایست به صورت خودکار در صورت داشتن تیکت و صحت استعلام آن،‌به سیستم وارد شود.

در هر صفحه سامانه تحت وب با استفاده از مکانیزمهایی مانند bootstrap یا middleware یا هر روش استانداردی که سامانه می‌تواند استفاده کند، باید این مسئله قابل چک و تشخیص باشد. اینکه یک سامانه فقط از طریق آدرس URL مشخص و ثابتی این فرآیند را انجام دهد، کاملا خارج از استاندارد پیاده‌سازی SSO هست. روشهای دیگر مانند redirect اولیه از سمت سرویس SSO به سامانه مذکور نیز اشتباه هست.

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

بعنوان نمونه متود زیر از کتابخانه phpCAS امکان بررسی وضعیت فعلی کاربر را دارد و در صورتی که کاربر از قبل در SSO وارد شده باشد مقدار true برمی‌گرداند. در سایر کتابخانه‌ها نیز این مسئله پیاده‌سازی شده و قابل استفاده هست.

در ذیل تابع اول نمایش داده شده است که تابع دیگری را فراخوانی می‌کند که تابع دوم نیز در ادامه آورده شده است.

تابع اول

	/**
	 * Checks to see is user is globally in CAS
	 *
	 * @return boolean
	 */
	public function checkAuthentication() {
		return $this->isMasquerading() ? true : phpCAS::checkAuthentication();
	}

تابع دوم فراخوان شده توسط تابع اول

    public static function checkAuthentication()
    {
        phpCAS :: traceBegin();
        phpCAS::_validateClientExists();

        $auth = self::$_PHPCAS_CLIENT->checkAuthentication();

        // store where the authentication has been checked and the result
        self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);

        phpCAS :: traceEnd($auth);
        return $auth;
    }

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

مفهوم و صحت کارکرد SLO

زمانی که یک کاربر از سامانه خارج می‌شود، جدا از اینکه آن سامانه نشست کاربر را تخریب می‌کند،‌اقدام به هدایت کاربر به آدرس cas/logout/ می‌کند. پس از اتصال کاربر به این آدرس، نشست کاربر سمت SSO نیز از بین خواهد رفت. اما یک مشکل باقی می‌ماند. کاربر در سایر سامانه‌های وارد شده و نشست محلی کاربر برقرار هست و سامانه‌ها متوجه این امر نمی‌شوند. این مسئله ۲ راهکار دارد:

۱- اینکه به ازای هر درخواست و عملیات کاربر در سامانه مربوطه، درخواست صدور تیکت ST جدید داده شود و اعتبار‌سنجی صورت بگیرد. که این روش اشتباه هست و باعث ایجاد سربار بسیار زیاد و البته کندی، بر روی سامانه و همچنین SSO خواهد شد و این عملیات اصلا مورد نیاز هست و این روش پیاده‌سازی کاملا اشتباه هست.

۲- سامانه مربوطه باید مکانیزم SLO طبق توضیحات همین مستند را پیاده‌سازی کند که روش ساده‌تر آن استفاده از مکانیزم Back Channel هست.

طبق روش دوم زمانی که کاربر وارد می‌شود آخرین تیکت ST مربوط به آن کاربر که به ازای سامانه مربوطه صادر شده است، در نشست کاربر سمت سرویس SSO نگهداری می‌شود. همین کار باید سمت سامانه نیز انجام شود. اگر فرض کنیم سامانه‌ای برای تخریب نشست کاربر از session-id کاربر استفاده می‌‌کند، می‌تواند آخرین تیکت ST اعتبارسنجی شده برای آن کاربر را در دیتابیس به همراه session-id نگهداری کند. (یا می‌تواند از یک کلید مشترک دیگر که به session-id یکتا می‌تواند برسد، استفاده کند) زمانی که کاربر از سمت سرویس SSO خارج می‌شود، این سرویس بر اساس نشست‌های فعال کاربر در سایر سامانه‌ها (سامانه‌هایی که تیکت ST را برای آن کاربر دریافت نموده و اعتبار سنجی کرده‌اند) می‌تواند به آنها اطلاع رسانی کند.

این اطلاع رسانی جهت خارج کردن کاربر از آن سامانه‌ها صورت می‌گیرد و منطق پیاده‌سازی آن در قسمت SLO این مستند ذکر شده است. اما بصورت کلی تیکت ST مربوط به کاربر برای هر سامانه به آن سامانه‌ روی درگاه مشخص شده از سمت آن سامانه ارسال می‌شود. منظور از درگاه مشخص شده آدرس URLی از آن سامانه هست که داده مربوطه را از سرویس SSO دریافت می‌کند و بر اساس آن کاربر را پیدا می‌کند و نشست آن را تخریب می‌کند.

آدرس logout برای هر سامانه باید اعلام گردد و این آدرس سمت سرویس SSO تعریف می‌شود. لذا در زمان خروج کاربر داده مربوطه بر اساس روش مشخص شده Front channel یا Back channel به آن سامانه اعلام می‌شود و سامانه موظف هست که نشست کاربر مربوطه را تخریب کند و کلیه عملیاتی که از سمت آن کاربر درخواست می‌شود را نادیده بگیرد و کاربر را از سامانه خارج کند.

هشدار
در یک اتصال صحیح تمامی موارد بالا الزاما باید رعایت شود و سایر پیاده‌سازی‌ها مطابق با استانداردها و الگوهای اثبات شده احراز هویت نیست و این مسائل فارغ از پروتکل استفاده شده برای سرویس SSO هست.


مرجع

  1. ticket granting ticket