عن الAuthentication Patterns

عن الAuthentication Patterns

أي برنامج بيحتاج login. هنتكلم عن الباترنس المشهور , بس في الأول محتاجين إنك تبقى عارف عن ال http protocol, how web works cookies/sessions and difference between each

عشان نركز في موضوعنا , مش حتكلم عن الأساسيات دي. بس ححول استخدم كذا طريقة وعيوب وميزة كل واحدة اولا : مكان ال AUTHENTICATION في الAPP ARCHITECTURE :- auth is a separate layer that should be between your app logic and external internet, its job is to identify request user make sure he is who he say he is يعني لو بنتكلم عن api مثلا ; el-authentication حيبقى قبل أو مع ال api-gateway ; شغلته انه يتعرف علي المستخدم قبل ما الريكوست يوصل للبرنامج, مهم اوي هنا اننا ناكد علي ان اين كانت طريقه الأث فمهم جدا إنها تبقى طبقة لوحدها , غير ال authorization الي ممكن تبقي متداخله شويه في بعض الحالات مع البيزنس لوجك. حنرجع للنقطه دي كمان شويه. ممكن نقسم الموضوع بناء علي: I) according to state Stateless Authentication Stateful Authentication II) according to storage Session-based Auth Token-Based Auth و دي اول خاحه عايزين نطلع بيها من البوست ده: هيه :

اختار اذاي انهي طريقه مناسبه للبرنامج بتاعي ؟ في 3 اعتبرات بحب اختار بناء عليه: 1. الperformance : هلي البرنامج ده بيخدم ملاين المستخدمين ؟ و لا ده internal platform مثلا مش متوقع يستخدمه اكتر من كام الف 2:الstateful vs stateless : عايز على السيرفر state ؟ , ولا نخلي elstate مع الكلينت وهو يبعتهالي مع كل ريكويست 3: عدد السيرفرات و الreplicas و الدومين ؟ هل ممكن اكتر من سيرفر يرد علي نفس الريكوست ؟ ولا هوه سيرفر واحد؟ , و هل السيرفرات دي علي نفس الدومين و لا ممكن يبقي في كذا subdomain شغال عليه اجزاء مختلفه للplatform ؟ مفيش صح و غلط, هيه معتمده علي احتياجك و كل سيناريو مختلف و تغير الlayer دي في المستقبل اسهل من انك تover-engineer من البدايه كلمة الstate هي هل المعلومات بتاعت اليوزر موجودة على السيرفر وبتفضل حتى مابين الريكويست والتاني , عكس elstateless الذي كل ريكويست بيبقى مطلوب منه يبقى معاه كل المعلومات اللي السيرفر محتاجها عشان يتعرف علي المستخدم بما ان السيرفر في الحاله دي معندوش state أو does not maintain state between requests لو مبداء الapplication-state جديد عليك, انصحك تقراء عنه خصوصا لو مش دارس اكاديمي فبناء عليه ممكن يكون قرار إنك تستخدم stateful session-based افضل, او تقرر stateless session-based; او تقول انا ححتاج token-based بس السيرفر محتاج الstate فا مشجستخدم JWT مثلا حستخدم string-based-token بدل الsession-id وال cookies .. هكذا , ميكس&ماتش زي ماتحب بس الموهم تعرف الفرق بينهم الأول وبعدين تقرار /// أولا ال session-based دي الطريقة اللي كلنا اتعلمناها , اليوزر يبعت الباسورد evalidate server بعد كده نفتح session server-side : السشون دي ليها ID ; بنبعتو في ال cookie وبكده مع كل ريكويست البروسر بيبعت elsessionID والسيرفر يفتح السسيون ويرجع state تاني . حتاخد بالك في القصة دي إنت معتمد على 1. application-server: إنه يهاندل السسيون 2. elbrowser : إنه يفهم el-HTTP-header و يسجل elcookie و يبعتها مع كل ريكويست منهنا ورايح 3.ال - webserver : إنه يهاندل الكوكي المبعوته طب إيه الميزة والعيب : أكبر ميزة طبعا السهولة ; وبلنسبة ل 90% من البرامج البرفرمنس كمان; الapplication-servers بتظبط هيه مكان ماحتسجل السشون في ملف serialized وانتى مابتشغلش بالك .. بس في عيبين قاتلين الحقيقه .. العيوب:

  1. الscalebility : وهنا حتلاحظ بيتأثر قوي el-performance ; مع زيادة عدد الزيارة ل ملايين; - وعلى حسب السيرفر بتأكسس وتحفظ السسيون ازاي - السيرفر ممكن يتملى بسرعة ده غير إن السسيون بتبقى في الميموري للسيرفر
  2. cross domain cookies : من عيوب الcookies -هو مش عيب هو سكيورتي- إنها مربوطة بال domain اللي عملها . يعني لو login حصل على domain api.myapp.com مش حتعرف تستخدمها -بسهوله- علي اي دومين تاني shop.myapp.com
  3. server-to-server communication: لو عندك كذا سيرفر وواحد بيحاول يكلم التاني عشان يجيب معلومة مثلا بيبقى حوار ! مش حطول في تفاصيل البوست طويل لوحده 😃 بس كل العيوب دي ليها حلول ( ذي انك تستخدم central storage او Redis مثلا عشان #1 , او انك تستخدم iframes عشان المشكله#2, بس دي كلها حلول لمشكله انت وجدتها لمه قررت تستخدم السشون بيذد , فا تالت و عاشر "it-depends" ثانيًا : TOKEN-BASED AUTH وده معتمد على HTTP Protocol , XHR/ajax requests وبنشوفه كتير قوي مع el single-page-applications- & API's فكرة اليوزر يبعت الباسورد نتأكد إنها صح < وبعدين نعمل token //والتوكن دي أنواع // ونبعتها للكلينت بحيث إنه برده يبعتها مع كل ريكويست من هنا ورايح >> الفكره هنا و الفرق عن السشون بيزد ان مفيش كوكيز , (و لوان ممكن برضه تسجل التوكن في الكوكي ) و ان المفروض ان process تبقي stateless
// login psudo-code
UserRepo.findUserByPK( req.username )
.then(user => user.comparePassword(req.pass) )
.then(user => user.generateToken() )
.then(token => res.send( user ) )
.catch(next)

بس ده يرجعنا ل نقطة أنواع التوكن : JWT based and its alikes : string based: ال JWT based هنا انابسجل بيانات اليوزر في JSON , و بشفرها عشان تبقي text مضغوط ; و مع كل ريكوست السيرفر بيفك التشفير يلاقي بيانات اليوزر , من غير مايحتاج يفتح سشون او يكلم داتابيز

الstring based: اقرب حل وسط لل سشيون بازد فيه التوكن بتبقى عبارة عن random-string (md5 masalan) و السترينج ده بنسجله في الداتابيز يشاور علي اليوزر . مع كل ريكوست السيرفر يضور علي السترينج ده موجود فعلا ولا لا و يجيب بيانات المستخدم من قاعده البيانات, او في بعض الاحيان بيبقي السترينج ده هوه اسم ملف فيه بيانات ال مستخدم في الحاله الJWT , انا هنا بدل مسجل بيانات المستخدم علي السيرفر, انا ببعتها متشفره ( two-way-encryption ) بحيث لما المستخدم يبعتلي التوكن دي تاني افكها الاقي بيانات على طول ; مش محتاج أكلم database وده بذات من أهم مزاية el-JWT اللي بيخليها مناسبة لي multi-server-applications أو ال cross-domain اللي قلنا إنها من مشاكل el-session-based auth /// عيب ال Token-based : أولا إنت صحيح بت delegate ال state للفرنت اند ; بس ده بيخالي في صعوبة في إنك تنتحكم في ال توكن بعد ماطلعت من عندك >> المبدأ كله مبني على الثقة إن التوكن -JWT - لو التلاعب فيها بتبوظ , فأنت لما بيجيلك توكن مع ريكويست لو عرفت تفكها =decode= يبقى هي سليمة وكل المعلومات اللي جواها مظبوطة >>> psudo-code for ExpressJS middleware and route example:-


// will reject req if we could not load User info
function authMiddleware(req, res, next){
res.locals.token = req.headers['authorization'].split(' ').pop();

jwt.decode(res.locals.token))
.then(user=>{ res.locals.user = user; });
.catch(e => new AccessDeniedError('TOKEN_DECODE') )
.then(next) // undefined unless .catch was triggered
}

example protected route

function protectedRoute(req, res, next){
const user = res.locals.user;

res.send( ' welcome back ${user.fullname}' )
}

زي ماتفقنا إن authentication is separate layer from app. و ان اي جزء من البرنامج المفروض متوقع ان في يوزر - اين كان نوعه او ال access-level بتاعه دي شغلة ال authorization مش ال authentication - هتلقي في الكود اللي فوق الروت بيرد be-welcome-msg ;; وإن اليزار احنا جبنا معلوماته من التوكن .. طب إفرض إن اليوزر غير اسمه مثلا >> ساعتها المعلومات اللي جوه التوكن دي حتبقى غلط >> وده عيبه بقى 😃 . Data anomalies due to lack of single source of truth (DB) طب نعمل إيه ؟ لأ ده بوست تاني بقى نتكلم فيه عن عيوب الاتنين بإستفاضة وازاي نحلهم

انا بقالي سنين مكتبتكش بوست تكنيكل فاسف لو طولت او اسلوبي مهرجل شويه 🙂 .. لو ليك تعليق اذاي احسن من نفسي او سؤال اكيد اتفضل: