אפליקציות OAuth
רישום אפליקציית OAuth, הפניית משתמשים למסך ההסכמה של Nodaro, החלפת הקוד באסימון גישה ל-90 ימים וקריאות ל-API בשם כל משתמש.
זמין ב-Nodaro Cloud · מהדורת Business
אפליקציית OAuth מאפשרת למוצר שלכם לקרוא ל-API של Nodaro בשם משתמשי Nodaro אחרים. כל משתמש מאשר את האפליקציה שלכם במסך הסכמה, השרת שלכם מחליף את הקוד שמתקבל באסימון גישה, וכל קריאה עם האסימון הזה פועלת בשם אותו משתמש, בגבולות ההרשאות שהוא אישר. Nodaro מממש את זרימת ה-authorization code הסטנדרטית של OAuth 2.0, עם PKCE ללקוחות שלא יכולים לשמור סוד.
יישומי מפתחים זמינים ב-Nodaro Cloud ובהתקנות של מהדורת Business.
OAuth או אסימון API אישי
| מה אתם בונים | במה להשתמש | מבנה האסימון |
|---|---|---|
| סקריפט, משימת cron, משימת CI או צד שרת שמשתמש בחשבון שלכם | אסימון API אישי | ndr_ ואחריו 64 תווים הקסדצימליים |
| מוצר מקוון שלמשתמשים שלו יש חשבונות Nodaro משלהם | אפליקציית OAuth | ndr_app_ ואחריו 64 תווים הקסדצימליים |
השתמשו באסימון API אישי כשרק החשבון שלכם מזדהה, ואין לכם צורך במסך הסכמה או בביטול גישה לכל משתמש בנפרד. ראו את דף ה-API אימות.
השתמשו ב-OAuth במקרים האלה:
- אתם בונים מוצר מקוון, כמו אפליקציית ווב, SaaS או מרקטפלייס, ולמשתמשים שלכם יש חשבונות Nodaro משלהם.
- כל משתמש נותן לאפליקציה שלכם רק חלק ממה שהחשבון שלו יכול לעשות.
- כל משתמש יכול לנתק את האפליקציה שלכם בכל רגע, בלי להשפיע על אפליקציות אחרות.
איך הזרימה עובדת
- המשתמש לוחץ על חיבור ל-Nodaro באתר שלכם.
- האתר שלכם מפנה את הדפדפן לדף
/oauth/authorizeשל Nodaro, עם ה-client_id, ה-redirect_uri, ה-scopeוה-stateשלכם. - Nodaro מציג את מסך ההסכמה, אחרי התחברות אם צריך. המסך מציג את השם, הלוגו וההרשאות המבוקשות של האפליקציה שלכם, ואת החשבון שייתן את הגישה. הכפתור שימוש בחשבון אחר מנתק את המשתמש מהחשבון וחוזר לאותו מסך.
- המשתמש לוחץ על אישור, ו-Nodaro יוצר authorization code חד־פעמי.
- הדפדפן חוזר ל-
redirect_uriשלכם עם?code=...&state=.... - השרת שלכם מחליף את הקוד באסימון גישה ב-
POST /v1/oauth/token, עם ה-client_idוה-client_secretשלכם. - השרת שלכם קורא ל-API של Nodaro בשם המשתמש, עם
Authorization: Bearer ndr_app_....
רישום האפליקציה שלכם
פתיחת הדף יישומי מפתחים
במופע של Nodaro שאליו אתם מכוונים, פתחו את הגדרות › יישומי מפתחים (/settings/developer-apps) ולחצו על יצירת יישום.
מילוי הטופס
הזינו את השם, את כתובות ההפניה ואת ההרשאות. השדות מתוארים בטבלה שלמטה.
שמירת סוד הלקוח
תיבת הדו־שיח היישום נוצר מציגה בשדה מזהה לקוח את מזהה הלקוח, שמתחיל ב-app_, ובשדה סוד לקוח את סוד הלקוח, שמתחיל ב-sec_. הסוד מוצג פעם אחת בלבד. העתיקו אותו למאגר הסודות שלכם לפני שאתם סוגרים את תיבת הדו־שיח: Nodaro שומר רק גיבוב שלו ולא יכול להציג אותו שוב.
| שדה | חובה | כללים |
|---|---|---|
| שם | כן | 1–100 תווים. מוצג במסך ההסכמה. |
| תיאור | לא | עד 500 תווים. מוצג מתחת לשם במסך ההסכמה. |
| כתובות הפניה | כן | 1–10, אחת בכל שורה. כל אחת היא כתובת https://, או כתובת http://localhost לפיתוח. Nodaro משווה אותן בייט אחר בייט, ותווים כלליים לא נתמכים. |
| מקורות מורשים | לא | עד 5 origins, כל אחד בלי נתיב, בלי מחרוזת שאילתה ובלי fragment. נדרשים רק אם הפרונטאנד שלכם קורא ל-Nodaro מדפדפן (CORS). |
| הרשאות מבוקשות | כן | לפחות אחת. זה המקסימום שהאפליקציה שלכם יכולה לבקש אי פעם: משתמשים יכולים לאשר פחות, והאפליקציה אף פעם לא יכולה לבקש יותר. |
| כתובת דף הבית, כתובת הלוגו | לא | מגדירים אותן בדף של האפליקציה אחרי שיוצרים אותה. כל אחת היא כתובת https:// או http://localhost. לוגו מרובע נראה הכי טוב. |
ניהול האפליקציה
- החליפו את הסוד בדף של האפליקציה כשאתם מאבדים אותו, או כנוהל אבטחה שגרתי. הסוד הישן מפסיק לעבוד מיד, ולכן עדכנו מיד את התצורה של כל שירות שרץ.
- מחקו את האפליקציה כדי לבטל כל אסימון גישה שניתן לה. משתמשים שאישרו אותה יצטרכו לחבר אותה שוב.
- חמש אפליקציות לכל משתמש. לקוחות MCP שרשמו את עצמם מופיעים באותה רשימה, אבל לא נספרים במגבלה.
- מקוד, המשאב
client.developerAppsשל ה-SDK יוצר, מעדכן ומוחק אפליקציות ומחליף את הסודות שלהן. ראו את הדף SDK ל-TypeScript.
הרשאות
כל הרשאה (scope) היא היתר אחד שהאפליקציה שלכם מבקשת. בקשו רק את ההרשאות שאתם משתמשים בהן: המשתמשים רואים כל הרשאה מבוקשת במסך ההסכמה, ורשימה קצרה זוכה באמון שלהם.
| הרשאה | מה כתוב במסך ההסכמה | מה היא מאפשרת |
|---|---|---|
workflows:read | קריאת התהליכים שלכם | הצגת רשימה, קריאה וייצוא של תהליכים. הצגת רשימה וקריאה של האפליקציות שהמשתמש פרסם, עם נתוני השימוש והרווחים שלהן, וקריאת ברירות המחדל למונטיזציה. |
workflows:write | יצירה ועריכה של תהליכים | יצירה, עדכון, מחיקה, ייבוא והעברה של תהליכים, ויצירת תת־תהליכים. פרסום, שינוי, מחיקה ושחזור של אפליקציות וסימון שלהן כמועדפות, וקביעת ברירות המחדל למונטיזציה. |
workflows:execute | הרצת תהליכים בשמכם | הרצה של תהליכים, של אפליקציות שפורסמו ושל רכיבים שמורים שפורסמו, הרצת רכיבי יצירה בודדים דרך MCP, ושימוש באשף הפרומפטים. ניסיון חוזר של הרצות אפליקציה, רינדור הגרסה הסופית שלהן, שינוי השם שלהן, מחיקה ושחזור שלהן, וקריאה שלהן. |
jobs:read | קריאת מצב ותוצאות של משימות | קריאת משימות, הסטטוס שלהן והתוצאות שלהן, קריאת סשני יצירה, קריאת הרצות אפליקציה, וניהול נקודות קצה של Webhook. |
assets:read | קריאת הנכסים שהעליתם | קריאת הגלריה, ההעלאות, המועדפים, הרצות האפליקציה, הדמויות, המיקומים, האובייקטים והיצורים, והפלטות והמודבורדים של המשתמש. |
assets:write | הוספה, שינוי ומחיקה של פריטים בספרייה שלכם: העלאות, דמויות, פוסטים שמורים, אוספים והערכות שמורות של צמתים | העלאת מדיה, סימון משימות כמועדפות ודירוג שלהן, יצירה ועדכון של דמויות, מיקומים ואובייקטים, כתיבת פלטות ומודבורדים, כתיבת ערכות שמורות, התיקיות שלהן והמועדפים שלהן, ויצירה ותיוק של סשני יצירה. |
credits:read | צפייה ביתרת הקרדיטים שלכם | קריאת יתרת הקרדיטים ותנועות הקרדיטים דרך MCP. אף נתיב REST לא בודק את ההרשאה הזאת. |
apps:read | קריאת יישומים שפורסמו | הצגת רשימה של האפליקציות שהמשתמש פרסם ושל האפליקציות המועדפות עליו, וקריאת הקלטים של אפליקציות. |
pipelines:read | קריאת הפייפליינים שלכם | קריאת פייפליינים של סיפור ← וידאו, הסטטוס שלהם והאישורים שממתינים בהם. |
pipelines:execute | הרצת פייפליינים בשמכם (עלול לצרוך קרדיטים) | התחלת פייפליינים, הרצת השלבים שלהם והסתעפות משלב. |
pipelines:approve | אישור שלבי פייפליין בשמכם | אישור הפלט של שלבים, ושימוש בצ׳אט של השלב ובכלי העזר לסצנות. |
presets:read | קריאת הערכות השמורות שלכם | קריאת הערכות השמורות של המשתמש, תיקיות הערכות והערכות המועדפות. קטלוג הערכות המובנות ציבורי ולא דורש הרשאה. כתיבת ערכות דורשת assets:write. |
workspaces:read | צפייה בסביבות העבודה שאתם חברים בהן | הצגת רשימה של סביבות העבודה של המשתמש. |
workspaces:write | בחירת סביבת העבודה שבה הוא פועל | בחירת סביבת העבודה שבה האפליקציה פועלת. |
- חלק מההרשאות שולטות בגישה לנתיבי REST, חלק בכלי ה-MCP, וחלק בשניהם. שרת ה-MCP מסתיר כל כלי שההרשאה שלו חסרה באסימון.
- אסימון בלי ההרשאה שנתיב דורש נדחה עם
403 insufficient_scope, וההרשאה החסרה מופיעה ב-missingScope. ראו את הסעיף שגיאות. - הרשאות סביבת העבודה אף פעם לא מתווספות לאסימון שהונפק לפני שהיו ארגונים. כדי לתת אותן, המשתמש צריך לאשר שוב את האפליקציה שלכם.
- הרצה של אפליקציה שפורסמה דורשת
workflows:executeכדי להתחיל את ההרצה ו-jobs:readכדי לקרוא את ההתקדמות שלה. קריאת הרצות אפליקציה מתאפשרת גם עםassets:readאוworkflows:execute, ולכן אפליקציה שמתחילה הרצות תמיד יכולה לבדוק את הסטטוס שלהן. - טעינה של אפליקציה שפורסמה עם
GET /v1/app/:slugלא דורשת הרשאה. - ההרשאות חלות רק על אסימונים של אפליקציות OAuth. Nodaro לא בודק הרשאות באסימוני סשן ובאסימוני API אישיים.
ניהול אפליקציות שפורסמו
עם אסימון של אפליקציית OAuth, נתיבי /v1/apps/* ונתיבי המונטיזציה האלה בודקים הרשאה:
| הרשאה | נתיבים |
|---|---|
workflows:write | POST /v1/apps/publish, PATCH ו-DELETE /v1/apps/:appId, POST /v1/apps/:appId/restore, מתג המועדפים POST /v1/apps/favorite ו-PUT /v1/user/monetization-defaults. |
workflows:read או apps:read | GET /v1/apps/mine, GET /v1/apps/by-workflow/:workflowId, GET /v1/apps/favorites ו-GET /v1/apps/browse?favoritesOnly=true. |
workflows:read | GET /v1/apps/:appId/analytics (וגם /analytics/runs), GET /v1/apps/:appId/earnings, GET /v1/user/earnings ו-GET /v1/user/monetization-defaults. |
workflows:execute | POST /v1/app/:slug/run, POST /v1/app/:slug/runs, PATCH ו-DELETE /v1/app/:slug/runs/:runId, POST /v1/app/:slug/runs/:runId/resume, /render-final ו-/restore, DELETE /v1/app/:slug/runs/:runId/permanent ו-POST /v1/component/execute. |
jobs:read, assets:read או workflows:execute | GET /v1/app/:slug/runs, GET /v1/app/:slug/runs/:runId ו-GET /v1/me/archived-runs. |
קטלוג השוק, GET /v1/apps/browse ו-GET /v1/apps/by-slug/:slug/latest-version, לא דורש הרשאה. אסימון בלי ההרשאה נדחה עם 403 insufficient_scope עם missingScope.
הפניית המשתמש למסך ההסכמה
כשהמשתמש לוחץ על חיבור ל-Nodaro, הפנו את הדפדפן לכתובת הזאת:
https://nodaro.example.com/oauth/authorize?
client_id=app_...&
redirect_uri=https://yourapp.com/oauth/callback&
response_type=code&
scope=workflows:read+workflows:execute&
state=<random CSRF token>| פרמטר | כלל |
|---|---|
client_id | מזהה הלקוח של האפליקציה שלכם. |
redirect_uri | בדיוק אחת מכתובות ההפניה הרשומות שלכם, בייט אחר בייט. כתובת שלא תואמת נדחית עם 400 invalid_redirect_uri. |
response_type | תמיד code. מסך ההסכמה דוחה כל ערך אחר. |
scope | ההרשאות שאתם מבקשים, מופרדות ברווחים או ב-+. הן חייבות להיות תת־קבוצה של ההרשאות המבוקשות של האפליקציה. |
state | אסימון אקראי שאתם יוצרים לכל אישור גישה ושומרים בסשן של המשתמש. Nodaro מחזיר אותו בלי שינוי, ואתם חייבים לבדוק אותו. |
צרו את state בשרת שלכם:
import { randomBytes } from "node:crypto"
// In your /connect handler:
const state = randomBytes(32).toString("hex")
req.session.oauthState = state
const url = new URL("https://nodaro.example.com/oauth/authorize")
url.searchParams.set("client_id", process.env.NODARO_CLIENT_ID!)
url.searchParams.set("redirect_uri", "https://yourapp.com/oauth/callback")
url.searchParams.set("response_type", "code")
url.searchParams.set("scope", "workflows:read workflows:execute")
url.searchParams.set("state", state)
res.redirect(url.toString())- אם המשתמש לוחץ על ביטול, Nodaro מפנה ל-
redirect_uriשלכם עםerror=access_denied, עםerror_descriptionועם ה-stateשלכם. התייחסו לביטול כאל תוצאה רגילה, לא כאל תקלה. - אם כתובת ההפניה לא רשומה, מסך ההסכמה מציג דף שגיאה ולא מפנה לשום מקום, גם בלחיצה על ביטול וגם בלחיצה על אישור.
החלפת הקוד באסימון
אחרי שהמשתמש לוחץ על אישור, Nodaro מפנה את הדפדפן לכתובת הקריאה החוזרת שלכם:
https://yourapp.com/oauth/callback?code=ndr_code_...&state=<your state>- בדקו קודם את
state. אם הוא לא תואם לערך שבסשן של המשתמש, עצרו: זו ההגנה מפני זיוף בקשות בין אתרים. - החליפו את הקוד בשרת שלכם. לעולם אל תבצעו את הקריאה הזאת מדפדפן, שבו כל מי שיש לו כלי מפתחים יכול לקרוא את ה-
client_secretשלכם.
import { createClient, StaticTokenAuth } from "@nodaro/sdk"
// The token endpoint is public: your client ID and secret authenticate
// the request, so the client needs no token of its own.
const client = createClient({
baseUrl: "https://nodaro.example.com",
auth: new StaticTokenAuth(""),
})
const tokens = await client.oauth.exchangeCode({
client_id: process.env.NODARO_CLIENT_ID!,
client_secret: process.env.NODARO_CLIENT_SECRET!,
code: req.query.code as string,
redirect_uri: "https://yourapp.com/oauth/callback",
})
// tokens.access_token: "ndr_app_..."
// tokens.scope: the scopes the user granted, separated by spaces
// tokens.expires_in: 7776000 (seconds, that is 90 days)
// tokens.token_type: "Bearer"curl -X POST https://nodaro.example.com/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "app_...",
"client_secret": "sec_...",
"code": "ndr_code_...",
"redirect_uri": "https://yourapp.com/oauth/callback"
}'התגובה משתמשת בשמות השדות הסטנדרטיים של OAuth:
{
"access_token": "ndr_app_...",
"token_type": "Bearer",
"scope": "workflows:read workflows:execute",
"expires_in": 7776000
}- קוד עובד פעם אחת. החלפה שנייה של אותו קוד נדחית עם
400 invalid_grant. - תוקף הקוד פג 10 דקות אחרי שהוא הונפק. החליפו אותו ברגע שהוא מגיע לכתובת הקריאה החוזרת שלכם.
- נקודת הקצה של האסימונים מקבלת גוף בקשה ב-JSON ובקידוד של טופס. לקוחות OAuth סטנדרטיים ששולחים
application/x-www-form-urlencodedעובדים בלי שינוי, בשיטהclient_secret_post.
לקוחות ציבוריים: PKCE
אפליקציות מובייל, אפליקציות של דף יחיד וכלי CLI לא יכולים לשמור client_secret. במקום זה הם משתמשים ב-PKCE. Nodaro תומך רק בשיטה S256; השיטה plain נדחית עם 400 invalid_request.
יצירת verifier ו-challenge
לפני ההפניה, צרו code_verifier אקראי עם אנטרופיה גבוהה. גזרו ממנו את code_challenge: קידוד base64url של גיבוב SHA-256 של ה-verifier.
שליחת ה-challenge עם בקשת ההרשאה
הוסיפו את code_challenge ואת code_challenge_method=S256 לכתובת ההרשאה:
https://nodaro.example.com/oauth/authorize?
client_id=app_...&
redirect_uri=https://yourapp.com/oauth/callback&
response_type=code&
scope=workflows:read+workflows:execute&
state=<random CSRF token>&
code_challenge=<base64url SHA-256 of the verifier>&
code_challenge_method=S256שליחת ה-verifier עם החלפת הקוד באסימון
שלחו code_verifier במקום client_secret:
curl -X POST https://nodaro.example.com/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "app_...",
"code": "ndr_code_...",
"redirect_uri": "https://yourapp.com/oauth/callback",
"code_verifier": "<the original verifier>"
}'לקוח שיכול לשמור סוד רשאי לשלוח גם סוד וגם verifier של PKCE. Nodaro בודק כל אחד מהם שנשלח.
קריאה ל-API עם האסימון
צרו לקוח אחד לכל משתמש, עם אסימון הגישה של אותו משתמש:
import { createClient, StaticTokenAuth } from "@nodaro/sdk"
const userClient = createClient({
baseUrl: "https://nodaro.example.com",
auth: new StaticTokenAuth(tokens.access_token),
})
// Every call acts as the user who authorized your app, within the granted scopes.
const projects = await userClient.projects.list()
const workflows = await userClient.workflows.list(projects.data[0].id)
const run = await userClient.workflows.run(workflows.data[0].id)בלי ה-SDK, שלחו את האסימון בכותרת Authorization: Bearer של כל קריאת REST. נקודות הקצה מפורטות במדריך של ה-REST API.
כשתוקף האסימון פג
אסימון גישה תקף 90 ימים. Nodaro לא מנפיק אסימוני רענון: יש סוג אסימון אחד, מקום אחד לשמור אותו וכלל תפוגה אחד, במחיר של מסך הסכמה כל 90 ימים.
- אחרי שתוקף האסימון פג או שהוא בוטל, קריאות ל-API נדחות עם
401. הפנו את המשתמש שוב ל-/oauth/authorize. - כשהמשתמש מאשר שוב את האפליקציה שלכם, Nodaro מעדכן את אישור הגישה שלו ומנפיק אסימון חדש. אסימונים קודמים נשארים בתוקף עד שהם פגים או מבוטלים, ולכן שמרו רישום של האסימונים שנמצאים בשימוש.
- כדי להוסיף הרשאה, שלחו את המשתמש דרך כתובת ההרשאה עם
scopeרחב יותר. אישור הגישה הקיים מורחב.
שמירה בטוחה של אסימונים
- שמרו את האסימונים בשרת שלכם. לעולם אל תשימו אסימון גישה ב-
localStorage, ב-sessionStorageאו בעוגייה ש-JavaScript יכול לקרוא. - הצפינו את האסימונים באחסון אם הפלטפורמה שלכם תומכת בזה. Nodaro שומר רק גיבוב SHA-256 של כל אסימון, ולכן אסימון יכול לדלוף רק אם מסד הנתונים שלכם דולף.
- לעולם אל תשתפו אסימון בין משתמשים. כל אסימון שייך למשתמש Nodaro אחד; שימוש בו בהקשר של משתמש אחר הוא באג הרשאות.
ביטול אסימון
בטלו אסימון כשהמשתמש מתנתק מהאפליקציה שלכם, מוחק את החשבון שלו בפלטפורמה שלכם או לוחץ על ניתוק Nodaro בהגדרות של האפליקציה שלכם.
await client.oauth.revoke(tokens.access_token)
// { success: true }curl -X POST https://nodaro.example.com/v1/oauth/revoke \
-H "Content-Type: application/json" \
-d '{ "token": "ndr_app_..." }'נקודת הקצה של הביטול תמיד מחזירה 200, גם לאסימון שלא קיים, כך שאף אחד לא יכול להשתמש בה כדי לבדוק אם אסימון שניחש תקף. אחרי ביטול, קריאות עם האסימון נדחות עם 401.
כשהמשתמש מבטל את הגישה
משתמשים יכולים גם לסיים בעצמם את הגישה של האפליקציה שלכם. בדף הגדרות › אפליקציות מחוברות (/settings/connected-apps) מופיעים כל האפליקציות ועוזרי ה-AI שיש להם גישה לחשבון של המשתמש. כל פריט מציג את השם והסוג שלו, מתי הוא חובר, מתי השתמשו בו לאחרונה ואת ההרשאות שיש לו. הכפתור ביטול גישה מבקש אישור, ואז מסיים מיד את אישור הגישה ואת כל האסימונים שהונפקו במסגרתו.
אחרי הביטול, קריאות עם האסימון שלכם נדחות עם 401. טפלו במצב הזה כמו באסימון שתוקפו פג: שלחו את המשתמש שוב דרך מסך ההסכמה.
רק סשן מחובר בדפדפן יכול להציג את אישורי הגישה האלה או לבטל אותם. הנתיבים GET /v1/me/connected-apps ו-POST /v1/me/connected-apps/:id/revoke דוחים אסימון גישה של OAuth ואסימון API אישי עם 401, ולכן אפליקציה לא יכולה לקרוא את הרשימה וגם לא לשנות אותה. כדי לסיים מקוד את הגישה של האפליקציה שלכם, השתמשו בנקודת הקצה של הביטול שלמעלה.
אפליקציית דפדפן שבנויה על ה-SDK קוראת את אישורי הגישה האלה ומבטלת אותם עם client.connectedApps() ועם client.revokeConnectedApp(authorizationId), בעזרת הסשן של המשתמש עצמו (supabaseAuth). עם מפתח API או עם אסימון של אפליקציה, שתי המתודות נכשלות עם 401, ולכן לא ה-CLI ולא שרת ה-MCP מציעים אותן.
שגיאות
נקודת הקצה של האסימונים עונה בשגיאות OAuth סטנדרטיות:
| סטטוס | שגיאה | מתי | מה לעשות |
|---|---|---|---|
400 | invalid_request | גוף הבקשה פגום או ששדה חסר. | תקנו את הבקשה. |
401 | invalid_client, "Unknown client" (לקוח לא מוכר) | ה-client_id לא תואם לאף אפליקציה רשומה. | בדקו את מזהה הלקוח בתצורה שלכם. |
401 | invalid_client, "Bad client_secret" (סוד הלקוח שגוי) | הסוד שגוי, לעיתים קרובות סוד ישן אחרי החלפה. | טענו את הסוד הנוכחי והפעילו מחדש את השירות שלכם. |
400 | invalid_grant | עברו יותר מ-10 דקות מאז שהקוד הונפק, כבר נעשה בו שימוש או שה-redirect_uri שונה מזה שבבקשת ההרשאה. | שלחו את המשתמש שוב דרך מסך ההסכמה, עם כתובות זהות. |
שלב ההרשאה מציג את השגיאות האלה במסך ההסכמה עצמו, ואף פעם לא מפנה איתן:
| סטטוס | קוד | מתי | מה לעשות |
|---|---|---|---|
400 | invalid_redirect_uri | ה-redirect_uri לא רשום לאפליקציה. | הוסיפו את הכתובת בדף של האפליקציה. |
400 | invalid_scope | אחת מההרשאות שהתבקשו לא נמצאת בהרשאות המבוקשות של האפליקציה. | הוסיפו קודם את ההרשאה לאפליקציה. |
404 | invalid_client | ה-client_id לא מוכר, או שהאפליקציה מושעית. | בדקו את מזהה הלקוח ואת הסטטוס של האפליקציה. |
קריאות ל-API עם אסימון הגישה יכולות להיכשל בשגיאות האלה:
| סטטוס | קוד | מתי | מה לעשות |
|---|---|---|---|
401 | unauthorized | תוקף האסימון פג, הוא בוטל או שהוא פגום. | שלחו את המשתמש שוב דרך מסך ההסכמה. |
403 | insufficient_scope | חסרה לאסימון ההרשאה שהנתיב דורש. גוף התגובה מציין אותה ב-missingScope. | שלחו את המשתמש דרך מסך ההסכמה עם ההרשאה הרחבה יותר. |
ה-SDK זורק את מקרה ה-403 כ-ForbiddenError עם missingScope בעל טיפוס, כך שתוכלו להציע הסכמה מחדש בלחיצה אחת:
import { ForbiddenError } from "@nodaro/sdk"
try {
await userClient.workflows.run(workflowId)
} catch (err) {
if (err instanceof ForbiddenError && err.missingScope) {
// Send the user back to /oauth/authorize with the broader scope list.
redirectToConsent({ scopes: [...currentScopes, err.missingScope] })
return
}
throw err
}רשימת בדיקות אבטחה
- HTTPS בכל מקום. מופע ה-Nodaro, האפליקציה שלכם וכל כתובת הפניה משתמשים ב-
https://. הכתובתhttp://localhostמיועדת רק לפיתוח מקומי. - בדקו את
stateבכל קריאה חוזרת. צרו אותו לכל אישור גישה ושמרו אותו בסשן של המשתמש. - שמרו את
client_secretבשרת שלכם. לעולם אל תכללו אותו באפליקציית דפדפן, אל תרשמו אותו ביומן ואל תציגו אותו בהודעת שגיאה. - החליפו את הסוד לפחות פעם בשנה, ומיד אם אתם חושדים בדליפה.
- רשמו רק כתובות הפניה שלכם. רשמו רק את הכתובות שאתם באמת משתמשים בהן.
- בקשו את מספר ההרשאות הקטן ביותר. הוסיפו הרשאה כשאתם בונים את היכולת שצריכה אותה.
- בטלו את האסימון בהתנתקות. קראו לנקודת הקצה של הביטול כשמשתמש מתנתק מהאפליקציה שלכם, כדי שאי אפשר יהיה להשתמש שוב באסימון שלו.
- טפלו ב-
missingScope. הציעו למשתמש הסכמה מחדש, ולא דף כללי של ״אין הרשאה״.
בדיקת הזרימה מקומית
לולאת הבדיקה המהירה ביותר דורשת מופע Nodaro עם יישומי מפתחים, כמו Nodaro Cloud או התקנה של מהדורת Business, ושרת קטן במחשב שלכם שמקבל את הקריאה החוזרת.
רישום אפליקציית בדיקה
צרו אפליקציה עם כתובת ההפניה http://localhost:8080/cb ועם ההרשאות workflows:read, workflows:execute ו-jobs:read.
הרצת שרת לקריאה החוזרת בפורט 8080
import express from "express"
import { createClient, StaticTokenAuth } from "@nodaro/sdk"
const NODARO_URL = "https://app.nodaro.ai" // or your Business edition install
const app = express()
app.get("/cb", async (req, res) => {
const client = createClient({ baseUrl: NODARO_URL, auth: new StaticTokenAuth("") })
const tokens = await client.oauth.exchangeCode({
client_id: process.env.NODARO_CLIENT_ID!,
client_secret: process.env.NODARO_CLIENT_SECRET!,
code: req.query.code as string,
redirect_uri: "http://localhost:8080/cb",
})
res.json(tokens)
})
app.listen(8080)פתיחת כתובת ההרשאה ולחיצה על אישור
פתחו במופע את /oauth/authorize?client_id=app_...&redirect_uri=http://localhost:8080/cb&response_type=code&scope=workflows:read+workflows:execute&state=test123. אחרי שתלחצו על אישור, שרת הקריאה החוזרת יציג את ה-JSON של האסימון.
קריאה לנתיב אמיתי
השתמשו באסימון בנתיב כמו GET /v1/projects/<id>/workflows, ובדקו שהוא מחזיר 200 עם נתונים.
גילוי ורישום דינמי ללקוחות MCP
לקוחות MCP, כמו Claude, ChatGPT ו-Cursor, מוצאים בעצמם את נקודות הקצה של OAuth ויכולים לרשום את עצמם בזמן ריצה, בלי שמישהו ייכנס לדף יישומי מפתחים. את הצד של המשתמש מתאר הדף חיבור לקוח.
מסמכי גילוי
| נקודת קצה | תקן | מטרה |
|---|---|---|
GET /.well-known/oauth-authorization-server | RFC 8414 | איפה מאשרים, מקבלים אסימונים, נרשמים ומבטלים. |
GET /.well-known/oauth-protected-resource | RFC 9728 | קושר את משאב ה-MCP, https://mcp.nodaro.ai/mcp, לשרת ההרשאות שלו. |
כל מסמך זמין גם עם הסיומת /mcp, כי חלק מהלקוחות המחמירים מנסים את הצורה הזאת קודם. כל ארבעת המסמכים זמינים גם במארח של Nodaro וגם במארח של ה-MCP. המנפיק הוא ה-PUBLIC_URL של המופע, https://app.nodaro.ai ב-Nodaro Cloud.
במטא־דאטה של שרת ההרשאות מופיעים:
- נקודות הקצה של ההרשאה, של האסימונים, של הרישום ושל הביטול;
- סוג התגובה
codeוסוג ה-grantauthorization_code; - PKCE בשיטה
S256בלבד; - שיטת האימות
client_secret_postבנקודת הקצה של האסימונים; - כל ההרשאות, ב-
scopes_supported.
רישום לקוחות דינמי
לקוח רושם את עצמו עם POST /v1/oauth/register (RFC 7591) ומקבל client_id שמתחיל ב-ndr_dcr_, ובנוסף client_secret. נקודת הקצה מקבלת עד 10 בקשות לדקה מכל כתובת IP. מנהל השרת של המופע מגדיר את MCP_DYNAMIC_REGISTRATION:
| מצב | התנהגות |
|---|---|
allowlist (ברירת המחדל) | רק לקוחות ששמם מופיע ב-MCP_DCR_ALLOWLIST יכולים להירשם. האחרים נדחים עם 403 client_not_allowed. |
open | כל לקוח יכול להירשם, עד 5 רישומים שלא נעשה בהם שימוש לכל צמד של שם לקוח וכתובות הפניה בתוך 24 שעות (429 too_many_open_registrations). |
off | הרישום מושבת (403 dcr_disabled). במקום זה, מנהל השרת מחלק מזהה לקוח וסוד קבועים. |
לקוח שרשם את עצמו בחר את השם שלו בעצמו, ולכן מסך ההסכמה מזהיר את המשתמש ש-Nodaro לא אימת אותו. ההרשאות שהלקוח מצהיר עליהן הן לידיעה בלבד: ההסכמה של המשתמש היא המחסום האמיתי, והלקוח יכול לבקש כל הרשאה תקפה. את ההגדרות של מנהל השרת מתאר הדף MCP בהתקנה באירוח עצמי.
התוסף ל-Figma בהתקנה באירוח עצמי
התוסף של Nodaro ל-Figma רץ בתוך Figma ולא יכול לקבל הפניה. במקום זה הוא מתחבר בלחיצת יד בסגנון device flow: התוסף מציג למשתמש קוד קצר, המשתמש מאשר את התוסף במסך ההסכמה הרגיל ומקליד את הקוד הזה, ואז התוסף מקבל את האסימון שלו. האסימון הוא אסימון רגיל של יישום מפתחים, עם ההרשאות jobs:read, assets:read, assets:write ו-credits:read, ואפשר לבטל אותו כמו כל אסימון אחר.
כדי לאפשר לתוסף להתחבר להתקנה שלכם:
- רשמו יישום מפתחים, בדף יישומי מפתחים או עם
POST /v1/developer-apps. הוסיפו את<PUBLIC_URL>/v1/oauth/plugin/callbackלכתובות ההפניה שלו, ובקשו את ארבע ההרשאות שלמעלה. - שימו את מזהה הלקוח של האפליקציה ב-
FIGMA_PLUGIN_OAUTH_CLIENT_IDבשרת.
בלי ההגדרה הזאת, כל נתיב חיבור של התוסף מחזיר 503 plugin_connect_not_configured. אם חסרה לאפליקציה כתובת הקריאה החוזרת או הרשאה, הנתיבים מחזירים 503 plugin_connect_misconfigured, ויומן השרת מציין מה חסר.
שאלות נפוצות
מתי צריך OAuth במקום אסימון API אישי?
השתמשו ב-OAuth כשהמוצר שלכם פועל בחשבונות Nodaro של אנשים אחרים, וכל משתמש צריך לאשר את האפליקציה שלכם ולהיות מסוגל לנתק אותה. לסקריפטים ולשרתים שמשתמשים רק בחשבון שלכם, אסימון API אישי פשוט יותר.
לכמה זמן תקף אסימון גישה של OAuth ב-Nodaro?
אסימון גישה של OAuth תקף 90 ימים. Nodaro לא מנפיק אסימוני רענון, ולכן כשתוקף האסימון פג או שהוא מבוטל, קריאות ל-API נדחות עם 401, ואתם שולחים את המשתמש שוב דרך מסך ההסכמה.
האם Nodaro תומך ב-PKCE?
כן, רק בשיטה S256. אפליקציות מובייל, אפליקציות של דף יחיד וכלי CLI שולחים code_challenge בבקשת ההרשאה ואת ה-code_verifier התואם בהחלפת הקוד באסימון, במקום סוד לקוח.
מה קורה אם איבדתי את סוד הלקוח?
Nodaro שומר רק גיבוב של הסוד ולא יכול להציג אותו שוב. החליפו את הסוד בדף של האפליקציה כדי לקבל סוד חדש. הסוד הישן מפסיק לעבוד מיד.
כמה יישומי מפתחים אפשר לרשום?
חמישה לכל משתמש. לקוחות MCP שרושמים את עצמם מופיעים באותה רשימה, אבל לא נספרים במגבלה.
האם משתמש יכול לבטל את הגישה שנתן לאפליקציה שלי?
כן. בדף הגדרות › אפליקציות מחוברות, משתמש יכול לבטל את הגישה של כל אפליקציה שיש לה גישה לחשבון שלו. אישור הגישה וכל אסימון שהונפק במסגרתו מפסיקים לעבוד מיד, והקריאות שלכם נדחות עם 401. שלחו את המשתמש שוב דרך מסך ההסכמה.
דפים קשורים
אימות
SDK ל-TypeScript
חיבור לקוח
סקילים לסוכנים
הטמעת מיני־אפליקציה
עודכן לאחרונה