שימוש בטוקנים של OAuth של צד שלישי

הדף הזה רלוונטי ל-Apigee ול-Apigee Hybrid.

לעיון במסמכי התיעוד של Apigee Edge

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

בדרך כלל, Apigee יוצר ומאחסן אסימון OAuth ומחזיר אותו לאפליקציה שקוראת ל-API. אחר כך האפליקציה שקוראת מציגה את הטוקן הזה בחזרה ל-Apigee כשמבקשים שירות, ו-Apigee – באמצעות מדיניות OAuthV2 עם Operation = VerifyAccessToken – יאמת שהטוקן תקף. במאמר הזה מוסבר איך להגדיר את Apigee כך שיאחסן אסימון OAuth שנוצר במקום אחר, תוך שמירה על אותו חלק של אימות האסימון, בדיוק כמו אם האסימון נוצר על ידי Apigee.

דוגמה

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

מה זה?

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

קצת רקע

בדרך כלל, Apigee יוצר טוקן על ידי יצירת מחרוזת אקראית של אותיות ומספרים. ‫Apigee משייך לטוקן הזה נתונים אחרים, כמו השעה שבה הטוקן הונפק, תאריך התפוגה, רשימת מוצרי ה-API שהטוקן תקף לגביהם וההיקף. כל המידע הזה יכול לחזור בתגובה שנוצרת באופן אוטומטי על ידי מדיניות OAuthV2 שהוגדרה עם Operation = GenerateAccessToken. התגובה אמורה להיראות כך:

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "zBC90HhCGmGlaMBWeZAai2s3za5j",
  "organization_name": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

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

בעזרת השלבים שמתוארים כאן, אפשר להגדיר את Apigee לאחסון אסימון שהערך access_token שלו נוצר על ידי שירות חיצוני. לדוגמה, נניח שיש לכם מערכת חיצונית ל-Apigee שמפיקה טוקנים מהצורה TOKEN-<16 מספרים אקראיים> . במקרה כזה, המטא-נתונים המלאים של הטוקן שמאוחסנים ב-Apigee יכולים להיות:

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "TOKEN-1092837373654221",
  "organization_name": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

במקרה כזה, אפליקציה יכולה לשלוח בקשה ל-proxy ל-API עם אסימון ה-bearer TOKEN-1092837373654221, ו-Apigee יוכל לאמת אותו. אפשר להשתמש בדפוס ייבוא דומה גם עבור קודי הרשאה וטוקנים לרענון.

עכשיו נדבר על אימות פרטי הכניסה של הלקוח

אחת מהדרישות המוקדמות ליצירת אסימון היא אימות הלקוח ששולח את הבקשה. כברירת מחדל, המדיניות OAuthV2/GenerateAccessToken ב-Apigee מאמתת באופן מרומז את פרטי הכניסה של הלקוח. בדרך כלל, בבקשה לאסימון OAuthV2, הערכים client_id ו-client_secret מועברים בכותרת Authorization, מקודדים באמצעות אימות HTTP בסיסי (מחוברים באמצעות נקודתיים, ואז מקודדים ב-base64). המדיניות OAuthV2/GenerateAccessToken ב-Apigee מפענחת את הכותרת הזו, מחפשת את client_id ומוודאת שclient_secret שהועבר תקף עבור client_id. השיטה הזו פועלת אם פרטי הכניסה ידועים ל-Apigee – במילים אחרות, אם יש אפליקציית מפתחים שמאוחסנת ב-Apigee ומכילה פרטי כניסה, שכוללים את הערכים client_id ו-client_secret שצוינו.

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

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

אם רוצים שמדיניות OAuthV2/GenerateAccessToken ב-Apigee תאמת את פרטי הכניסה של הלקוח מול החנות של Apigee, צריך להגדיר את הרכיב <ExternalAuthorization> ל-false בהגדרת המדיניות, או להשמיט אותו לחלוטין. אם רוצים להשתמש בשירות הרשאות חיצוני כדי לאמת במפורש את פרטי הכניסה של הלקוח, צריך להגדיר את <ExternalAuthorization> ל-true.

יכול להיות ש-Apigee לא יאמת את פרטי הכניסה של הלקוח, אבל עדיין צריך ש-Apigee יכיר את client_id וינהל אותו. כל access_token ב-Apigee, בין אם הוא נוצר על ידי Apigee או על ידי מערכת חיצונית ואז יובא ל-Apigee, חייב להיות משויך לאפליקציית לקוח – מסומן על ידי client_id. לכן, גם במקרה שבו מדיניות OAuthV2/GenerateAccessToken ב-Apigee לא תאמת את ההתאמה בין client_id לבין client_secret, המדיניות תאמת ש-client_id תקף, קיים ולא בוטל. לכן, כשלב הגדרה מקדים, יכול להיות שתצטרכו לייבא את client_id באמצעות ה-API האדמיניסטרטיבי של Apigee.

תהליך המדיניות של OAuth של צד שלישי ב-Apigee

כדי להשתמש באסימונים ממערכות OAuth של צד שלישי ב-Apigee, התהליך ליצירת אסימוני גישה צריך לפעול לפי אחד מהדפוסים הבאים.

אימות חיצוני של פרטי כניסה של לקוח

  1. ServiceCallout כדי לאמת את פרטי הכניסה של הלקוח הנכנס ולקבל אסימון חיצוני.
  2. ExtractVariables או שלב JavaScript כדי לחלץ את האסימון שנוצר חיצונית מהתגובה.
  3. AssignMessage כדי להגדיר את המשתנה המיוחד המוכר שנקרא oauth_external_authorization_status. הערך חייב להיות true כדי לציין שפרטי הכניסה של הלקוח תקפים.
  4. OAuthV2/GenerateAccessToken עם הרכיב <ExternalAuthorization> שמוגדר ל-true, ולפחות אחד מהרכיבים <ExternalAccessToken>,‏ <ExternalRefreshToken> או <ExternalAuthorizationCode>.

אימות פנימי של פרטי כניסה של לקוח

  • ServiceCallout כדי לקבל אסימון חיצוני.
  • ExtractVariables או שלב JavaScript כדי לחלץ את האסימון שנוצר חיצונית מהתגובה.
  • OAuthV2/GenerateAccessToken עם הרכיב <ExternalAuthorization> שמוגדר ל-false, ולפחות אחד מהרכיבים <ExternalAccessToken>,‏ <ExternalRefreshToken> או <ExternalAuthorizationCode>.

הערות לגבי התהליך והגדרת המדיניות

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

  • אחרי ServiceCallout, proxy ה-API צריך לנתח את התגובה כדי לחלץ את סטטוס התוקף, את access_token שנוצר חיצונית ואולי גם את refresh_token.

  • במדיניות OAuthV2/GenerateAccessToken, מגדירים את הרכיב <StoreToken> לערך true, ואת הרכיב <ExternalAuthorization> לערך true או false, בהתאם לצורך.

    כשמדיניות OAuthV2/GenerateAccessToken מופעלת, היא קוראת את המשתנה oauth_external_authorization_status. אם המשתנה מוגדר והערך הוא true, ‏ Apigee לא ינסה לאמת את פרטי הכניסה של הלקוח. אם המשתנה לא מוגדר או שהערך שלו הוא לא true, מערכת Apigee תנסה לאמת את פרטי הכניסה של הלקוח.

  • יש שלושה רכיבים במדיניות OAuthV2 שמאפשרים לציין את הנתונים החיצוניים לייבוא: <ExternalAccessToken>,‏ <ExternalRefreshToken> ו-<ExternalAuthorizationCode>. כל אחד מהרכיבים האלה מקבל משתנה של זרימת נתונים. מדיניות Apigee תקרא את המשתנה הזה כדי למצוא את אסימון הגישה, אסימון הרענון או קוד ההרשאה שנוצרו חיצונית. אתם צריכים להטמיע מדיניות ולוגיקה כדי למקם את האסימונים או הקודים החיצוניים במשתנים המתאימים.

    לדוגמה, ההגדרה הבאה במדיניות OAuthV2 אומרת ל-Apigee לחפש את האסימון במשתנה הקשר שנקרא external_token.

    <ExternalAccessToken>external_token</ExternalAccessToken>

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

  • לגבי הגדרת המשתנה oauth_external_authorization_status, טכניקה נפוצה להגדרת המשתנה הזה היא שימוש במדיניות AssignMessage עם הרכיב AssignVariable, באופן הבא:

    <AssignMessage name="AssignMessage-SetVariable">
        <DisplayName>Assign Message - Set Variable</DisplayName>
        <AssignVariable>
            <Name>oauth_external_authorization_status</Name>
            <Value>true</Value>
        </AssignVariable>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    </AssignMessage>

    חשוב לזכור שהמדיניות הזו צריכה להיות לפני המדיניות OAuthV2 עם Operation = GenerateAccessToken.

דוגמה למדיניות OAuthV2

מדיניות OAuthV2 הבאה יוצרת אסימון גישה, בהנחה שמערכת Apigee מוצאת ערך של אסימון במשתנה של זרימת הנתונים external_access_token.

<OAuthV2 name="OAuth-v20-Store-External-Token">
    <DisplayName>OAuth v2.0 1</DisplayName>
    <Attributes/>
    <ExternalAccessToken>external_access_token</ExternalAccessToken>
    <ExternalAuthorization>true</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <GenerateResponse enabled="true">
        <Format>FORM_PARAM</Format>
    </GenerateResponse>
    <ReuseRefreshToken>false</ReuseRefreshToken>
    <StoreToken>true</StoreToken>
    <SupportedGrantTypes>
        <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <ExpiresIn ref='flow.variable'>2400000</ExpiresIn>
</OAuthV2>

באופן תיאורטי, אפשר להשתמש בדפוס הזה עם כל שירות הרשאות OAuth2 של צד שלישי.