CAS Development
معرفی
بسیاری از سازمانها جهت حل این مشکل از سرویسهایی بر پایه LDAP استفاده میکنند تا هویت کاربران یکپارچه شود و از تعدد نام کاربری و رمز عبور جلوگیری شود. کارکرد این سرویس نیازمند اتصال همه سامانههای نرمافزاری به پروتکل LDAP جهت احراز هویت هست. اگر چه مشکل تعدد نام کاربری حل میشود اما مشکل دیگری ایجاد میشود. تصور کنید که یک کاربر روزانه به ۱۰ سامانه نرمافزاری مختلف میخواهد متصل شود و رمز کاربر نیز پیچیده باشد. کاربر حداقل ۱۰ بار باید نام کاربری و رمز عبور خود را وارد کند تا بتواند از این سامانهها استفاده کند. اگر این مقدار را با تعداد کابران محاسبه کنیم به حجم بسیار بالایی از ورود خواهیم رسید.
جهت سهولت در ورود و خروج کاربران از سامانههای مختلف و حل مشکل فوق، از سرویسهای SSO یا یکبار ورود استفاده میشود. این سرویسها پروتکلهای مختلفی را اصولاً پوشش میدهند که شامل CAS, OAuth2, SAML و یا بصورت وبسرویس Restful خواهد بود. سامانهها در صورتی که بر روی یک پروتکل مشترک احراز هویت را انجام دهند توسط Ticket صادره از سرویس SSO میتوانند اعتبار ورود کاربر را بررسی نموده و در صورتی که ticket مربوطه هنوز معتبر باشد امکان و اجازه ورود کاربر را بدون وارد نمودن نام کاربر و رمز عبور بدهند. در هنگام خروج یک کاربر از یک سامانه نیز با استفاده از SLO یا یکبار خروج و اعلام آن به سرویس SSO میتوان ticket مربوطه را بیاعتبار کرد و دسترسی کاربر از همه سامانهها به جهت امنیت قطع خواهد شد.
در ادامه به نحوه چگونگی اتصال و اعتبارسنجی این سرویس میپردازیم.
پروتکل 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 و دوم هم سایر پارامترها و اطلاعاتی که از سمت این سرویس در مورد کاربر به درخواست کننده برگشت داده میشود.
در سرویس CAS سه قسمت اصلی وجود دارد:
- مرورگر کاربر
- نرمافزار تحت وب
- سرور SSO با پشتیبانی از CAS
مرورگر کاربر
نرمافزار تحت وب
سرور SSO با پشتیبانی از CAS
- ارائه خدمات صفحه ورود و احراز هویت کاربر از یک منبع واحد (دیتابیس، LDAP و غیره)
- صدور کوکی TG [۱]جهت عدم نیاز به ورود مجدد کاربر در موارد بعدی که به سمت سرور CAS هدایت میشود (هر نرمافزار جهت کنترل اعتبار ورود کاربر، مرورگر را به سمت آدرس وب سرویس CAS هدایت میکند و در صورتی که تیکت کاربر معتبر باشد، مجدداً از سمت CAS کاربر به سامانه اصلی هدایت میشود. لذا در این فرآیند کاربری که قبلاً وارد شده است نیازی به ورود مجدد ندارد و متوجه این امر نخواهد شد و این همان سهولتی هست که در کنار امنیت برای کاربر به ارمغان میآید)
- امکان هدایت و برگشت به نرمافزار تحت وب با تنظیم ticket=ST-XXX در url مربوطه برای اینکه به عنوان CAS client بتواند تیکت را بررسی کند
- اعتبارسنجی تیکت صادر شده توسط کتابخانه CAS برای اطمینان نرمافزار از صحت ورود کاربر و اعتبار تیکت آن
نحوه اتصال با CAS
برای مشاهده دیاگرامهای دقیقتر و بهمراه کدهای HTTP مربوطه میتوان به لینک زیر مراجعه کرد
https://apereo.github.io/cas/5.2.x/protocol/CAS-Protocol.html
Initial request (مرحله یک)
- نرمافزار sampleapp به عنوان CAS client تنظیم شده است تا مثلاً روی آدرس test/ احراز هویت را انجام دهد.
- کاربر از طریق مرورگر به test/ متصل میشود.
- اگر مرورگر در حال حاضر بر روی نرمافزار sampleapp هیچ نشستی نداشته باشد، sampleapp کنترل را بدست کتابخانه CAS میدهد.
- اگر کتابخانه 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
هدایت به صفحه ورود CAS (مرحله دو)
- کاربر به صفحه ورود CAS جهت احراز هویت انتقال داده میشود. فرم ورود مربوط به صفحه CAS روی مرورگر کاربر نمایش داده خواهد شد.
- در این مرحله کاربر میبایست نام کاربری و رمز عبور خود را واردکند. در سمت راست صفحه نیز نام و توضیحات برنامهای که کاربر از آن به سمت صفحه ورود هدایت شده است نمایش داده میشود. مانند تصویر زیر:در تصویر فوق ما از نرمافزاری با عنوان CAS Management به این صفحه هدایت شدهایم. این موارد توسط مدیر سیستم به عنوان نام و توضیحات نرمافزار مجاز تعریف شده، تعیین میشود.
بررسی TGT در مرورگر (مرحله سه)
- در این مرحله مقدار CASTGC cookie که در سمت سرور با نام TGT تولید شده است چک میشود. اگر چنین مقداری در مرورگر در همان لحظه وجود داشته باشد، یعنی اینکه کاربر توسط CAS قبلاً احراز هویت شده است و از اینجا به مرحله شش خواهد رفت و به نرمافزار مجاز با مشخص نمودن مقدار service ticket برگشت داده خواهد شد.
- اگر هیچ CASTGC وجود نداشته باشد، صفحه ورود CAS در مرورگر نمایش داده خواهد شد.
ارسال صفحه ورود به مرورگر توسط CAS (مرحله چهار)
- عدم نیاز به مدیریت صفحه ورود توسط هر نرمافزار
- عدم نیاز به اتصال به سیستمهای بانک اطلاعاتی و یا 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/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
نحوه اتصال با 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
یکبار خروج (SLO)
همانطور که کاربر یک بار در سرویس SSO ورود میکند و سپس در سایر سامانه ها بدون ورود مجدد، احراز خواهد شد، در زمان خروج نیز چنین عملی اتفاق خواهد افتاد. همانطور که میدانیم نشست ایجاد شده برای کاربر مختص هر سامانه هست و زمانی که کاربر از یک سامانه خارج میشود تنها نشست مربوط به همان سامانه از بین میرود و کاربر در سایر سامانهها همچنان متصل باقی خواهد ماند. به طور بالقوه چندین برنامه به سرویس SSO متصل هستند و یک نشست داخلی برای کاربر دارند و تمایز بین خروج و خروج یکتا (SLO) براساس تعداد نشستهایی است که بر اساس یک عمل خروج به پایان می رسد.
این عملیات به نام SLO یا Single Logout خوانده میشود که در ادامه در مورد نحوه انجام آن توضیح خواهیم داد. بدیهی هست که همانطور که در زمان اتصال به SSO برای ورود کاربران سامانهها باید در سمت خود تغییراتی را اعمال نمایند در این قسمت نیز این مسئله بایستی انجام شود.
نکته
دقت کنید که مطالب ذکر شده در این قسمت مربوط به پروتکل CAS هست و با توجه به اینکه پروتکلهای دیگری مانند OAuth2, WS-Federation, OpenID, SAML, REST در این سرویس پشتیبانی میشوند، این مطالب صرفا مربوط به پروتکل CAS هست و سایر پروتکلهای رفتار و روش خود را دارند.
عملیات خروج
عملیات خروج در دو حالت رخ میدهد:
- خروج از یک برنامه متصل به SSO
- خروج مستقیم از سامانه 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 جدید برای آن سامانه صادر میشود.
مرجع
- ↑ ticket granting ticket