Saat Looker disematkan dalam iframe menggunakan embedding yang ditandatangani, beberapa browser secara default menggunakan kebijakan cookie yang memblokir cookie pihak ketiga. Cookie pihak ketiga ditolak saat iframe sematan dimuat dari domain yang berbeda dengan domain yang memuat aplikasi embedding. Anda umumnya dapat mengatasi batasan ini dengan meminta dan menggunakan domain vanity. Namun, domain vanity tidak dapat digunakan dalam beberapa skenario. Untuk skenario inilah embedding tanpa cookie Looker dapat digunakan.
Bagaimana cara kerja embedding tanpa cookie?
Jika cookie pihak ketiga tidak diblokir, cookie sesi akan dibuat saat pengguna pertama kali login ke Looker. Cookie ini dikirim dengan setiap permintaan pengguna, dan server Looker menggunakannya untuk menetapkan identitas pengguna yang memulai permintaan. Jika cookie diblokir, cookie tidak akan dikirim dengan permintaan, sehingga server Looker tidak dapat mengidentifikasi pengguna yang terkait dengan permintaan tersebut.
Untuk mengatasi masalah ini, sematan tanpa cookie Looker mengaitkan token dengan setiap permintaan yang dapat digunakan untuk membuat ulang sesi pengguna di server Looker. Aplikasi embedding bertanggung jawab untuk mendapatkan token ini dan menyediakannya untuk instance Looker yang berjalan di iframe sematan. Proses mendapatkan dan menyediakan token ini dijelaskan di bagian lain dalam dokumen ini.
Untuk menggunakan salah satu API, aplikasi embedding harus dapat melakukan autentikasi ke Looker API dengan hak istimewa admin. Domain sematan juga harus tercantum dalam Daftar Izinkan Domain Sematan, atau, jika menggunakan Looker 23.8 atau yang lebih baru, domain sematan dapat disertakan saat sesi tanpa cookie diperoleh.
Membuat iframe sematan Looker
Diagram urutan berikut menggambarkan pembuatan iframe sematan. Beberapa iframe dapat dibuat secara bersamaan atau pada waktu mendatang. Jika diterapkan dengan benar, iframe akan otomatis bergabung dengan sesi yang dibuat oleh iframe pertama. Looker Embed SDK menyederhanakan proses ini dengan otomatis bergabung ke sesi yang ada.

- Pengguna melakukan tindakan di aplikasi embedding yang menghasilkan pembuatan iframe Looker.
- Klien aplikasi embedding memperoleh sesi Looker. Looker Embed SDK dapat digunakan untuk memulai sesi ini, tetapi URL endpoint atau fungsi callback harus disediakan. Jika fungsi callback digunakan, fungsi tersebut akan memanggil server aplikasi embedding untuk memperoleh sesi sematan Looker. Jika tidak, Embed SDK akan memanggil URL endpoint yang disediakan.
- Server aplikasi embedding menggunakan Looker API untuk memperoleh sesi sematan. Panggilan API ini mirip dengan proses penandatanganan sematan yang ditandatangani Looker, karena menerima definisi pengguna sematan sebagai input. Jika sesi sematan Looker sudah ada untuk pengguna yang memanggil, token referensi sesi terkait harus disertakan dalam panggilan. Hal ini akan dijelaskan lebih mendetail di bagian Memperoleh sesi dalam dokumen ini.
- Pemrosesan endpoint sesi sematan yang diperoleh mirip dengan endpoint
/login/embed/(signed url)yang ditandatangani, karena mengharapkan definisi pengguna sematan Looker sebagai isi permintaan, bukan di URL. Proses endpoint sesi sematan yang diperoleh memvalidasi, lalu membuat atau memperbarui, pengguna sematan. Proses ini juga dapat menerima token referensi sesi yang ada. Hal ini penting karena memungkinkan beberapa iframe sematan Looker berbagi sesi yang sama. Pengguna sematan tidak akan diperbarui jika token referensi sesi disediakan dan sesi belum berakhir. Hal ini mendukung kasus penggunaan saat satu iframe dibuat menggunakan URL sematan yang ditandatangani dan iframe lainnya dibuat tanpa URL sematan yang ditandatangani. Dalam hal ini, iframe tanpa URL sematan yang ditandatangani akan mewarisi cookie dari sesi pertama. - Panggilan Looker API menampilkan empat token, masing-masing dengan time to live (TTL):
- Token otorisasi (TTL = 30 detik)
- Token navigasi (TTL = 10 menit)
- Token API (TTL = 10 menit)
- Token referensi sesi (TTL = masa aktif sesi yang tersisa)
- Server aplikasi embedding harus melacak data yang ditampilkan oleh data Looker dan mengaitkannya dengan pengguna yang memanggil dan agen pengguna browser pengguna yang memanggil. Saran tentang cara melakukannya disediakan di bagian Membuat token dalam dokumen ini. Panggilan ini akan menampilkan token otorisasi, token navigasi, dan token API, beserta semua TTL terkait. Token referensi sesi harus diamankan dan tidak diekspos di browser yang memanggil.
Setelah token ditampilkan ke browser, URL login sematan Looker harus dibuat. Looker Embed SDK akan membuat URL login sematan secara otomatis. Untuk menggunakan
windows.postMessageAPI guna membuat URL login sematan, lihat bagian Menggunakanwindows.postMessageAPI Looker dalam dokumen ini untuk mengetahui contohnya.URL login tidak berisi detail pengguna sematan yang ditandatangani. URL ini berisi URI target, termasuk token navigasi, dan token otorisasi sebagai parameter kueri. Token otorisasi harus digunakan dalam waktu 30 detik dan hanya dapat digunakan satu kali. Jika iframe tambahan diperlukan, sesi sematan harus diperoleh lagi. Namun, jika token referensi sesi disediakan, token otorisasi akan dikaitkan dengan sesi yang sama.
Endpoint login sematan Looker menentukan apakah login untuk sematan tanpa cookie, yang ditunjukkan oleh keberadaan token otorisasi. Jika token otorisasi valid, token tersebut akan memeriksa hal berikut:
- Sesi terkait masih valid.
- Pengguna sematan terkait masih valid.
- Agen pengguna browser yang terkait dengan permintaan cocok dengan agen browser yang terkait dengan sesi.
Jika pemeriksaan dari langkah sebelumnya lulus, permintaan akan dialihkan menggunakan URI target yang terdapat dalam URL. Proses ini sama dengan proses untuk login sematan yang ditandatangani Looker.
Permintaan ini adalah pengalihan untuk meluncurkan dasbor Looker. Permintaan ini akan memiliki token navigasi sebagai parameter.
Sebelum endpoint dieksekusi, server Looker akan mencari token navigasi dalam permintaan. Jika server menemukan token, server akan memeriksa hal berikut:
- Sesi terkait masih valid.
- Agen pengguna browser yang terkait dengan permintaan cocok dengan agen browser yang terkait dengan sesi.
Jika valid, sesi akan dipulihkan untuk permintaan dan permintaan dasbor akan berjalan.
HTML untuk memuat dasbor akan ditampilkan ke iframe.
UI Looker yang berjalan di iframe menentukan bahwa HTML dasbor adalah respons sematan tanpa cookie. Pada saat itu, UI Looker akan mengirim pesan ke aplikasi embedding untuk meminta token yang diambil pada langkah 6. UI kemudian menunggu hingga menerima token. Jika token tidak diterima, pesan akan ditampilkan.
Aplikasi embedding mengirim token ke iframe sematan Looker.
Saat token diterima, UI Looker yang berjalan di iframe akan memulai proses untuk merender objek permintaan. Selama proses ini, UI akan melakukan panggilan API ke server Looker. Token API yang diterima pada langkah 15 akan otomatis dimasukkan sebagai header ke semua permintaan API.
Sebelum endpoint dieksekusi, server Looker akan mencari token API dalam permintaan. Jika server menemukan token, server akan memeriksa hal berikut:
- Sesi terkait masih valid.
- Agen pengguna browser yang terkait dengan permintaan cocok dengan agen browser yang terkait dengan sesi.
Jika sesi valid, sesi akan dipulihkan untuk permintaan, dan permintaan API akan berjalan.
Data dasbor akan ditampilkan.
Dasbor akan dirender.
Pengguna memiliki kontrol atas dasbor.
Membuat token baru
Diagram urutan berikut menggambarkan pembuatan token baru.

- UI Looker yang berjalan di iframe sematan memantau TTL token sematan.
- Saat token mendekati masa berlaku, UI Looker akan mengirim pesan token refresh ke klien aplikasi embedding.
- Klien aplikasi embedding kemudian meminta token baru dari endpoint yang diterapkan di server aplikasi embedding. The Looker Embed SDK akan meminta token baru secara otomatis, tetapi URL endpoint atau fungsi callback harus disediakan. Jika fungsi callback digunakan, fungsi tersebut akan memanggil server aplikasi embedding untuk membuat token baru. Jika tidak, Embed SDK akan memanggil URL endpoint yang disediakan.
- Aplikasi embedding menemukan
session_reference_tokenyang terkait dengan sesi sematan. Contoh yang disediakan di repositori Git Looker Embed SDK menggunakan cookie sesi, tetapi cache sisi server terdistribusi, misalnya Redis, juga dapat digunakan. - Server aplikasi embedding memanggil server Looker dengan permintaan untuk membuat token. Permintaan ini juga memerlukan token API dan navigasi terbaru selain agen pengguna browser yang memulai permintaan.
- Server Looker memvalidasi agen pengguna, token referensi sesi, token navigasi, dan token API. Jika permintaan valid, token baru akan dibuat.
- Token akan ditampilkan ke server aplikasi embedding yang memanggil.
- Server aplikasi embedding menghapus token referensi sesi dari respons dan menampilkan respons yang tersisa ke klien aplikasi embedding.
- Klien aplikasi embedding mengirim token yang baru dibuat ke UI Looker. Looker Embed SDK akan melakukannya secara otomatis. Klien aplikasi embedding yang menggunakan
windows.postMessageAPI akan bertanggung jawab untuk mengirim token. Setelah UI Looker menerima token, token tersebut akan digunakan dalam panggilan API dan navigasi halaman berikutnya.
Menerapkan sematan tanpa cookie Looker
Sematan tanpa cookie Looker dapat diterapkan menggunakan Looker Embed SDK atau windows.postMessage API. Anda dapat menggunakan metode Looker Embed SDK, tetapi contoh yang menunjukkan cara menggunakan windows.postMessage API juga tersedia. Penjelasan mendetail tentang kedua penerapan dapat ditemukan dalam file README Looker Embed SDK. Repositori Git Embed SDK juga berisi penerapan yang berfungsi.
Mengonfigurasi instance Looker
Embedding tanpa cookie memiliki kesamaan dengan embedding yang ditandatangani Looker. Untuk menggunakan embedding tanpa cookie, admin harus mengaktifkan Autentikasi SSO Sematan. Namun, tidak seperti embedding yang ditandatangani Looker, embedding tanpa cookie tidak menggunakan setelan Rahasia Sematan. Embedding tanpa cookie menggunakan Token Web JSON (JWT) dalam bentuk setelan Rahasia JWT Sematan, yang dapat ditetapkan atau direset di halaman Sematan di bagian Platform pada menu Admin.
Menetapkan rahasia JWT tidak diperlukan, karena upaya pertama untuk membuat sesi sematan tanpa cookie akan membuat JWT. Hindari mereset token ini, karena tindakan tersebut akan membatalkan semua sesi sematan tanpa cookie yang aktif.
Tidak seperti rahasia sematan, rahasia JWT sematan tidak pernah diekspos, karena hanya digunakan secara internal di server Looker.
Penerapan klien aplikasi
Bagian ini menyertakan contoh cara menerapkan embedding tanpa cookie di klien aplikasi dan berisi subbagian berikut:
- Menginstal dan memperbarui Looker Embed SDK
- Menggunakan Looker Embed SDK
- Menggunakan
windows.postMessageAPI Looker
Menginstal atau memperbarui Looker Embed SDK
Versi Looker SDK berikut diperlukan untuk menggunakan embedding tanpa cookie:
@looker/embed-sdk >= 2.0.0
@looker/sdk >= 22.16.0
Menggunakan Looker Embed SDK
Metode inisialisasi baru telah ditambahkan ke Embed SDK untuk memulai sesi tanpa cookie. Metode ini menerima dua string URL atau dua fungsi callback. String URL harus mereferensikan endpoint di server aplikasi embedding. Detail penerapan endpoint ini di server aplikasi dibahas di bagian Penerapan server aplikasi dalam dokumen ini.
getEmbedSDK().initCookieless(
runtimeConfig.lookerHost,
'/acquire-embed-session',
'/generate-embed-tokens'
)
Contoh berikut menunjukkan cara penggunaan callback. Callback hanya boleh digunakan jika aplikasi klien embedding perlu mengetahui status sesi embedding Looker. Anda juga dapat menggunakan session:status peristiwa, sehingga tidak perlu menggunakan callback dengan 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
)
Menggunakan windows.postMessage API Looker
Anda dapat melihat contoh mendetail tentang penggunaan windows.postMessage API di file message_example.ts dan message_utils.ts di repositori Git Embed SDK. Sorotan contohnya dijelaskan di sini.
Contoh berikut menunjukkan cara mem-build URL untuk iframe. Fungsi callback identik dengan contoh acquireEmbedSessionCallback yang terlihat sebelumnya.
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}`
}
Contoh berikut menunjukkan cara memproses permintaan token, membuat token baru, dan mengirimkannya ke Looker. Fungsi callback identik dengan contoh generateEmbedTokensCallback sebelumnya.
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
}
Penerapan server aplikasi
Bagian ini menyertakan contoh cara menerapkan embedding tanpa cookie di server aplikasi dan berisi subbagian berikut:
Penerapan dasar
Aplikasi embedding harus menerapkan dua endpoint sisi server yang akan memanggil endpoint Looker. Hal ini untuk memastikan token referensi sesi tetap aman. Berikut adalah endpointnya:
- Memperoleh sesi — Jika token referensi sesi sudah ada dan masih aktif, permintaan untuk sesi akan bergabung dengan sesi yang ada. Memperoleh sesi dipanggil saat iframe dibuat.
- Membuat token — Looker memicu panggilan ke endpoint ini secara berkala.
Memperoleh sesi
Contoh ini dalam TypeScript menggunakan sesi untuk menyimpan atau memulihkan token referensi sesi. Endpoint tidak harus diterapkan di 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
}
}
Mulai Looker 23.8, domain sematan dapat disertakan saat sesi tanpa cookie diperoleh. Ini adalah alternatif untuk menambahkan domain sematan menggunakan panel Admin > Sematan Looker. Looker menyimpan domain sematan di database internal Looker, sehingga tidak akan ditampilkan di panel Admin > Sematan. Sebagai gantinya, domain sematan dikaitkan dengan sesi tanpa cookie dan hanya ada selama durasi sesi. Tinjau praktik terbaik keamanan jika Anda memutuskan untuk memanfaatkan fitur ini.
Membuat token
Contoh ini dalam TypeScript menggunakan sesi untuk menyimpan atau memulihkan token referensi sesi. Endpoint tidak harus diterapkan di TypeScript.
Anda harus mengetahui cara menangani respons 400, yang terjadi saat token tidak valid. Meskipun respons 400 yang ditampilkan seharusnya tidak terjadi, jika terjadi, sebaiknya akhiri sesi sematan Looker. Anda dapat mengakhiri sesi sematan Looker dengan menghancurkan iframe sematan atau dengan menetapkan nilai session_reference_token_ttl ke nol dalam pesan session:tokens. Jika Anda menetapkan nilai session_reference_token_ttl ke nol, iframe Looker akan menampilkan dialog sesi berakhir.
Respons 400 tidak ditampilkan saat sesi sematan berakhir. Jika sesi sematan telah berakhir, respons 200 akan ditampilkan dengan nilai session_reference_token_ttl yang ditetapkan ke nol.
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
}
Pertimbangan penerapan
Aplikasi embedding harus melacak token referensi sesi dan harus menjaganya tetap aman. Token ini harus dikaitkan dengan pengguna aplikasi sematan. Token aplikasi embedding dapat disimpan dengan salah satu cara berikut:
- Dalam sesi pengguna aplikasi sematan
- Dalam cache sisi server yang tersedia di seluruh lingkungan cluster
- Dalam tabel database yang terkait dengan pengguna
Jika sesi disimpan sebagai cookie, cookie harus dienkripsi. Contoh di repositori SDK sematan menggunakan cookie sesi untuk menyimpan token referensi sesi.
Saat sesi sematan Looker berakhir, dialog akan ditampilkan di iframe sematan. Pada saat ini, pengguna tidak akan dapat melakukan apa pun di instance sematan. Saat hal ini terjadi, peristiwa session:status akan dibuat, sehingga aplikasi embedding dapat mendeteksi status aplikasi Looker sematan saat ini dan melakukan tindakan tertentu.
Aplikasi embedding dapat mendeteksi apakah sesi sematan telah berakhir dengan memeriksa apakah nilai session_reference_token_ttl yang ditampilkan oleh endpoint generate_tokens adalah nol. Jika nilainya nol, sesi sematan telah berakhir. Pertimbangkan untuk menggunakan fungsi callback untuk membuat token saat sematan tanpa cookie diinisialisasi. Fungsi callback kemudian dapat menentukan apakah sesi sematan telah berakhir dan akan menghancurkan iframe sematan sebagai alternatif untuk menggunakan dialog sesi sematan berakhir default.
Menjalankan contoh sematan tanpa cookie Looker
Repositori SDK sematan berisi server dan klien node express yang ditulis dalam TypeScript yang menerapkan aplikasi sematan. Contoh yang ditampilkan sebelumnya diambil dari penerapan ini. Berikut ini mengasumsikan bahwa instance Looker Anda telah dikonfigurasi untuk menggunakan sematan tanpa cookie seperti yang dijelaskan sebelumnya.
Anda dapat menjalankan server sebagai berikut:
- Kloning repositori Embed SDK —
git clone git@github.com:looker-open-source/embed-sdk.git - Ubah direktori —
cd embed-sdk - Instal dependensi —
npm install - Konfigurasi server, seperti yang ditunjukkan di bagian Mengonfigurasi server dalam dokumen ini.
- Jalankan server —
npm run server
Mengonfigurasi server
Buat file .env di root repositori yang di-clone (file ini disertakan dalam .gitignore).
Formatnya adalah sebagai berikut:
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