אימות והרשאות
לכל קריאה ל‑API יש בדיוק שתי שאלות: לאיזו מערכת אתם פונים, ובזכות מה מותר לכם. הראשונה נענית תמיד באותה כותרת; השנייה נענית בארבע דרכים שונות.
הכותרת שתמיד נשלחת
Section titled “הכותרת שתמיד נשלחת”ה‑Application Id מזהה את המערכת (ה“אפליקציה”) שלכם. הוא מזהה ציבורי, לא סוד: הוא מופיע ב‑JavaScript של כל דף נחיתה שמחובר למערכת, וזה בסדר גמור. השער האמיתי הוא ההרשאות בצד השרת, לא סודיות המזהה.
איפה מוציאים אותו: Databases ← המערכת שלכם ← לשונית Settings. ראו סביבות וגישה.
טבלת ההחלטה
Section titled “טבלת ההחלטה”| השיטה | הכותרת | מה היא מרשה | איפה מותר להחזיק אותה |
|---|---|---|---|
| Application Id בלבד | X-Parse-Application-Id |
getlead / web2table — ובנוסף, בפועל, גם POST /parse/files/… |
מותר בדפדפן |
| API Key | X-Parse-API-Key |
הכול, בזהות Master; ניתן לביטול נקודתי |
צד שרת בלבד; אסור בדפדפן |
| Master Key | X-Parse-Master-Key |
הכול, עוקף כל הרשאה; אין ביטול נקודתי | צד שרת בלבד; אסור בדפדפן |
| Session Token | X-Parse-Session-Token |
מה שהמשתמש עצמו מורשה | צד שרת, או אפליקציה שהמשתמש התחבר אליה |
ארבע שאלות, בסדר הזה:
- הקוד רץ בדפדפן של גולש אנונימי?
→ Application Id בלבד, ורק מול
getlead/web2table. עצרו כאן. - ההרשאות צריכות להיות של משתמש מסוים (פורטל, אפליקציה שכל אחד רואה את שלו)?
→ Session Token דרך
POST /parse/login. - נדרשת פעולה שדורשת Master Key — כתיבה ל‑
_Timeline, מחיקת קובץ, דגליskipTriggers/skipTimelineב‑Create-Many? → Master Key, ממנהל סודות, בצד שרת בלבד. - אחרת → API Key. זו ברירת המחדל לשירותי צד שרת, כי אפשר לבטל אותה נקודתית.
1 · Application Id בלבד — הדלת הציבורית
Section titled “1 · Application Id בלבד — הדלת הציבורית”זו הדרך היחידה שבה קוד אנונימי בדפדפן יכול לכתוב למערכת:
await fetch(`https://api.mbapps.co.il/functions/${APP_ID}/getlead`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Parse-Application-Id': APP_ID }, body: JSON.stringify({ PhoneNumber: '0501234567', Email: 'a@b.co.il' }),});כתיבה לטבלה סגורה בפני קריאה אנונימית: POST /parse/classes/<Table> עם ה‑Application Id בלבד מוחזר עם
{"code":119,"error":"This action is not allowed without a valid CAPTCHA"} — גם אחרי שפתחתם את הרשאות הטבלה ל‑create: {"*": true}.
שער ה‑CAPTCHA יושב לפני בדיקת ההרשאות, ולכן פתיחת ההרשאות לא קונה כלום מלבד חשיפה — הקריאה האנונימית כן נפתחת, והכתיבה עדיין נכשלת.
2 · API Key — לשירותים בצד שרת
Section titled “2 · API Key — לשירותים בצד שרת”הפקה: תפריט המשתמש ← סביבת פיתוח ← Databases ← המערכת שלכם ← Settings ← בלוק API Keys ← + Add Key ← שם ← Save.
curl -sS "https://api.mbapps.co.il/parse/classes/Sales?limit=5" \ -H "X-Parse-Application-Id: {appId}" \ -H "X-Parse-API-Key: {apiKey}"const APP_ID = "{appId}";const API_KEY = "{apiKey}";
const res = await fetch("https://api.mbapps.co.il/parse/classes/Sales?limit=5", { headers: { "X-Parse-Application-Id": APP_ID, "X-Parse-API-Key": API_KEY, },});const data = await res.json();import requests
APP_ID = "{appId}"API_KEY = "{apiKey}"
res = requests.get( "https://api.mbapps.co.il/parse/classes/Sales", headers={ "X-Parse-Application-Id": APP_ID, "X-Parse-API-Key": API_KEY, }, params={"limit": 5},)data = res.json()$appId = "{appId}";$apiKey = "{apiKey}";
$ch = curl_init();curl_setopt_array($ch, [ CURLOPT_URL => "https://api.mbapps.co.il/parse/classes/Sales?limit=5", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-Parse-Application-Id: $appId", "X-Parse-API-Key: $apiKey", ],]);$response = curl_exec($ch);curl_close($ch);שלוש עובדות שכדאי לדעת מראש:
- המפתח לא מוגבל בהיקף. הוא קורא וכותב בכל טבלה — כולל
_User,_Timelineו‑Config— והכתיבות שלו מתועדות בזהותMaster. ההבדל היחיד מ‑Master Key הוא שאפשר לבטל אותו לבד (Revoke) בלי לגעת בשאר. - הוא תקף רק תחת שם הכותרת שלו. אותו ערך בכותרת
X-Parse-Master-Keyנחשב לפרטי גישה שגויים ומוחזר ב‑{"code":119,"error":"Permission denied for action find on class …"}. - שדה ה‑
Nameנשמר — תנו למפתח שם משמעותי כבר בהפקה. זה מה שיאפשרRevokeנקודתי בעוד חצי שנה.
3 · Session Token — הרשאות של משתמש אמיתי
Section titled “3 · Session Token — הרשאות של משתמש אמיתי”כשצריך גבול הרשאות אמיתי (פורטל לקוחות, אפליקציה פנימית שבה כל משתמש רואה את שלו), מתחברים בשם המשתמש:
curl -sS -X POST "https://api.mbapps.co.il/parse/login" \ -H "X-Parse-Application-Id: {appId}" \ -H "Content-Type: application/json" \ -d '{ "username": "user@company.co.il", "password": "********" }'const APP_ID = "{appId}";
const res = await fetch("https://api.mbapps.co.il/parse/login", { method: "POST", headers: { "X-Parse-Application-Id": APP_ID, "Content-Type": "application/json", }, body: JSON.stringify({ username: "user@company.co.il", password: "********", }),});const data = await res.json();import requests
APP_ID = "{appId}"
res = requests.post( "https://api.mbapps.co.il/parse/login", headers={ "X-Parse-Application-Id": APP_ID, "Content-Type": "application/json", }, json={ "username": "user@company.co.il", "password": "********", },)data = res.json()$appId = "{appId}";
$payload = json_encode([ "username" => "user@company.co.il", "password" => "********",]);$ch = curl_init();curl_setopt_array($ch, [ CURLOPT_URL => "https://api.mbapps.co.il/parse/login", CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-Parse-Application-Id: $appId", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => $payload,]);$response = curl_exec($ch);curl_close($ch);{ "objectId": "g7y9tkhB7O", "username": "user@company.co.il", "email": "user@company.co.il", "name": "ישראל ישראלי", "createdAt": "2022-01-01T12:23:45.678Z", "updatedAt": "2022-01-01T12:23:45.678Z", "_failed_login_count": 0, "last_success_login": { "__type": "Date", "iso": "2026-08-23T09:01:59.000Z" }, "ACL": { "g7y9tkhB7O": { "read": true, "write": true } }, "sessionToken": "r:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}createdBy / updatedBy חוזרים גם הם; הטוקן הוא מחרוזת בת 34 תווים שמתחילה ב‑r:. שם משתמש או סיסמה שגויים מוחזרים ב‑HTTP 404 עם {"code":101,"error":"Invalid username/password."}.
מכאן והלאה מוסיפים לכל קריאה:
הגישה מוגבלת לתפקידים של המשתמש ולהרשאות ברמת הטבלה. ניתוק: POST /parse/logout עם X-Parse-Application-Id + X-Parse-Session-Token.
מדיניות סיסמאות של המוצר: הסיסמה חייבת לעמוד ב‑
(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,} — מינימום 8 תווים, אות קטנה, אות גדולה וספרה. הפרה מוחזרת ב‑{"code":142,"error":"Password does not meet the Password Policy requirements."}.
ה‑username אמור להיות כתובת אימייל — זו מוסכמת מוצר שכל זרימות ההתחברות והשחזור מניחות, אבל השרת אינו אוכף אותה: username שאינו אימייל מתקבל.
4 · Master Key — גישה מלאה, עוקפת כל הרשאה
Section titled “4 · Master Key — גישה מלאה, עוקפת כל הרשאה”X-Parse-Application-Id: {appId}X-Parse-Master-Key: {masterKey}עוקף כל הרשאה ברמת הטבלה וברמת הרשומה. פעולות מסוימות דורשות אותו:
| הפעולה | למה |
|---|---|
מחיקת קובץ (DELETE /parse/files/<name>) |
אנונימי מקבל unauthorized: master key is required |
כתיבה ל‑_Timeline |
אפשרית עם Master Key בלבד — וזו מגבלת ביקורת, ראו יומנים |
skipTriggers / skipTimeline בכלי Create-Many |
הדגלים מכובדים רק באימות Master Key |
קריאת סכימות של _Role / _Session |
בשכבת ה‑MCP Get-Schema מחזיר עליהן {} |
ומה שלא דורש Master Key, בניגוד למה שנהוג לחשוב: טבלת Config נקראת גם עם API Key וגם עם Session Token של משתמש מורשה (אנונימי ומשתמש בלי תפקיד מקבלים 119). היא הייתה חסומה בשכבת ה‑MCP — Error: Table is restricted — בגרסאות שרת ישנות; ההגבלה הוסרה, ו‑Get-Schema / Get-Data / Create-Data עליה עובדים גם משם. גם האגרגציה ב‑REST — GET /parse/classes-aggregate/<Table> — עובדת עם API Key ועם Session Token של משתמש מורשה; אנונימי מקבל 119. הנתיב הגנרי /parse/aggregate/ אינו קיים בפריסה — 404, ראו אגרגציות.
אותו מפתח, שכבה אחרת — MCP
Section titled “אותו מפתח, שכבה אחרת — MCP”שכבת ה‑MCP אינה עולם נפרד מבחינת אימות: אותו API Key שנשלח ב‑REST נשלח שם, באותו שם כותרת בדיוק.
| מצב | מה הלקוח שולח | הזהות בשרת | מודל ההרשאות |
|---|---|---|---|
| Application Id + API Key | X-Parse-Application-Id + X-Parse-API-Key |
משתמש הדמה Master |
ללא — עוקף כל הרשאת טבלה |
| התחברות משתמש (OAuth 2.1) | Authorization: Bearer <token> |
משתמש ה‑CRM שנכנס | התפקיד שלו בתוספת הרשאות ה‑MCP שלו; לעולם לא מעבר לתפקיד הבסיס |
שלוש נקודות שמפתיעות מפתחים:
- המפתח תקף רק תחת שם הכותרת שלו — גם כאן. אותו ערך ב‑
X-Parse-Master-Key= פרטי גישה שגויים. - למשתמשים אין גישת MCP כברירת מחדל — גם לא ל‑owner. היא ניתנת פרטנית בלשונית MCP Permissions של כרטיס המשתמש (סביבת הפיתוח ← Databases ← המערכת ← Users ← המשתמש): ארבע תיבות —
mcp:view,mcp:create,mcp:update,mcp:edit-page-and-schema— כולן כבויות במערכת חדשה. המסך עצמו מציין שההרשאות כפופות להרשאות הטבלה של המשתמש ושהשימוש ב‑MCP תלוי בתוכנית המנוי. - חיבור אחד = מערכת אחת. ניתוב הפרטים קורה בהגדרת החיבור, לא בקריאה.
איך נראה כשל אימות
Section titled “איך נראה כשל אימות”| מה קרה | מה תראו |
|---|---|
| כותרת אימות חסרה לגמרי (MCP) | Authorization header is required |
| פרטי גישה שגויים (MCP) | HTTP 200 ותשובת הכלי Permission denied for action find on class … |
| Session Token פג/לא תקין (REST) | {"code":209,"error":"invalid session token"} — HTTP 400 |
שם משתמש או סיסמה שגויים ב‑POST /parse/login |
{"code":101,"error":"Invalid username/password."} — HTTP 404 |
| API Key / Master Key מבוטל או שגוי (REST) | {"code":119,"error":"Permission denied for action find on class …"} — זהה לקריאה בלי הרשאה |
| כתיבה אנונימית ל‑REST | {"code":119,"error":"This action is not allowed without a valid CAPTCHA"} |
| קריאה בלי הרשאה (REST) | {"code":119,"error":"Permission denied for action find on class Accounts."} — אותו קוד, הודעה אחרת |
| שם שדה לא חוקי | {"code":105,"error":"Invalid field name: bl!ng."} |
| רשומה לא נמצאה — או שההרשאות מסתירות אותה | {"code":101,"error":"Object not found."} |
| סיסמה שאינה עומדת במדיניות | {"code":142,"error":"Password does not meet the Password Policy requirements."} |
סיכום מדיניות
Section titled “סיכום מדיניות”- בדפדפן: רק Application Id, ורק מול
getlead/web2table. - בשרת: API Key (מועדף: ניתן לביטול) או Master Key, מתוך מנהל סודות.
- בשם משתמש: Session Token, כשההרשאות אמורות להיות של המשתמש ולא של המערכת.
- לסוכני AI: ראו שרת ה‑MCP: שם יש גם מסלול OAuth 2.1 שקושר את החיבור למשתמש אמיתי.
- בכל מקום: מפתח לכל צרכן, כדי שביטול יהיה נקודתי.
המשך מכאן
Section titled “המשך מכאן”- סביבות וגישה — מאיפה מוציאים את הפרטים, ומה זה בכלל “המערכת שלי”
- משתמשים וסשנים — התחברות, 209, ומדיניות הסיסמאות
- שגיאות ופתרון תקלות — כל קוד ומה עושים איתו
- getlead — הדלת הציבורית, בפירוט