הדף הזה רלוונטי ל-Apigee ול-Apigee Hybrid.
לעיון במסמכי התיעוד של
Apigee Edge
במאמר הזה נסביר איך להשתמש בהיקפי הרשאות של OAuth 2.0 ולאכוף אותם ב-Apigee.
מהו היקף הרשאות OAuth2?
היקפי OAuth 2.0 מאפשרים להגביל את רמת הגישה שניתנת לאסימון גישה. לדוגמה, יכול להיות שאסימון גישה שהונפק לאפליקציית לקוח יקבל הרשאת קריאה וכתיבה למשאבים מוגנים, או רק הרשאת קריאה. אתם יכולים להטמיע את ממשקי ה-API כדי לאכוף כל היקף או שילוב של היקפים שתרצו. לכן, אם לקוח מקבל טוקן עם היקף קריאה ומנסה לקרוא לנקודת קצה ל-API שנדרשת לה גישת כתיבה, הקריאה תיכשל.
בנושא הזה נסביר איך מוקצים היקפי הרשאות לאסימוני גישה ואיך Apigee אוכף היקפי הרשאות של OAuth 2.0. אחרי שתקראו את הנושא הזה, תוכלו להשתמש בהיקפים בביטחון.
איך מוקצים היקפים לאסימוני גישה?
כש-Apigee יוצר אסימון גישה, הוא עשוי להקצות לו היקף. כדי להבין איך זה קורה, קודם צריך להכיר את הישויות הבאות ב-Apigee: מוצרי API, מפתחים ואפליקציות למפתחים. למבוא, ראו מבוא לפרסום. מומלץ לעיין בחומר הזה לפני שממשיכים.
אסימון גישה הוא מחרוזת ארוכה של תווים שנראים אקראיים, שמאפשרת ל-Apigee לאמת בקשות API נכנסות (אפשר לחשוב על זה כעל תחליף לפרטי כניסה רגילים של שם משתמש וסיסמה). מבחינה טכנית, האסימון הוא מפתח שמפנה לאוסף של מטא-נתונים שנראה כך:
{ "issued_at" : "1416962591727", "application_name" : "0d3e1d41-a59f-4d74-957e-d4e3275d4781", "scope" : "A", "status" : "approved", "api_product_list" : "[scopecheck1-bs0cSuqS9y]", "expires_in" : "1799", //--in seconds "developer.email" : "scopecheck1-AdBmANhsag@apigee.com", "organization_id" : "0", "token_type" : "BearerToken", "client_id" : "eTtB7w5lvk3DnOZNGReBlvGvIAeAywun", "access_token" : "ODm47ris5AlEty8TDc1itwYPe5MW", "organization_name" : "wwitman", "refresh_token_expires_in" : "0", //--in seconds "refresh_count" : "0" }
המטא-נתונים של האסימון כוללים את המחרוזת של אסימון הגישה בפועל, פרטי התפוגה, זיהוי של אפליקציית המפתח, המפתח והמוצרים שמשויכים לאסימון. תוכלו לראות שהמטא-נתונים כוללים גם את המאפיין scope (היקף).
איך הטוקן מקבל את ההיקף שלו?
הדבר הראשון שחשוב לזכור כדי להבין את ההיקף הוא שלכל מוצר באפליקציה של מפתח יכולים להיות אפס או יותר היקפים שמשויכים אליו. אפשר להקצות את ההיקפים האלה כשיוצרים את המוצר, או להוסיף אותם מאוחר יותר. הם מופיעים כרשימה של שמות ונכללים ב'מטא-נתונים' שמשויכים לכל מוצר.
כשיוצרים אפליקציה למפתחים ומוסיפים לה מוצרים, מערכת Apigee בודקת את כל המוצרים באפליקציה למפתחים ויוצרת רשימה של כל ההיקפים של המוצרים האלה (רשימת ההיקפים הראשית או הגלובלית של האפליקציה – איחוד של כל ההיקפים המוכרים).
כשאפליקציית לקוח מבקשת אסימון גישה מ-Apigee, היא יכולה לציין אילו היקפי הרשאות היא רוצה לשייך לאסימון הזה. לדוגמה, בבקשה הבאה מוגדר היקף ההרשאה 'A'. כלומר, הלקוח מבקש משרת ההרשאות (Apigee) ליצור אסימון גישה עם היקף הרשאות A (שנותן לאפליקציה הרשאה להפעיל ממשקי API עם היקף הרשאות A). האפליקציה שולחת בקשת POST כזו:
curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG \ -H content-type:application/x-www-form-urlencoded \ https://apitest.acme.com/oauth/token?grant_type=client_credentials&scope=A
מה קורה
כש-Apigee מקבל את הבקשה הזו, הוא יודע איזו אפליקציה שולחת את הבקשה ואיזו אפליקציית פיתוח הלקוח רשם (מזהה הלקוח ומפתחות הסוד של הלקוח מקודדים בכותרת של אימות בסיסי). מכיוון שפרמטר השאילתה scope כלול, מערכת Apigee צריכה להחליט אם לאף אחד ממוצרי ה-API שמשויכים לאפליקציה של המפתח יש היקף 'A'. אם כן,
נוצר אסימון גישה עם ההיקף A. דרך נוספת להסתכל על זה היא שפרמטר השאילתה scope הוא סוג של מסנן. אם אפליקציית המפתחים מזהה את היקפי ההרשאות A, B ו-X, ופרמטר השאילתה מציין scope=X Y Z, רק היקף ההרשאות X יוקצה לאסימון.
מה קורה אם הלקוח לא מצרף פרמטר של היקף? במקרה כזה, Apigee יוצר טוקן שכולל את כל ההיקפים שהאפליקציה למפתחים מזהה. חשוב להבין שההתנהגות שמוגדרת כברירת מחדל היא החזרת טוקן גישה שמכיל את איחוד כל ההיקפים של כל המוצרים שנכללים באפליקציה למפתחים.
אם לא צוינו היקפי הרשאות לאף אחד מהמוצרים שמשויכים לאפליקציה של המפתח, אבל לאסימון יש היקף הרשאות, הקריאות שמתבצעות באמצעות האסימון הזה ייכשלו.
נניח שאפליקציית מפתח מזהה את היקפי ההרשאות הבאים: A B C D. זו רשימת ההיקפים הראשית של האפליקציה. יכול להיות שלמוצר אחד באפליקציה יש היקף A ו-B, ולמוצר שני יש היקף C ו-D, או כל שילוב אחר. אם הלקוח לא מציין פרמטר scope (או אם הוא מציין פרמטר היקף ללא ערך), יינתן לטוקן כל ארבעת ההיקפים: A, B, C ו-D. שוב, האסימון מקבל קבוצה של היקפי הרשאות שהיא איחוד של כל היקפי ההרשאות שהאפליקציה של המפתח מזהה.
יש עוד מקרה שבו התנהגות ברירת המחדל היא להחזיר אסימון גישה עם כל ההיקפים המוכרים, והוא כשמדיניות GenerateAccessToken (מדיניות Apigee שמפיקה אסימוני גישה) לא מציינת רכיב <Scope>.
לדוגמה, הנה מדיניות GenerateAccessToken שבה מצוין <Scope>
is. אם רכיב <Scope> חסר (או אם הוא קיים אבל ריק), תתבצע ההתנהגות שמוגדרת כברירת מחדל.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-GenerateAccessToken"> <DisplayName>OAuthV2 - Generate Access Token</DisplayName> <Attributes> <Attribute name='hello' ref='system.time' display='false'>value1</Attribute> </Attributes> <Scope>request.queryparam.scope</Scope> <GrantType>request.formparam.grant_type</GrantType> <ExternalAuthorization>false</ExternalAuthorization> <Operation>GenerateAccessToken</Operation> <SupportedGrantTypes> <GrantType>client_credentials</GrantType> </SupportedGrantTypes> <GenerateResponse enabled="true"/> </OAuthV2>
איך נאכפים טווחי ההרשאות?
קודם כל, חשוב לזכור שב-Apigee, אסימוני גישה מאומתים באמצעות מדיניות OAuthV2 (בדרך כלל ממוקמת בתחילת זרימת הנתונים של שרת proxy). במדיניות צריך לציין את הפעולה VerifyAccessToken. בואו נבחן את המדיניות הזו:
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
<DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<Scope>A</Scope> <!-- Optional: space-separated list of scope names. -->
<GenerateResponse enabled="true"/>
</OAuthV2>שימו לב לרכיב <Scope>. הוא משמש לציון ההיקפים שהמדיניות תקבל.
בדוגמה הזו, המדיניות תצליח רק אם אסימון הגישה כולל את ההיקף A. אם הרכיב <Scope> הזה מושמט או אם אין לו ערך, המדיניות מתעלמת מההיקף של אסימון הגישה.
עכשיו, עם היכולת לאמת אסימוני גישה על סמך היקף, אתם יכולים לתכנן את ממשקי ה-API שלכם כך שיאכפו היקפים ספציפיים. כדי לעשות את זה, צריך לעצב תהליכים מותאמים אישית עם מדיניות VerifyAccessToken מבוססת-היקף שמצורפת אליהם.
נניח של-API שלכם מוגדר תהליך לנקודת הקצה /resourceA:
<Flow name="resourceA">
<Condition>(proxy.pathsuffix MatchesPath "/resourceA") and (request.verb = "GET")</Condition>
<Description>Get a resource A</Description>
<Request>
<Step>
<Name>OAuthV2-VerifyAccessTokenA</Name>
</Step>
</Request>
<Response>
<Step>
<Name>AssignMessage-CreateResponse</Name>
</Step>
</Response>
</Flow>כשתהליך העבודה הזה מופעל (מתקבלת בקשה עם /resourceA בסיומת של נתיב), המדיניות OAuthV2-VerifyAccessTokenA נקראת באופן מיידי. המדיניות הזו בודקת שאסימון הגישה תקף, ומחפשת את ההיקפים שהאסימון תומך בהם. אם המדיניות מוגדרת כמו בדוגמה שלמטה, עם <Scope>A</Scope>, המדיניות תפעל רק אם לטוקן הגישה יש היקף 'A'. אחרת, תוחזר שגיאה.
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
<DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<Scope>A</Scope>
<GenerateResponse enabled="true"/>
</OAuthV2>לסיכום, מפתחי API אחראים לעיצוב של אכיפת היקף ההרשאות בממשקי ה-API שלהם. הם עושים זאת על ידי יצירת תהליכים מותאמים אישית לטיפול בהיקפים ספציפיים, וצירוף מדיניות VerifyAccessToken כדי לאכוף את ההיקפים האלה.
דוגמאות לקוד
לבסוף, נבחן כמה קריאות לדוגמה ל-API כדי להמחיש איך טוקנים מקבלים היקפי הרשאה ואיך היקפי הרשאה נאכפים.
מקרה ברירת מחדל
נניח שיש לכם אפליקציית מפתחים עם מוצרים, ואיחוד ההיקפים של המוצרים האלה הוא: A, B ו-C. הקריאה הזו ל-API מבקשת אסימון גישה, אבל לא מציינת פרמטר של שאילתת היקף.
curl -X POST -H content-type:application/x-www-form-urlencoded \ https://apitest.acme.com/scopecheck1/token?grant_type=client_credentials
במקרה כזה, לטוקן שנוצר יוקצו ההיקפים A, B ו-C (התנהגות ברירת המחדל). המטא-נתונים של האסימון ייראו בערך כך:
{ "issued_at" : "1417016208588", "application_name" : "eb1a0333-5775-4116-9eb2-c36075ddc360", "scope" : "A B C", "status" : "approved", "api_product_list" : "[scopecheck1-yEgQbQqjRR]", "expires_in" : "1799", //--in seconds "developer.email" : "scopecheck1-yxiuHuZcDW@apigee.com", "organization_id" : "0", "token_type" : "BearerToken", "client_id" : "atGFvl3jgA0pJd05rXKHeNAC69naDmpW", "access_token" : "MveXpj4UYXol38thNoJYIa8fBGlI", "organization_name" : "wwitman", "refresh_token_expires_in" : "0", //--in seconds "refresh_count" : "0" }
נניח שיש לכם נקודת קצה ל-API עם היקף הרשאות 'A' (כלומר, הפונקציה VerifyAccessToken דורשת את היקף ההרשאות 'A'). זו המדיניות VerifyAccessToken:
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
<DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<Scope>A</Scope>
<GenerateResponse enabled="true"/>
</OAuthV2>הנה דוגמה לקריאה לנקודת קצה שמחילה את היקף A:
curl -X GET -H Authorization: Bearer MveXpj4UYXol38thNoJYIa8fBGlI \ https://apitest.acme.com/scopecheck1/resourceA
קריאת ה-GET הזו מסתיימת בהצלחה:
{
"hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
}הפעולה מצליחה כי מדיניות VerifyAccessToken שמופעלת כשקוראים לנקודת הקצה דורשת הרשאה A, ואסימון הגישה קיבל הרשאות A, B ו-C – התנהגות ברירת המחדל.
סינון בקשות תמיכה
נניח שיש לכם אפליקציה למפתחים עם מוצרים בהיקפים A, B, C ו-X. שולחים בקשה לאסימון גישה וכוללים את פרמטר השאילתה scope, כך:
curl -i -X POST -H content-type:application/x-www-form-urlencoded \ 'https://apitest.acme.com/oauth/token?grant_type=client_credentials&scope=A X'
במקרה כזה, הטוקן שייווצר יקבל את ההיקפים A ו-X, כי שניהם היקפים תקפים. חשוב לזכור שאפליקציית המפתח מזהה את ההיקפים A, B, C ו-X. במקרה כזה, אתם מסננים את רשימת מוצרי ה-API על סמך ההיקפים האלה. אם למוצר יש היקף A או X, אפשר להגדיר נקודות קצה של API שיאכפו את ההיקפים האלה. אם למוצר אין היקף A או X (נניח שיש לו היקפים B, C ו-Z), אי אפשר לקרוא ל-API שמחיל היקפים A או X באמצעות הטוקן.
כשמפעילים את ה-API עם הטוקן החדש:
curl -X GET -H Authorization: Bearer Rkmqo2UkEIyIBCrtro1QpIG \ https://apitest.acme.com/scopecheck1/resourceX
אסימון הגישה מאומת על ידי proxy ל-API. לדוגמה:
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenX">
<DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<Scope>A X</Scope>
<GenerateResponse enabled="true"/>
</OAuthV2>הפעלת ה-GET מצליחה ומוחזרת תשובה. לדוגמה:
{
"hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
}
הבקשה מצליחה כי מדיניות VerifyAccessToken דורשת את ההרשאות A או X, ואסימון הגישה כולל את ההרשאות A ו-X. כמובן, אם הרכיב <Scope> היה מוגדר לערך B, הקריאה הזו הייתה נכשלת.
סיכום
חשוב להבין איך Apigee מטפל בהיקפי הרשאות של OAuth 2.0. הנה כמה נקודות מרכזיות:
- אפליקציה של מפתח 'מזהה' את האיחוד של כל ההיקפים שהוגדרו לכל המוצרים שלה.
- כשאפליקציה מבקשת אסימון גישה, היא יכולה לציין את היקפי ההרשאות שהיא רוצה לקבל. מערכת Apigee (שרת ההרשאות) קובעת אילו היקפי הרשאות היא תעניק בפועל לאסימון הגישה על סמך (א) היקפי ההרשאות המבוקשים ו-(ב) היקפי ההרשאות שמזוהים על ידי אפליקציית המפתחים.
- אם Apigee לא מוגדר לבדיקת היקף (הרכיב
<Scope>חסר במדיניות VerifyAccessToken או שהוא ריק), קריאה ל-API תצליח כל עוד ההיקף שמוטמע בטוקן הגישה תואם לאחד ההיקפים שמזוהים על ידי אפליקציית המפתח הרשומה (אחד ההיקפים ברשימת ההיקפים 'הראשית' של האפליקציה). - אם לטוקן גישה לא משויכים היקפי הרשאה, הוא יצליח רק במקרים שבהם Apigee לא מתייחס להיקף ההרשאה (הרכיב
<Scope>חסר במדיניות VerifyAccessToken או שהוא ריק).