הטמעה ללא קובצי Cookie

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

איך פועלת הטמעה ללא קובצי Cookie?

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

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

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

יצירת iframe מוטמע של Looker

בתרשים הרצף הבא מוצגת יצירה של iframe להטמעה. יכול להיות שיווצרו כמה רכיבי iframe בו-זמנית או ברצף. אם ההטמעה תתבצע בצורה נכונה, ה-iframe יצטרף באופן אוטומטי לסשן שנוצר על ידי ה-iframe הראשון. ‫Looker Embed SDK מפשט את התהליך הזה על ידי הצטרפות אוטומטית לסשן הקיים. במאמר שיטות מומלצות להטמעת כמה רכיבי iframe ללא קובצי Cookie מוסבר איך להימנע מהתנגשויות בין התחברויות בו-זמניות כשמטעינים כמה רכיבי iframe.

תרשים רצף שממחיש את היצירה של iframe להטמעה.

  1. המשתמש מבצע פעולה באפליקציה המוטמעת שגורמת ליצירת iframe של Looker.
  2. אפליקציית הלקוח שבה מוטמעת התצוגה מקבלת סשן ב-Looker. אפשר להשתמש ב-Looker Embed SDK כדי להתחיל את הסשן הזה, אבל צריך לספק כתובת URL של נקודת קצה או פונקציית קריאה חוזרת. אם משתמשים בפונקציית קריאה חוזרת, היא תתקשר לשרת של האפליקציה המוטמעת כדי לקבל את סשן ההטמעה של Looker. אחרת, ה-Embed SDK יקרא לכתובת ה-URL של נקודת הקצה שצוינה.
  3. שרת האפליקציה המוטמעת משתמש ב-Looker API כדי לקבל סשן הטמעה. הקריאה הזו ל-API דומה לתהליך החתימה של הטמעה חתומה ב-Looker, כי היא מקבלת את הגדרת המשתמש המוטמע כקלט. אם כבר קיים סשן מוטמע של Looker למשתמש שמתקשר, צריך לכלול בקריאה את אסימון ההפניה המשויך לסשן. הנושא הזה מוסבר בפירוט בקטע השגת סשן במאמר הזה.
  4. העיבוד של נקודת הקצה של סשן ההטמעה שנרכש דומה לנקודת הקצה החתומה של /login/embed/(signed url), בכך שהוא מצפה להגדרת המשתמש המוטמע של Looker כגוף הבקשה, ולא בכתובת ה-URL. התהליך של נקודת הקצה של סשן ההטמעה מאמת את משתמש ההטמעה, ואז יוצר או מעדכן אותו. הוא יכול גם לקבל טוקן הפניה לסשן קיים. זה חשוב כי זה מאפשר לכמה רכיבי iframe מוטמעים של Looker לשתף את אותו סשן. המשתמש המוטמע לא יעודכן אם סופק אסימון הפניה לסשן והסשן לא פג. האפשרות הזו תומכת בתרחיש שבו iframe אחד נוצר באמצעות כתובת URL חתומה להטמעה, ורכיבי iframe אחרים נוצרים בלי כתובת URL חתומה להטמעה. במקרה כזה, רכיבי ה-iframe בלי כתובות ה-URL החתומות להטמעה יקבלו את קובץ ה-Cookie מהסשן הראשון.
  5. הקריאה ל-Looker API מחזירה ארבעה אסימונים, לכל אחד מהם יש אורך חיים (TTL):
    • טוקן הרשאה (TTL = ‏30 שניות)
    • טוקן ניווט (TTL = ‏10 דקות)
    • טוקן API‏ (TTL = ‏10 דקות)
    • טוקן הפניה לסשן (TTL = משך החיים שנותר לסשן)
  6. שרת האפליקציה המוטמעת צריך לעקוב אחרי הנתונים שמוחזרים על ידי הנתונים של Looker ולשייך אותם גם למשתמש שביצע את הקריאה וגם לסוכן המשתמש של הדפדפן של המשתמש שביצע את הקריאה. בקטע יצירת טוקנים במסמך הזה מפורטות הצעות לאיך לעשות את זה. הקריאה הזו תחזיר את אסימון ההרשאה, אסימון הניווט ואסימון ה-API, יחד עם כל ערכי ה-TTL המשויכים. אסימון ההפניה של הסשן צריך להיות מאובטח ולא חשוף בדפדפן שממנו מתבצעת הקריאה.
  7. אחרי שהאסימונים מוחזרים לדפדפן, צריך ליצור כתובת URL להתחברות להטמעה של Looker. ‫Looker Embed SDK ייצור את כתובת ה-URL להתחברות להטמעה באופן אוטומטי. כדי להשתמש ב-API של windows.postMessage כדי ליצור את כתובת ה-URL להתחברות להטמעה, עיינו בקטע שימוש ב-API של Looker windows.postMessage במסמך הזה כדי לראות דוגמאות.

    כתובת ה-URL להתחברות לא מכילה את פרטי המשתמש החתומים להטמעה. הוא מכיל את ה-URI של היעד, כולל אסימון הניווט ואסימון ההרשאה כפרמטר של שאילתה. צריך להשתמש באסימון ההרשאה תוך 30 שניות, ואפשר להשתמש בו רק פעם אחת. אם נדרשים רכיבי iframe נוספים, צריך ליצור שוב סשן הטמעה. עם זאת, אם מספקים את אסימון ההפניה לסשן, אסימון ההרשאה ישויך לאותו סשן.

  8. נקודת הקצה (endpoint) של ההתחברות להטמעה ב-Looker קובעת אם ההתחברות היא להטמעה ללא קובצי Cookie, שמסומנת על ידי הנוכחות של אסימון ההרשאה. אם אסימון ההרשאה תקין, המערכת בודקת את הפרטים הבאים:

    • הסשן המשויך עדיין בתוקף.
    • המשתמש המשויך להטמעה עדיין תקף.
    • סוכן המשתמש של הדפדפן שמשויך לבקשה תואם לסוכן המשתמש של הדפדפן שמשויך לסשן.
  9. אם הבדיקות מהשלב הקודם עוברות, הבקשה מופנית מחדש באמצעות ה-URI של היעד שכלול בכתובת ה-URL. זהו אותו תהליך כמו בכניסה להטמעה חתומה של Looker.

  10. הבקשה הזו היא ההפניה להפעלת מרכז הבקרה של Looker. הבקשה הזו תכלול את אסימון הניווט כפרמטר.

  11. לפני שנקודת הקצה מופעלת, שרת Looker מחפש את אסימון הניווט בבקשה. אם השרת מוצא את האסימון, הוא בודק את הדברים הבאים:

    • הסשן המשויך עדיין בתוקף.
    • סוכן המשתמש של הדפדפן שמשויך לבקשה תואם לסוכן המשתמש של הדפדפן שמשויך לסשן.

    אם הוא תקין, הסשן משוחזר לבקשה והבקשה של מרכז הבקרה פועלת.

  12. קוד ה-HTML לטעינת מרכז הבקרה מוחזר ל-iframe.

  13. ממשק המשתמש של Looker שפועל ב-iframe קובע שה-HTML של מרכז הבקרה הוא תגובה להטמעה ללא קובצי Cookie. בשלב הזה, ממשק המשתמש של Looker שולח הודעה לאפליקציה המוטמעת כדי לבקש את האסימונים שאוחזרו בשלב 6. ממשק המשתמש ממתין עד שהוא מקבל את האסימונים. אם האסימונים לא מגיעים, מוצגת הודעה.

  14. האפליקציה המוטמעת שולחת את האסימונים ל-iframe המוטמע של Looker.

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

  16. לפני שנקודת קצה כלשהי מופעלת, שרת Looker מחפש את אסימון ה-API בבקשה. אם השרת מוצא את הטוקן, הוא בודק את הדברים הבאים:

    • הסשן המשויך עדיין בתוקף.
    • סוכן המשתמש של הדפדפן שמשויך לבקשה תואם לסוכן המשתמש של הדפדפן שמשויך לסשן.

    אם הסשן תקין, הוא משוחזר לבקשה, ובקשת ה-API פועלת.

  17. הנתונים של לוח הבקרה מוחזרים.

  18. מרכז הבקרה מוצג.

  19. למשתמש יש שליטה על מרכז הבקרה.

המערכת יוצרת טוקנים חדשים

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

תרשים רצף שממחיש יצירת טוקנים חדשים.

  1. ממשק המשתמש של Looker שפועל ב-iframe המוטמע עוקב אחרי ה-TTL של אסימוני ההטמעה.
  2. כשהתוקף של הטוקנים עומד לפוג, ממשק המשתמש של Looker שולח הודעה על טוקן רענון ללקוח של האפליקציה המוטמעת.
  3. לאחר מכן, הלקוח של האפליקציה המוטמעת מבקש אסימונים חדשים מנקודת קצה שמוטמעת בשרת של האפליקציה המוטמעת. Looker Embed SDK יבקש אסימונים חדשים באופן אוטומטי, אבל צריך לספק את כתובת ה-URL של נקודת הקצה או פונקציית קריאה חוזרת. אם משתמשים בפונקציית הקריאה החוזרת, היא תשלח קריאה לשרת של האפליקציה המוטמעת כדי ליצור אסימונים חדשים. אחרת, ה-Embed SDK יתקשר לכתובת ה-URL של נקודת הקצה שצוינה.
  4. האפליקציה המוטמעת מוצאת את ה-session_reference_token שמשויך לסשן ההטמעה. בדוגמה שמופיעה במאגר Looker Embed SDK Git נעשה שימוש בקובצי Cookie זמניים, אבל אפשר גם להשתמש במטמון מבוזר בצד השרת, כמו Redis.
  5. שרת האפליקציה המוטמעת שולח לשרת Looker בקשה ליצור טוקנים. הבקשה הזו דורשת גם אסימוני API וניווט עדכניים, בנוסף לסוכן המשתמש של הדפדפן שיזם את הבקשה.
  6. שרת Looker מאמת את סוכן המשתמש, את אסימון ההפניה לסשן, את אסימון הניווט ואת אסימון ה-API. אם הבקשה תקינה, נוצרים אסימונים חדשים.
  7. האסימונים מוחזרים לשרת של האפליקציה המטמיעה שמבצעת את הקריאה.
  8. שרת האפליקציה המוטמעת מסיר את אסימון ההפניה לסשן מהתגובה ומחזיר את שאר התגובה ללקוח של האפליקציה המוטמעת.
  9. הלקוח של האפליקציה המוטמעת שולח את האסימונים החדשים שנוצרו לממשק המשתמש של Looker. ‫Looker Embed SDK יעשה את זה באופן אוטומטי. לקוחות של אפליקציות מוטמעות שמשתמשים ב-API של windows.postMessage יהיו אחראים לשליחת הטוקנים. אחרי שממשק המשתמש של Looker מקבל את האסימונים, הם משמשים בקריאות ל-API ובניווט בדפים.

הטמעה של Looker ללא קובצי Cookie

אפשר להטמיע את Looker ללא קובצי Cookie באמצעות Looker Embed SDK או באמצעות ה-API של windows.postMessage. אפשר להשתמש ב-Looker Embed SDK, אבל יש גם דוגמה שמראה איך להשתמש ב-API של windows.postMessage. הסברים מפורטים על שתי ההטמעות זמינים בקובץ ה-README של Looker Embed SDK. מאגר ה-Git של Embed SDK מכיל גם הטמעות פעילות.

הגדרת המופע ב-Looker

הטמעה ללא קובצי Cookie חולקת מאפיינים עם הטמעה חתומה של Looker.

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

כדי להשתמש בהטמעה ללא קובצי Cookie ולחשוף את נקודות הקצה של ה-API להטמעה ללא קובצי Cookie, אדמין ב-Looker צריך לאמת ולהפעיל את הדרישות הבאות בחלונית Admin ב-Looker:

  • אימות SSO מוטמע: בחלונית Admin > Platform > Embed, מפעילים את האפשרות Embed SSO Authentication. הטמעה ללא קובצי Cookie מסתמכת על הפונקציה הבסיסית אימות SSO מוטמע כהגדרה בסיסית.
  • סשנים קבועים: בחלונית אדמין > אימות > סשנים, מפעילים את האפשרות סשנים קבועים.
  • הרשאות משתמש ב-API: ודאו שפרטי הכניסה ל-API שמשמשים לקבלת הטוקן שייכים למשתמש Looker עם תפקיד אדמין או תפקיד בהתאמה אישית שכולל את ההרשאה manage_embed_settings.

הגדרת הסוד של JSON Web Token

בניגוד להטמעה חתומה ב-Looker, בהטמעה ללא קובצי Cookie לא משתמשים בהגדרה Embed Secret. הטמעה ללא קובצי Cookie משתמשת ב-JSON Web Token ‏ (JWT) בצורה של הגדרת Embed JWT Secret, שאפשר להגדיר או לאפס בדף Embed בקטע Platform בתפריט Admin.

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

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

הטמעת אפליקציית לקוח

בקטע הזה יש דוגמאות להטמעה ללא קובצי Cookie בלקוח של האפליקציה, והוא כולל את סעיפי המשנה הבאים:

התקנה או עדכון של Looker Embed SDK

כדי להשתמש בהטמעה ללא קובצי Cookie, צריך להשתמש בגרסאות הבאות של Looker SDK:

@looker/embed-sdk >= 2.0.0
@looker/sdk >= 22.16.0

שימוש ב-Looker Embed SDK

שיטת אתחול חדשה נוספה ל-Embed SDK כדי להתחיל את הסשן ללא קובצי Cookie. השיטה הזו מקבלת שתי מחרוזות של כתובות URL או שתי פונקציות קריאה חוזרת. מחרוזות כתובות ה-URL צריכות להפנות לנקודות קצה בשרת של האפליקציה המוטמעת. פרטי ההטמעה של נקודות הקצה האלה בשרת האפליקציה מפורטים בקטע הטמעה של שרת אפליקציה במסמך הזה.

getEmbedSDK().initCookieless(
  runtimeConfig.lookerHost,
  '/acquire-embed-session',
  '/generate-embed-tokens'
)

בדוגמה הבאה אפשר לראות איך משתמשים בקריאות חוזרות (callbacks). צריך להשתמש בקריאות חוזרות רק כשחשוב שאפליקציית הלקוח המוטמעת תדע מה הסטטוס של סשן ההטמעה של Looker. אפשר גם להשתמש באירוע session:status, כך שלא צריך להשתמש בקריאות חוזרות (callbacks) עם Embed SDK.

const acquireEmbedSessionCallback =
  async (): Promise<LookerEmbedCookielessSessionData> => {
    const resp = await fetch('/acquire-embed-session')
    if (!resp.ok) {
      console.error('acquire-embed-session failed', { resp })
      throw new Error(
        `acquire-embed-session failed: ${resp.status} ${resp.statusText}`
      )
    }
    return (await resp.json()) as LookerEmbedCookielessSessionData
  }

const generateEmbedTokensCallback =
  async ({ api_token, navigation_token }): Promise<LookerEmbedCookielessSessionData> => {
    const resp = await fetch('/generate-embed-tokens', {
      method: 'PUT',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ api_token, navigation_token }),
    })
    if (!resp.ok) {
      console.error('generate-embed-tokens failed', { resp })
      throw new Error(
        `generate-embed-tokens failed: ${resp.status} ${resp.statusText}`
      )
    }
    return (await resp.json()) as LookerEmbedCookielessSessionData
  }

getEmbedSDK().initCookieless(
  runtimeConfig.lookerHost,
  acquireEmbedSessionCallback,
  generateEmbedTokensCallback
)

שימוש ב-Looker windows.postMessage API

אפשר לראות דוגמה מפורטת לשימוש ב-API של windows.postMessage בקבצים message_example.ts ו-message_utils.ts במאגר Git של Embed SDK. הדגשים של הדוגמה מפורטים כאן.

בדוגמה הבאה מוסבר איך ליצור את כתובת ה-URL של ה-iframe. פונקציית הקריאה החוזרת זהה לדוגמה של acquireEmbedSessionCallback שראינו קודם.

  private async getCookielessLoginUrl(): Promise<string> {
    const { authentication_token, navigation_token } =
      await this.embedEnvironment.acquireSession()
    const url = this.embedUrl.startsWith('/embed')
      ? this.embedUrl
      : `/embed${this.embedUrl}`
    const embedUrl = new URL(url, this.frameOrigin)
    if (!embedUrl.searchParams.has('embed_domain')) {
      embedUrl.searchParams.set('embed_domain', window.location.origin)
    }
    embedUrl.searchParams.set('embed_navigation_token', navigation_token)
    const targetUri = encodeURIComponent(
      `${embedUrl.pathname}${embedUrl.search}${embedUrl.hash}`
    )
    return `${embedUrl.origin}/login/embed/${targetUri}?embed_authentication_token=${authentication_token}`
  }

בדוגמה הבאה אפשר לראות איך להאזין לבקשות של אסימונים, ליצור אסימונים חדשים ולשלוח אותם ל-Looker. פונקציית הקריאה החוזרת זהה לדוגמה הקודמת של generateEmbedTokensCallback.

      this.on(
        'session:tokens:request',
        this.sessionTokensRequestHandler.bind(this)
      )

  private connected = false

  private async sessionTokensRequestHandler(_data: any) {
    const contentWindow = this.getContentWindow()
    if (contentWindow) {
      if (!this.connected) {
        // When not connected the newly acquired tokens can be used.
        const sessionTokens = this.embedEnvironment.applicationTokens
        if (sessionTokens) {
          this.connected = true
          this.send('session:tokens', this.embedEnvironment.applicationTokens)
        }
      } else {
        // If connected, the embedded Looker application has decided that
        // it needs new tokens. Generate new tokens.
        const sessionTokens = await this.embedEnvironment.generateTokens()
        this.send('session:tokens', sessionTokens)
      }
    }
  }

  send(messageType: string, data: any = {}) {
    const contentWindow = this.getContentWindow()
    if (contentWindow) {
      const message: any = {
        type: messageType,
        ...data,
      }
      contentWindow.postMessage(JSON.stringify(message), this.frameOrigin)
    }
    return this
  }

הטמעה של שרת אפליקציות

בקטע הזה יש דוגמאות להטמעה ללא קובצי Cookie בשרת האפליקציה, והוא כולל את סעיפי המשנה הבאים:

הטמעה בסיסית

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

  1. השגת סשן – אם כבר קיים אסימון הפניה לסשן והוא עדיין פעיל, בקשות לסשן יצטרפו לסשן הקיים. הפונקציה Acquire session מופעלת כשנוצר iframe.
  2. יצירת טוקנים – Looker מפעיל קריאות לנקודת הקצה הזו מדי פעם.

הוספת סשן

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

  app.get(
    '/acquire-embed-session',
    async function (req: Request, res: Response) {
      try {
        const current_session_reference_token =
          req.session && req.session.session_reference_token
        const response = await acquireEmbedSession(
          req.headers['user-agent']!,
          user,
          current_session_reference_token
        )
        const {
          authentication_token,
          authentication_token_ttl,
          navigation_token,
          navigation_token_ttl,
          session_reference_token,
          session_reference_token_ttl,
          api_token,
          api_token_ttl,
        } = response
        req.session!.session_reference_token = session_reference_token
        res.json({
          api_token,
          api_token_ttl,
          authentication_token,
          authentication_token_ttl,
          navigation_token,
          navigation_token_ttl,
          session_reference_token_ttl,
        })
      } catch (err: any) {
        res.status(400).send({ message: err.message })
      }
    }
  )

async function acquireEmbedSession(
  userAgent: string,
  user: LookerEmbedUser,
  session_reference_token: string
) {
  await acquireLookerSession()
    try {
    const request = {
      ...user,
      session_reference_token: session_reference_token,
    }
    const sdk = new Looker40SDK(lookerSession)
    const response = await sdk.ok(
      sdk.acquire_embed_cookieless_session(request, {
        headers: {
          'User-Agent': userAgent,
        },
      })
    )
    return response
  } catch (error) {
    console.error('embed session acquire failed', { error })
    throw error
  }
}

החל מגרסה 23.8 של Looker, אפשר לכלול את הדומיין המוטמע כשמקבלים את הסשן ללא קובצי Cookie. זוהי חלופה להוספת הדומיין המוטמע באמצעות החלונית Admin > Embed ב-Looker. ‫Looker שומר את הדומיין להטמעה במסד הנתונים הפנימי של Looker, כך שהוא לא יוצג בחלונית Admin > Embed. במקום זאת, הדומיין המוטמע משויך לסשן ללא קובצי Cookie וקיים רק למשך הסשן. אם אתם מחליטים להשתמש בתכונה הזו, כדאי לעיין בשיטות המומלצות לאבטחה.

יצירת טוקנים

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

חשוב לדעת איך לטפל בתגובות 400, שמתרחשות כשהאסימונים לא חוקיים. תגובה 400 לא אמורה לחזור, אבל אם היא חוזרת, מומלץ לסיים את סשן ההטמעה של Looker. אפשר לסיים את הסשן המוטמע של Looker על ידי השמדת ה-iframe המוטמע או על ידי הגדרת הערך session_reference_token_ttl לאפס בהודעה session:tokens. אם מגדירים את הערך של session_reference_token_ttl לאפס, ב-iframe של Looker מוצגת תיבת דו-שיח על סשן שפג תוקפו.

תגובת 400 לא מוחזרת כשתוקף הסשן המוטמע פג. אם פג התוקף של סשן ההטמעה, מוחזרת תשובה 200 עם הערך session_reference_token_ttl שמוגדר כאפס.

  app.put(
    '/generate-embed-tokens',
    async function (req: Request, res: Response) {
      try {
        const session_reference_token = req.session!.session_reference_token
        const { api_token, navigation_token } = req.body as any
        const tokens = await generateEmbedTokens(
          req.headers['user-agent']!,
          session_reference_token,
          api_token,
          navigation_token
        )
        res.json(tokens)
      } catch (err: any) {
        res.status(400).send({ message: err.message })
      }
    }
  )
}
async function generateEmbedTokens(
  userAgent: string,
  session_reference_token: string,
  api_token: string,
  navigation_token: string
) {
  if (!session_reference_token) {
    console.error('embed session generate tokens failed')
    // missing session reference  treat as expired session
    return {
      session_reference_token_ttl: 0,
    }
  }
  await acquireLookerSession()
  try {
    const sdk = new Looker40SDK(lookerSession)
    const response = await sdk.ok(
      sdk.generate_tokens_for_cookieless_session(
        {
          api_token,
          navigation_token,
          session_reference_token: session_reference_token || '',
        },
        {
          headers: {
            'User-Agent': userAgent,
          },
        }
      )
    )
    return {
      api_token: response.api_token,
      api_token_ttl: response.api_token_ttl,
      navigation_token: response.navigation_token,
      navigation_token_ttl: response.navigation_token_ttl,
      session_reference_token_ttl: response.session_reference_token_ttl,
    }
  } catch (error: any) {
    if (error.message?.includes('Invalid input tokens provided')) {
      // The Looker UI does not know how to handle bad
      // tokens. This shouldn't happen but if it does expire the
      // session. If the token is bad there is not much that that
      // the Looker UI can do.
      return {
        session_reference_token_ttl: 0,
      }
    }
    console.error('embed session generate tokens failed', { error })
    throw error
  }

שיקולים להטמעה

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

  • בסשן של המשתמש באפליקציה המוטמעת
  • במטמון בצד השרת שזמין בסביבה מקובצת (clustered)
  • בטבלה של מסד נתונים שמשויכת למשתמש

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

כשהסשן של Looker המוטמע יסתיים, תוצג תיבת דו-שיח ב-iframe המוטמע. בשלב הזה, המשתמש לא יוכל לעשות שום דבר במופע המוטמע. במצב כזה, ייווצרו אירועי session:status, שיאפשרו לאפליקציה המוטמעת לזהות את המצב הנוכחי של אפליקציית Looker המוטמעת ולבצע פעולה כלשהי.

אפליקציה מוטמעת יכולה לזהות אם פג התוקף של סשן ההטמעה על ידי בדיקה אם הערך של session_reference_token_ttl שמוחזר על ידי נקודת הקצה (endpoint) של generate_tokens הוא אפס. אם הערך הוא אפס, פג התוקף של הסשן המוטמע. מומלץ להשתמש בפונקציית קריאה חוזרת כדי ליצור אסימונים כשההטמעה ללא קובצי Cookie עוברת אתחול. פונקציית הקריאה החוזרת יכולה לקבוע אם פג התוקף של הסשן המוטמע, ולהשמיד את ה-iframe המוטמע במקום להשתמש בתיבת הדו-שיח שמופיעה כברירת מחדל כשתוקף הסשן המוטמע פג.

שיטות מומלצות להטמעת כמה רכיבי iframe ללא קובצי Cookie

כשמטמיעים כמה רכיבי iframe של Looker בדף אחד בהטמעה ללא קובצי Cookie, כל iframe דורש authentication_token משלו לשימוש חד-פעמי מ-acquire_embed_cookieless_session, אבל כל רכיבי ה-iframe בדף חייבים לשתף session_reference_token אחד. כדי להטמיע כמה רכיבי iframe ללא קובצי Cookie, כדאי לפעול לפי השיטות המומלצות הבאות:

  • קבלת הסשן פעם אחת ושימוש חוזר ב-session_reference_token: קודם מקבלים את הסשן ללא קובצי Cookie פעם אחת, שומרים במטמון את ה-session_reference_token שהוחזר בשרת הבק-אנד, ומעבירים את ה-session_reference_token הזה לקריאות הבאות של acquire_embed_cookieless_session בשביל רכיבי iframe נוספים. לאחר מכן, Looker מצרף כל iframe חדש לסשן הקיים ומדלג על עדכון המשתמש המוטמע.

  • הימנעו מהשגת סשן ראשוני במקביל: אם כמה רכיבי iframe נטענים בו-זמנית וה-backend שלכם קורא ל-acquire_embed_cookieless_session במקביל בלי להעביר session_reference_token קיים, Looker מתייחס לכל בקשה כהתחברות חדשה, מעדכן את המשתמש המוטמע בו-זמנית ויוצר סשנים נפרדים. בקשות התחברות בו-זמניות של אותו משתמש מוטמע יכולות לגרום לתחרות על נעילה בשרת Looker. בנוסף, החלפת ה-session_reference_token המאוחסן בתגובה האחרונה משבשת את רענון הטוקן (generate_tokens_for_cookieless_session) במסגרות ה-iframe הקודמות, ומופיעה השגיאה 400 Invalid input tokens provided.

  • טעינה מראש של iframe ושימוש בניווט בתוך מסגרת: כדי ליצור את סשן המשתמש המוטמע לפני טעינת התוכן, טוענים מראש iframe באמצעות /embed/preload (או השיטה .preload() ב-Embed SDK v2). כשמשתמשים ב-Embed SDK v2, אפשר גם לנווט בתוך iframe קיים באמצעות שיטות כמו connection.loadDashboard(DASHBOARD_ID) או connection.loadUrl(EMBED_URL) במקום ליצור רכיבי iframe נוספים. מידע נוסף זמין במאמר מבוא ל-Embed SDK.

הרצת הדוגמה להטמעה ללא קובצי Cookie ב-Looker

מאגר ה-SDK להטמעה מכיל שרת Node Express ולקוח שכתוב ב-TypeScript שמטמיע אפליקציית הטמעה. הדוגמאות שהוצגו קודם נלקחו מההטמעה הזו. ההנחה הבאה היא שהמופע של Looker הוגדר לשימוש בהטמעה ללא קובצי Cookie, כפי שמתואר למעלה.

כדי להפעיל את השרת:

  1. משכפלים את המאגר של Embed SDK — git clone git@github.com:looker-open-source/embed-sdk.git
  2. שינוי הספרייה — cd embed-sdk
  3. מתקינים את יחסי התלות – npm install
  4. מגדירים את השרת, כמו שמוסבר בקטע הגדרת השרת במסמך הזה.
  5. מפעילים את השרת – npm run server

הגדרת השרת

יוצרים קובץ .env בתיקיית הבסיס של המאגר המשוכפל (הוא כלול ב-.gitignore).

הפורמט הוא:

LOOKER_WEB_URL=your-looker-instance-url.com
LOOKER_API_URL=https://your-looker-instance-url.com
LOOKER_DEMO_HOST=localhost
LOOKER_DEMO_PORT=8080
LOOKER_EMBED_SECRET=embed-secret-from-embed-admin-page
LOOKER_CLIENT_ID=client-id-from-user-admin-page
LOOKER_CLIENT_SECRET=client-secret-from-user-admin-page
LOOKER_DASHBOARD_ID=id-of-dashboard
LOOKER_LOOK_ID=id-of-look
LOOKER_EXPLORE_ID=id-of-explore
LOOKER_EXTENSION_ID=id-of-extension
LOOKER_VERIFY_SSL=true
LOOKER_REPORT_ID=id-of-report
LOOKER_QUERY_VISUALIZATION_ID=id-of-query-visualization

כשמשתמשים בהטמעה ללא קובצי Cookie ב-Looker, משתמשים שמנסים לפתוח קישורים בכרטיסייה או בחלון חדשים בדפדפן (כמו פירוט של מרכז בקרה, חקירות או הורדות של מסמכים) עלולים להיתקל בשגיאה HTTP 401 Unauthorized או להיות מופנים לדף ההתחברות של Looker. הבעיה הזו מתרחשת בדרך כלל כשקובצי Cookie של צד שלישי מושבתים בדפדפן.

מטרה

כדי למנוע נקודות חולשה שמאפשרות חטיפת פעילות (Session Hijacking), הוספנו ל-Looker (גרסאות 25.18.61 ומעלה, 25.20.44 ומעלה ו-26.0.22 ומעלה) תיקון אבטחה שמפסיק באופן מכוון את ההחזרה של קובצי Cookie של סשן בתגובה הראשונית להטמעה ללא קובצי Cookie. הדפדפן לא מקבל יותר את קובץ ה-Cookie הזמני הזה, ולכן כשפותחים כתובת URL של Looker בכרטיסייה או בחלון חדשים, ההקשר לצורכי אימות אובד והבקשה נכשלת.

פתרון ודרכים חלופיות

  • שדרוג Looker: משדרגים את המכונה של Looker לגרסה 26.0.36 ואילך. בגרסה הזו הוספנו תיקון שמוסיף באופן מאובטח אסימון חד-פעמי לכתובות URL שנפתחות בחלון חדש במהלך סשן הטמעה ללא קובצי Cookie. התיקון הזה מאפשר למשתמשים לפתוח קישורים מאובטחים בכרטיסיות חדשות.
  • פתיחת קישורים באותו iframe: אם אי אפשר לשדרג באופן מיידי, מגדירים את כל הקישורים במרכזי הבקרה המוטמעים כך שייפתחו באותו iframe. כדי לעשות את זה, מגדירים את יעדי הקישורים ל-_self (לדוגמה, target="_self").
  • ניתוב דרך האפליקציה המארחת: אם חייבים לפתוח בכרטיסייה או בחלון חדשים, צריך לטרגט את הקישור לדף חדש באפליקציה המארחת שמפעיל iframe חדש להטמעה ללא קובצי Cookie, במקום לקשר ישירות למכונה של Looker.
  • שימוש בהטמעה חתומה עם דומיין מותאם אישית: לחלופין, אפשר להשתמש בהטמעה חתומה רגילה עם דומיין מותאם אישית.