כתיבה נכונה של REST-API

ilgnd

New member
כתיבה נכונה של REST-API

מתחיל לכתוב REST-API לאפליקציה שלי. אני מעלה את השאלה הזו כי אחד הפערים הגדולים שלי הוא בנושא אבטחת מידע ברשת.

כיום אחת הדרכים הנפוצות להזדהות הוא שימוש ב - OAuth. אם אני מבין נכון, זה דורש הזדהות מול צד ג' כגון גוגל או פייסבוק או לחילופין הקמת שרת Oauth משלך.
השאלה הראשונה שלי היא האם אני צודק, ואכן נדרש שימוש בצד ג' כדי לנהל הזדהות מסוג OAuth?

כרגע הפתרון שלי נראה כך:
  1. הלקוח שולח POST עם שם וסיסמה (ייחודיים לאפליקציה) אל הכתובת /login. השם והסיסמה מושווים לאלה שנמצאים אצלי בשרת (מושווים כמובן לגיבוב קריפטוגרפי יחד עם salt של הסיסמה)
  2. אם אין התאמה מכל סיבה שהיא (בין אם שם המשתמש לא קיים ובין אם הסיסמה לא נכונה) מוחזר 404. זה כדי למנוע זליגה של שמות משתמשים.
  3. אם יש התאמה מוחזרת תשובה עם 200, שכוללת שדה של token, של refresh-token ושל expiration.
  4. כל בקשה אחרת ל-API צריכה להישלח עם אותו - token. אם אין על השרת session שמשוייך לאותו token, מוחזר401. אחרת מוחזרת התשובה הרלוונטית. אם ה - session פג תוקף, יוחזר גם 401 למשך מספר דקות, עד שהוא יעלם לחלוטין ואז גם refresh לא יעשה את העבודה.
  5. אם פג התוקף, הלקוח צריך לשלוח את ה - refresh-token יחד עם ה - token המקורי כדי לקבל חדש.
האם אני מפספס משהו? האם השיטה הזו מספיק מאובטחת עבור אפליקציה שמחזיקה פרטים אישיים סטנדרטיים (שם, מספר טלפון, אימייל וכו') ותוצאות משחקים, אבל ללא פרטים פיננסיים כלשהם?
 

vinney

Well-known member
הדבר האחרון שאתה צריך זה לכתוב מודול אבטחה מאפס.

או שתקח משהו קיים או שתשתמש בצד ג'. תלוי באופי הלקוחות, יכול להיות שצד ג' יהיה הרבה יותר טוב (כמה צדדים, אפילו - כל הרשתות החברתיות מציעות שירות כזה, גוגל, אמאזון, אפילו מייקרוסופט אני חושב שנכנסת לעסק הזה). זה חוסך לאנשים צורך להרשם ספציפית לאתר שלך, לתת פרטים, לזכור עוד סיסמא, וכד'. מצד שני, כמובן - זה יעלה לך בקריאות לAPIים האלה ורישום אצלם, תלוי בכמות המשתמשים זה יכול להיות די יקר.
&nbsp
לגבי 4 - לשמור מצב על השרת עלול להיות בעייתי. הייתי מציע לחשוב על איך לעשות את הAPI שיהיה stateless. דהיינו, כל בקשה בלתי תלויה בכל בקשה אחרת. הstate מועבר בבקשה עצמה (למשל סדר כזה - תן לי רשימת דברים, תן לי דבר X [מהרשימה שקיבלתי קודם], בצע פעולה על דבר X [שנתת לי קודם], וכד').
&nbsp
 

יבגניי34

New member


 

ilgnd

New member
זה לא בדיוק מודול אבטחה

ניהול האבטחה שלי מתבטא בניהול הסיסמאות, ניהול sessions וניהול tokens.
אני לא יודע אם יש FW קיים שעושה עבורי את העבודה הזו.
&nbsp
ה - API הוא stateless, ומאוד דומה למה שתיארת.
אני צריך לשמור את ה - session כדי להתאים בין המשתמש לבין הבקשה. לדוגמה לא אעביר למשתמש Y מידע על אובייקט ששייך למשתמש X.
 

vinney

Well-known member
לא ברור לי למה אתה צריך לנהל sessions בשביל זה

אמור להיות לך איזה DB של מה שייך לאיזה משתמש, אבל זה לא קשור לsessions. לא יכול להיות שהAPI יהיה stateless אבל אתה שומר sessions - דבר אחד סותר את השני

&nbsp
מודול אימות חייב להיות מאובטח, אלה דברים שעובדים ביחד. אם מודול האימות לא מאובטח, אז לא אימתת כלום. הבעיות והפרצות הן לרוב במימוש, לא בפרוטוקול. הפרוטוקולים ידועים ומפורסמים, אבל לממש אותן כך שלא יהיה ניתן למצוא תורפה שניתן לתקוף זאת אומנות שבאה עם הרבה הרבה הרבה מאוד נסיון שלא נראה שיש לך.
&nbsp
אפילו אם כל מה שאתה שומר זה שם, סיסמא ואימייל, פרצה למאגר כזה יכולה להביא הרבה תועלת כי הרבה מאוד אנשים משתמשים בסיסמא אחת להכל. בתיאור שלך כתבת שאתה תשווה את שם המשתמש והסיסמא מול מה ששמור אצלך, והנה - זאת כבר נקודת תורפה אחת.
 

ilgnd

New member
בוא נזנח את השם session

בסך הכל אובייקט ששומר את המשתמש שמקושר לאותה בקשה וככה מחליט אם מותר לו לגשת למשאב או לא. חוץ מזה יש גם זמן פקיעת תוקף, ולכן קראתי לזה - session.
&nbsp
אדגיש שאני לא שומר סיסמאות אלא רק hash קריפטוגרפי שלהן כולל salt.
&nbsp
לגבי מודול האימות: זו בדיוק השאלה שלי: האם יש עוד משהו שצריך לחשוב עליו בנושא האימות. הפחד היחיד שלי הוא שבגלל טעות כלשהי, מידע ששייך למשתמש אחד יזלוג למשתמשים אחרים. זה לא סוף העולם כי זה בסך הכל משחק רשת שלא מעורבת בו אגורה, אבל אני מעדיף כמובן שזה לא יקרה.
 

vinney

Well-known member
כל עוד האובייקט מקושר לבקשה - זה session

תקרא לזה איך שאתה רוצה


האובייקט שמתאר את הלקוח לא אמור להיות מקושר לבקשה. הבקשות קוראות אותו או מעדכנות אותו, אבל האובייקט עצמו לא אמור להיות מקושר לאף בקשה. אחרת אתה נכנס למצבים מוזרים של "המשתמש סגר את המחשב באמצע הsession - מה עושים?", או "קיבלתי ג'יבריש בבקשה כי משהו השתמש איפשהו - מה עושים?". אם האובייקט לא קשור לבקשות - זורקים את הבקשה וזהו. אם הוא מקושר - אתה תקוע.

לגבי קריפטוגריפיה - יש לי קצת נסיון בתחום הזה, והקצת נסיון הזה אומר שאם אין לך מישהו עם הרבה נסיון שידריך אותך - עדיף לא להכנס לזה.

אתה יכול לעשות הכל "פשוט", הבעיה תהיה כשמישהו אכן יפרוץ אלייך ונתוני המשתמשים יתחילו לזלוג בגלל טעות כזאת או אחרת במימוש או בגלל התשתית שעליה אתה יושב שלא מאובטחת מספיק. כשאתה עושה את זה דרך צד ג' - כל הנושא הזה מטופל בתשתית שלהם. הסיכוי שמישהו יצליח לגנוב סיסמא מאמאזון או פייסבוק נמוך משמעותית מהסיכוי שמישהו יגנוס את הסיסמא ממך. זה לא רק מימוש פרוטוקול האבטחה סביב פרוטוקול האימות - זה גם אבטחת האתר עצמו, בסיס הנתונים שבו כל זה שמור, הקוד שלך שרץ על האתר, וכד'. מספיק חוליה חלשה אחת בכל אלה כדי שהכל יפול. אתה יכול לעשות אבטחה נהדרת לפרוטוקול האימות שלך, אבל אם, לדוגמא, כל אחד יכול להכנס לשרת הhosting שלך - לא עשית כלום. האם אתה מסוגל להרים אבטחה כזאת שתסגור את כל הפינות האפשריות?

אתה אולי לא חושב שזה חשוב כי זה כולה משחק רשת, אבל כמו שאמרתי - המוטיבציה בפרצה היא לא לגנוב משהו מהמשחק שלך, אלא לגנוב פרטים של משתמשים שלך ואז להשתמש בזה במקום אחר.
 

ilgnd

New member
האובייקט מקושר ל - token

כלומר ברגע שאני מקבל בקשה עם token מסויים, אני מחפש את המשתמש שקשור אליו ואת אוסף ההרשאות שלו.
בזה נגמר ה - session.
&nbsp
אגב, השימוש בצ ג' לא יפתור את הבעיה. בסופו של דבר אני אקבל token מהמשתמש ואצטרך לקשר בינו לבין המשתמש. גם אם ה-token הגיע מצד ג' שנחשב הרבה יותר מאובטח ממני.
 

vinney

Well-known member
אז האובייקט לא מקושר לtoken, האובייקט מקושר למשתמש

זה מה שתיארת.
&nbsp
שימוש בצד ג' כן יפתור את הבעיה כי אתה לא צריך להתעסק באימות וסיסמאות, אלה ישמרו בפייסבוק (לדוגמא). אתה מקבל את הTOKEN, שאיתו אתה פונה לפייסבוק שמחזיר לך את הפרטים שהמשתמש אישר להחזיר לך, ועם זה אתה עובד. מישהו יגנוב את הTOKEN? שיגנבו, כי פייסבוק יתנו רק לך להשתמש בו. במצב הזה בעיית האבטחה מצטמצת רק לדברים שאתה שומר אצלך, שזה רק הנתונים של משחק הרשת שלך שלא מעניינים אף אחד. אתה לא שומר סיסמאות, שמות, אימיילים - כל אלה שמורים בפייסבוק.
 

ilgnd

New member
צודק, תודה על התיקון

מה שאתה מתאר מוריד ממני הרבה מהאחריות על אבטחת המידע, וזה מעולה.
יחד עם זאת, בסופו של דבר אני אקבל מפייסבוק פרטי משתמש. עדיין אצטרך לקשר בין פרטי המשתמש האלה לבין כל ההרשאות במשחק. אני מניח שאין דרך לצאת מזה: פייסבוק לא ינהלו עבורי את ההרשאות.
 

vinney

Well-known member
אתה לא צריך לשמור אצלך את פרטי המשתמש

אתה מקבל מפייסבוק (או כל ספק אחר, העקרון הוא אותו עקרון) איזה userid, שאיתו אתה יכול לשלוף את הפרטים עצמם בזמן הגישה. אבל אצלך - אתה שומר רק את הuserid. מישהו יגנוב את כווווווווווול מסד הנתונים שלך? יהיה לו אוסף של useridים שלא מזהים שום דבר ואף אחד כי אפשר לקבל את הפרטים עצמם רק מספקי האימות שהגנב לא ידע מהם או באיזה מפתח לפנות אליהם. אם הנתונים שלך עצמך פחות קריטיים - פתרת את הבעיה.
&nbsp
זה כן עולה לך במלא קריאות לAPIים האלה, כמובן, וכשאני אומר "עולה" אני מתכוון לעולה בכסף, השירותים האלה לא חינמיים. אם אין לך שום מודל עסקי לכסות על זה ואתה בונה על הרבה תעבורה (יותר מכמה מאות משתמשים שכל אחד מהם ניגש לאתר שלך פעם בחודש) - זה יכול לצאת יקר.
 

ilgnd

New member
העלות היא גם משהו שאני לוקח בחשבון

וכאמור, הפתרון הזה פותר לי את בעיות האבטחה, אבל לא את בעיות שיוך המזהים להרשאות וניהול נכון של ההרשאות.
 

vinney

Well-known member
מה הבעיה עם שיוך הרשאות?

טבלה עם מפתח? אני מניח שאתה יכול להתגבר על זה. זה מפריע לך אם זה ידלוף? אני מניח שלא במיוחד.
 

ilgnd

New member
לא בעיה אלא משהו שדורש פיתוח

הנקודה שלי הייתה שגם אם אשתמש בצד ג' עבור ההזדהות, עדיין אצטרך לפתח בעצמי את נושא ההרשאות.
 

rontech

New member
אז תמליץ לו על שירות איכותי...

איזה שרות HOSTING שידוע כאמין....
עם חשבון בענן או איזה VPS או אפילו dedicated קטן....

למיטב ידיעתי blue host נחשב לשירות טוב...
 

selalerer

New member
נשמע בסדר. לא לשכוח שהכל יהיה ב-HTTPS (פשוט לא רשמת את זה)

אבטחה כמובן מורכבת מעוד דברים: אבטחת רשת, אבטחה של הגישה ל-DB, מכונות שלא מארחות אפליקציות אחרות שיכולים לפרוץ אליהן ואל המכונות דרכן וכנראה עוד כמה דברים ששכחתי.
 

ilgnd

New member
כמובן שצריך SSL, אני אקפיד על זה

לגבי אבטחת הרשת, הגישה ל-DB והמכונה: כאן המצב יותר קל.
לכל אפליקציה יש best practices מתועדים ואני אקפיד עליהם.
 

יבגניי34

New member
OAuth זה פרוטוקול הזדהות. אתה יכול לנהל אותו בעצמך

או ע״ 3rd party provider שמוכן לעשות זאת עבורך (כמו אילו שציינת, ועוד רבים).

בלי לעבור על הרשימה שלך אני, וגם אתה, יכולים להיות בטוחים שהיא אינה מאובטחת באופן מספק (זו ההנחה הקטגורית, לא משהו אישי). אל תנהל הזדהות משלך אם אתה לא חייב.
 

ilgnd

New member
הרשימה שלי די מועתקת מפרוטוקול OAuth

ההבדל היחיד הוא שאין צד ג', לכן אני מוותר על החלק של בקשת ההזדהות ומולו וההזדהות של עצמי מולו.
 

יבגניי34

New member
זה לא משנה דבר - בכל קוד שאנחנו כותבים יש באגים

הקוד הכי טוב הוא זה שלא קיים.
שים את האגו בצד ועשה אינטגרציה עם צד שלישי.
אלא אם יש לך סיבה מהותית לא לעשות כך.

נ.ב
היתרון הגדול בלעבוד עם הזדהות צד ג׳ היא שהרבה מהמשתמשים כבר מזוהים מול FB, זה מוריד user friction ויעזור לך מכל בחינה. אנשים לא אוהבים לעשות login לאתרים. אל תירה לעצמך ברגל.
 
למעלה