שימוש בטוקנים של OAuth מסוג JWT

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

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

בנושא הזה מוסבר איך ליצור, לאמת ולרענן אסימוני גישה מסוג JWT באמצעות מדיניות OAuthV2.

מבוא

פעולות ה-JWT מאפשרות למדיניות OAuthV2 ליצור, לאמת ולרענן אסימוני גישה שתואמים ל-IETF RFC 9068, תקן שמתאר איך להנפיק אסימוני גישה בפורמט JWT. בדרך כלל משתמשים ב-JWT כדי לשתף טענות או הצהרות בין אפליקציות מקושרות. אפשר להנפיק אסימוני גישה מסוג OAuthV2 בפורמט JWT במקום להנפיק אסימוני גישה אטומים.

כשמגדירים את מדיניות OAuthV2 ל-JWT, היא יוצרת ומחזירה JWT בקידוד Base64 שמורכב מכותרת, ממטען ייעודי (payload) ומחתימה, שמופרדים באמצעות נקודות. לדוגמה:

איור 1: פורמט סריאלי של JWT שכולל כותרת, מטען ייעודי (payload) וחתימה, שמופרדים באמצעות נקודות.

התוכן המוצפן של הרכיבים האלה תלוי באופן שבו מגדירים את מדיניות OAuthV2. במדיניות, מציינים פרמטרים כמו אלגוריתם החתימה ורכיבי מטען ייעודי (payload) כמו נושא ושם. לדוגמה, יכול להיות שהכותרת תפוענח כ-{"alg":"HS256","typ":"at+JWT"}, והמטען הייעודי יפוענח כ-{"sub":"ABC1234567","iat":1516239022}.

הכותרת מציינת את ההצהרה typ (תמיד "at+JWT) ואת ההצהרה alg, שמציינת את האלגוריתם ששימש לחתימה על ה-JWT. ‫Apigee תומך באלגוריתמים RSA ו-HMAC: ‏ RS(256,384,512) ו-HS(256,384,512).

Payload

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

הצהרה על זכויות יוצרים תיאור סופק על ידי
iss הישות שהנפיקה את הטוקן. הערך הזה מוגדר כך: (http|https)://{domain-name-for-proxy}/{proxy-basePath}. לדוגמה: https://api.mycompany.com/auth/v2. Apigee
sub מזהה הלקוח או המזהה של בעל המשאב (במקרה של סוגי הרשאות סיסמה או הרשאות). אם הפרמטר appEndUserId מצורף לבקשה, הערך הזה משמש כמזהה של בעל המשאב. אפשר לקבוע איפה הערך הזה מוגדר באמצעות הרכיב <AppEndUser> של מדיניות OAuthV2. מפתח API
jti מזהה ייחודי שמיוצג כמחרוזת אקראית שמגובה על ידי UUID, כדי לזהות את האסימון באופן ייחודי. Apigee
exp מועד התפוגה, כלומר הזמן שאחריו האסימון נחשב לא תקף. הערך מופיע כזמן אפוקה (בשניות). Apigee
iat הזמן שבו הונפק האסימון, כלומר הזמן שבו הוא נוצר. הערך מופיע כזמן אפוקה (בשניות). Apigee
client_id המזהה הייחודי של אפליקציית הלקוח. מפתח API
scope היקף ההרשאות של OAuth שהוקצה לטוקן. אפשר לעיין גם במאמר בנושא עבודה עם היקפי הרשאות של OAuth. מפתח API

חתימה

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

למידע נוסף על אסימוני גישה מסוג OAuth 2.0 בפורמט JWT, אפשר לעיין ב-IETF RFC 9068: JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens.

דרישות מוקדמות

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

ביצירה

משתמשים בפעולות GenerateJWTAccessToken ו-GenerateJWTAccessTokenImplicitGrant כדי ליצור אסימון גישה מסוג JWT באמצעות מדיניות OAuthV2. הפעולות האלה דומות לפעולות המסורתיות GenerateAccessToken ו-GenerateAccessTokenImplicitGrant של המדיניות. ההבדל העיקרי הוא שפעולת ה-JWT מחזירה אסימון גישה בפורמט JWT במקום אסימון מחרוזת אטומה. אפשר גם לעיין במאמר בנושא קבלת טוקנים מסוג OAuth 2.0.

בדוגמאות הבאות אפשר לראות איך משתמשים בפעולות האלה במדיניות OAuthV2. בדוגמאות נעשה שימוש בסוג ההרשאה client_credentials, אבל אפשר להשתמש בכל אחד מסוגי ההרשאות הנתמכים בפעולות האלה.

יצירת אסימון בפורמט JWT שנחתם באמצעות אלגוריתם HMAC

מציינים את הרכיב <Algorithm> עם אחד מאלגוריתמי ה-HMAC‏ (HS256/HS384/HS512). צריך לספק גם את <SecretKey>. בדוגמה הבאה מוצגת מדיניות שהוגדרה ליצירת JWT שנחתם באמצעות אלגוריתם HS512 באמצעות המפתח הסודי שצוין.

<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessToken</Operation>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
  <Algorithm>HS512</Algorithm>
  <SecretKey>
    <Value ref="private.mysecretkey"/>
  </SecretKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>

יצירת אסימון בפורמט JWT שנחתם באמצעות אלגוריתם RSA

מציינים אחד מאלגוריתמי ה-RSA (אחד מהאלגוריתמים RS256/RS384/RS512) ברכיב <Algorithm>, ומספקים את המפתח הפרטי ברכיב <PrivateKey>. בדוגמה הבאה מוצגת מדיניות שמוגדרת ליצירת JWT בחתימה עם מפתח פרטי RSA באמצעות אלגוריתם RS256.

<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessToken</Operation>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
  <Algorithm>RS256</Algorithm>
  <PrivateKey>
    <Value ref="private.rsa-privatekey-1"/>
  </PrivateKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>

יצירת אסימון בפורמט JWT עם סוג ההרשאה המרומז

הפעולה GenerateJWTAccessTokenImplicitGrant יוצרת אסימון גישה מסוג JWT באמצעות סוג ההרשאה המרומז. הוא מקצה לטוקן באופן אוטומטי את סוג ההרשאה המרומז, ולכן אין צורך ברכיב <SupportedGrantTypes>. מכיוון שזהו JWT, נדרש הרכיב <Algorithm>. בדוגמה הבאה מוצג שימוש באלגוריתם RS256. לכן, חובה להשתמש ברכיב <PrivateKey>. מידע נוסף זמין במאמר בנושא שימוש בסוג ההרשאה המרומז.

<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessTokenImplicitGrant</Operation>
  <GenerateResponse enabled="true"/>
  <Algorithm>RS256</Algorithm>
  <PrivateKey>
    <Value ref="private.rsa-privatekey-1"/>
  </PrivateKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>

מוודא

משתמשים בVerifyJWTAccessToken פעולה כדי לאמת אסימון גישה מסוג JWT באמצעות המדיניות OAuthV2. הפעולה הזו דומה לפעולה VerifyAccessToken , אבל ההבדל הוא שהפעולה VerifyJWTAccessToken חלה על אסימונים בפורמט JWT, בעוד שהפעולה VerifyAccessToken חלה על אסימונים אטומים.

אימות של אסימון גישה מסוג JWT שנחתם באמצעות אלגוריתם HMAC

בדוגמה הבאה מוצג אופן ההגדרה של מדיניות OAuthV2 כדי לאמת אסימון JWT שנחתם באמצעות אלגוריתם HS512. כשמשתמשים בפעולה VerifyJWTAccessToken עם אלגוריתם HMAC, צריך להשתמש ברכיב <SecretKey> בהגדרת המדיניות כדי לציין את המפתח הסודי ששימש לחתימה על ה-JWT.

<OAuthV2 name="OAuthV2-verify-jwt">
  <Operation>VerifyJWTAccessToken</Operation>
  <Algorithm>HS512</Algorithm>
  <SecretKey>
    <Value ref="private.mysecretkey"/>
  </SecretKey>
</OAuthV2>

אימות של אסימון גישה מסוג JWT שנחתם באמצעות אלגוריתם RSA

בדוגמה הבאה מוצג אופן ההגדרה של מדיניות OAuthV2 כדי לאמת אסימון JWT שנחתם באמצעות אלגוריתם RS512. כשמשתמשים בפעולה VerifyJWTAccessToken עם אלגוריתם RSA, בהגדרת המדיניות צריך להשתמש ברכיב <PublicKey> כדי לציין את המפתח הציבורי שתואם למפתח הפרטי ששימש לחתימה על ה-JWT.

<OAuthV2 name="OAuthV2-verify-jwt">
  <Operation>VerifyJWTAccessToken</Operation>
  <Algorithm>RS512</Algorithm>
  <PublicKey>
    <Value ref="propertyset.non-secrets.rsa-publickey-1"/>
  </PublicKey>
</OAuthV2>

רענון

משתמשים בRefreshJWTAccessToken פעולה כדי לרענן אסימון גישה מסוג JWT. הפעולה הזו דומה לפעולה המסורתית של המדיניות RefreshAccessToken. אפשר לקרוא גם על רענון של טוקן גישה.

רענון של טוקן גישה עם חתימת HMAC

דוגמת המדיניות הבאה ממחישה איך להגדיר את מדיניות OAuthV2 כדי לרענן אסימון JWT שנחתם באמצעות אלגוריתם HMAC. במקרה כזה, חובה להשתמש ברכיבים <SecretKey> ו-<Algorithm>.

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

<OAuthV2 name="RefreshAccessToken">
    <Operation>RefreshJWTAccessToken</Operation>
    <GenerateResponse enabled="true"/>
    <Algorithm>HS512</Algorithm>
    <SecretKey>
      <Value ref="private.mysecretkey"/>
    </SecretKey>
    <RefreshTokenExpiresIn ref="kvm.oauth.expires_in">3600000</RefreshTokenExpiresIn>
</OAuthV2>

רענון של אסימון גישה מסוג JWT בחתימת RSA

בדוגמה הבאה של מדיניות אפשר לראות איך מגדירים את מדיניות OAuthV2 כדי לרענן אסימון JWT שנחתם באמצעות אלגוריתם RSA. אפשר לקרוא גם על רענון של טוקן גישה.

<OAuthV2 name="RefreshAccessToken">
    <Operation>RefreshJWTAccessToken</Operation>
    <GenerateResponse enabled="true"/>
    <Algorithm>RS256</Algorithm>
    <PrivateKey>
      <Value ref="private.rsa-privatekey-1"/>
    </PrivateKey>
    <RefreshTokenExpiresIn ref="kvm.oauth.expires_in">3600000</RefreshTokenExpiresIn>
</OAuthV2>

דוגמה לתגובת טוקן

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

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImF0K0pXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "token_type": "Bearer",
  "developer.email": "developer@example.org",
  "token_type": "Bearer",
  "issued_at": "1658352381404",
  "expires_in": 1799,
  "refresh_token": "rVSmm3QaNa0xBVFbUISz1NZI15akvgLJ",
  "refresh_token_issued_at": "1658352381404",
  "refresh_token_expires_in": 86399,
  "refresh_token_status": "Approved",
  "refresh_count": "0",
  "organization_name": "cerruti",
  "api_product_list_json": [ "TestingProduct" ]
}

סיכום של רכיבי המדיניות הנדרשים

בטבלה הבאה מתוארים רכיבים ספציפיים ל-JWT שמופיעים בדוגמאות שלמעלה:

רכיב סוג הערות
אלגוריתם ערך סטטי מציין את האלגוריתם שמשמש לחתימה על הטוקן.
SecretKey ערך שהופנה אליו המפתח הסודי שמשמש לאימות או לחתימה על אסימונים באמצעות אלגוריתם HMAC: ‏ HS ‏ (256/384/512).
PrivateKey ערך שהופנה אליו מספק את המפתח הפרטי ששימש ליצירת האסימון. השימוש מותר רק אם האלגוריתם הוא אלגוריתם RSA: ‏ RS ‏ (256/384/512).
PublicKey ערך שהופנה אליו המפתח הציבורי שמשמש לאימות הטוקן. השימוש מותר רק אם האלגוריתם הוא אלגוריתם RSA: ‏ RS ‏ (256/384/512).

רכיבי מדיניות שלא נתמכים

אין תמיכה ברכיבי המדיניות הבאים של OAuthV2 בהגדרות של אסימוני JWT:

רכיב הערות
ExternalAuthorization כשיוצרים טוקן גישה מסוג JWT, מדיניות OAuthV2 מאמתת את מזהה הלקוח ואת הסוד.
ExternalAccessToken כשיוצרים אסימון גישה מסוג JWT, הוא נחתם על ידי Apigee, והתביעות מסופקות על ידי Apigee כברירת מחדל או באמצעות הגדרת מדיניות. המדיניות תומכת ב-ExternalRefreshToken, שיכול לעזור בתרחישי שימוש בהעברה.
RFCCompliantRequestResponse היצירה והרענון של טוקנים מסוג JWT לגישה תואמים ל-RFC כברירת מחדל.

הערות שימוש

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