Intégration sans cookie

Lorsque Looker est intégré dans un iFrame à l'aide de l'intégration signée, certains navigateurs utilisent par défaut une règle de cookies qui bloque les cookies tiers. Les cookies tiers sont rejetés lorsque l'iFrame intégré est chargé à partir d'un domaine différent de celui qui charge l'application d'intégration. Vous pouvez généralement contourner cette limite en demandant et en utilisant un domaine personnalisé. Toutefois, les domaines personnalisés ne peuvent pas être utilisés dans certains cas. C'est dans ces cas que l'intégration sans cookies de Looker peut être utilisée.

Comment fonctionne l'intégration sans cookies ?

Lorsque les cookies tiers ne sont pas bloqués, un cookie de session est créé lorsqu'un utilisateur se connecte à Looker pour la première fois. Ce cookie est envoyé avec chaque requête utilisateur, et le serveur Looker l'utilise pour établir l'identité de l'utilisateur qui a lancé la requête. Lorsque les cookies sont bloqués, le cookie n'est pas envoyé avec une requête. Le serveur Looker ne peut donc pas identifier l'utilisateur associé à la requête.

Pour résoudre ce problème, l'intégration sans cookies de Looker associe des jetons à chaque requête qui peuvent être utilisés pour recréer la session utilisateur sur le serveur Looker. Il incombe à l'application d'intégration d'obtenir ces jetons et de les mettre à la disposition de l'instance Looker qui s'exécute dans l'iFrame intégré. Le processus d'obtention et de fourniture de ces jetons est décrit dans le reste de ce document.

Pour utiliser l'une ou l'autre des API, l'application d'intégration doit pouvoir s'authentifier auprès de l'API Looker avec des droits d'administrateur. Le domaine d'intégration doit également être répertorié dans la liste d'autorisation des domaines d'intégration. Si vous utilisez Looker 23.8 ou une version ultérieure, le domaine d'intégration peut être inclus lors de l'acquisition de la session sans cookies.

Créer un iFrame d'intégration Looker

Le diagramme de séquence suivant illustre la création d'un iFrame d'intégration. Plusieurs iFrames peuvent être générés simultanément ou à un moment donné. Lorsqu'il est correctement implémenté, l'iFrame rejoint automatiquement la session créée par le premier iFrame. Le SDK d'intégration Looker simplifie ce processus en rejoignant automatiquement la session existante.

Diagramme de séquence illustrant la création d'un iframe d'intégration.

  1. L'utilisateur effectue une action dans l'application d'intégration, ce qui entraîne la création d'un iFrame Looker.
  2. Le client de l'application d'intégration acquiert une session Looker. Le SDK d'intégration Looker peut être utilisé pour lancer cette session, mais une URL de point de terminaison ou une fonction de rappel doit être fournie. Si une fonction de rappel est utilisée, elle appelle le serveur d'application d'intégration pour acquérir la session d'intégration Looker. Sinon, le SDK d'intégration appelle l'URL de point de terminaison fournie.
  3. Le serveur d'application d'intégration utilise l'API Looker pour acquérir une session d'intégration. Cet appel d'API est semblable au processus de signature d'intégration signée de Looker, car il accepte la définition de l'utilisateur d'intégration comme entrée. Si une session d'intégration Looker existe déjà pour l'utilisateur appelant, le jeton de référence de session associé doit être inclus dans l'appel. Ce point sera expliqué plus en détail dans la section Acquérir une session de ce document.
  4. Le traitement du point de terminaison d'acquisition de session d'intégration est semblable au point de terminaison signé /login/embed/(signed url), car il attend la définition de l'utilisateur d'intégration Looker comme corps de la requête, plutôt que dans l'URL. Le processus du point de terminaison d'acquisition de session d'intégration valide, puis crée ou met à jour l'utilisateur d'intégration. Il peut également accepter un jeton de référence de session existant. Ceci est important, car cela permet à plusieurs iFrames intégrés Looker de partager la même session. L'utilisateur d'intégration n'est pas mis à jour si un jeton de référence de session est fourni et que la session n'a pas expiré. Cela est compatible avec le cas d'utilisation où un iFrame est créé à l'aide d'une URL d'intégration signée et d'autres iFrames sont créés sans URL d'intégration signée. Dans ce cas, les iFrames sans URL d'intégration signée héritent du cookie de la première session.
  5. L'appel d'API Looker renvoie quatre jetons, chacun avec une valeur TTL (Time To Live) :
    • Jeton d'autorisation (TTL = 30 secondes)
    • Jeton de navigation (TTL = 10 minutes)
    • Jeton d'API (TTL = 10 minutes)
    • Jeton de référence de session (TTL = durée de vie restante de la session)
  6. Le serveur d'application d'intégration doit suivre les données renvoyées par les données Looker et les associer à la fois à l'utilisateur appelant et à l'user-agent du navigateur de l'utilisateur appelant. Des suggestions sur la façon de procéder sont fournies dans la section Générer des jetons de ce document. Cet appel renvoie le jeton d'autorisation, un jeton de navigation et un jeton d'API, ainsi que toutes les valeurs TTL associées. Le jeton de référence de session doit être sécurisé et ne pas être exposé dans le navigateur appelant.
  7. Une fois les jetons renvoyés au navigateur, une URL de connexion d'intégration Looker doit être créée. Le SDK d'intégration Looker crée automatiquement l'URL de connexion d'intégration. Pour utiliser l'API windows.postMessage afin de créer l'URL de connexion d'intégration, consultez la section Utiliser l'API windows.postMessage de Looker de ce document pour obtenir des exemples.

    L'URL de connexion ne contient pas les détails de l'utilisateur d'intégration signé. Elle contient l'URI cible, y compris le jeton de navigation, et le jeton d'autorisation en tant que paramètre de requête. Le jeton d'autorisation doit être utilisé dans les 30 secondes et ne peut être utilisé qu'une seule fois. Si des iFrames supplémentaires sont nécessaires, une session d'intégration doit être acquise à nouveau. Toutefois, si le jeton de référence de session est fourni, le jeton d'autorisation sera associé à la même session.

  8. Le point de terminaison de connexion d'intégration Looker détermine si la connexion concerne l'intégration sans cookies, qui est indiquée par la présence du jeton d'autorisation. Si le jeton d'autorisation est valide, il vérifie les points suivants :

    • La session associée est toujours valide.
    • L'utilisateur d'intégration associé est toujours valide.
    • L'user-agent du navigateur associé à la requête correspond à l'agent de navigateur associé à la session.
  9. Si les vérifications de l'étape précédente sont réussies, la requête est redirigée à l'aide de l'URI cible contenu dans l'URL. Il s'agit du même processus que pour la connexion d'intégration signée de Looker.

  10. Cette requête est la redirection permettant de lancer le tableau de bord Looker. Cette requête aura le jeton de navigation comme paramètre.

  11. Avant l'exécution du point de terminaison, le serveur Looker recherche le jeton de navigation dans la requête. Si le serveur trouve le jeton, il vérifie les points suivants :

    • La session associée est toujours valide.
    • L'user-agent du navigateur associé à la requête correspond à l'agent de navigateur associé à la session.

    Si elle est valide, la session est restaurée pour la requête et la requête de tableau de bord s'exécute.

  12. Le code HTML permettant de charger le tableau de bord est renvoyé à l'iFrame.

  13. L'interface utilisateur Looker qui s'exécute dans l'iFrame détermine que le code HTML du tableau de bord est une réponse d'intégration sans cookies. À ce stade, l'interface utilisateur Looker envoie un message à l'application d'intégration pour demander les jetons récupérés à l'étape 6. L'interface utilisateur attend ensuite de recevoir les jetons. Si les jetons n'arrivent pas, un message s'affiche.

  14. L'application d'intégration envoie les jetons à l'iFrame intégré Looker.

  15. Lorsque les jetons sont reçus, l'interface utilisateur Looker qui s'exécute dans l'iFrame lance le processus de rendu de l'objet de requête. Au cours de ce processus, l'interface utilisateur effectue des appels d'API au serveur Looker. Le jeton d'API reçu à l'étape 15 est automatiquement injecté en tant qu'en-tête dans toutes les requêtes d'API.

  16. Avant l'exécution d'un point de terminaison, le serveur Looker recherche le jeton d'API dans la requête. Si le serveur trouve le jeton, il vérifie les points suivants :

    • La session associée est toujours valide.
    • L'user-agent du navigateur associé à la requête correspond à l'agent de navigateur associé à la session.

    Si la session est valide, elle est restaurée pour la requête et la requête d'API s'exécute.

  17. Les données du tableau de bord sont renvoyées.

  18. Le tableau de bord est affiché.

  19. L'utilisateur contrôle le tableau de bord.

Générer de nouveaux jetons

Le diagramme de séquence suivant illustre la génération de nouveaux jetons.

Diagramme de séquence illustrant la génération de jetons.

  1. L'interface utilisateur Looker qui s'exécute dans l'iFrame intégré surveille la durée de vie (TTL) des jetons d'intégration.
  2. Lorsque les jetons approchent de leur expiration, l'interface utilisateur Looker envoie un message de jeton d'actualisation au client de l'application d'intégration.
  3. Le client de l'application d'intégration demande ensuite de nouveaux jetons à un point de terminaison implémenté dans le serveur d'application d'intégration. Le SDK d'intégration Looker demande automatiquement de nouveaux jetons, mais l'URL du point de terminaison ou une fonction de rappel doit être fournie. Si la fonction de rappel est utilisée, elle appelle le serveur d'application d'intégration pour générer de nouveaux jetons. Sinon, le SDK d'intégration appelle l'URL de point de terminaison fournie.
  4. L'application d'intégration recherche le session_reference_token associé à la session d'intégration. L'exemple fourni dans le dépôt Git du SDK d'intégration Looker utilise des cookies de session, mais un cache côté serveur distribué, Redis par exemple, peut également être utilisé.
  5. Le serveur d'application d'intégration appelle le serveur Looker avec une requête de génération de jetons. Cette requête nécessite également des jetons d'API et de navigation récents, en plus de l'user-agent du navigateur qui a lancé la requête.
  6. Le serveur Looker valide l'user-agent, le jeton de référence de session, le jeton de navigation et le jeton d'API. Si la requête est valide, de nouveaux jetons sont générés.
  7. Les jetons sont renvoyés au serveur d'application d'intégration appelant.
  8. Le serveur d'application d'intégration supprime le jeton de référence de session de la réponse et renvoie le reste de la réponse au client de l'application d'intégration.
  9. Le client de l'application d'intégration envoie les jetons nouvellement générés à l'interface utilisateur Looker. Le SDK d'intégration Looker le fait automatiquement. Les clients d'application d'intégration qui utilisent l'API windows.postMessage sont responsables de l'envoi des jetons. Une fois que l'interface utilisateur Looker reçoit les jetons, ils sont utilisés dans les appels d'API et les navigations de page suivants.

Implémenter l'intégration sans cookies de Looker

L'intégration sans cookies de Looker peut être implémentée à l'aide du SDK d'intégration Looker ou de l'API windows.postMessage. Vous pouvez utiliser la méthode Looker Embed SDK, mais un exemple montrant comment utiliser l'API windows.postMessage est également disponible. Des explications détaillées des deux implémentations sont disponibles dans le fichier README du SDK d'intégration Looker Embed. Le dépôt Git du SDK d'intégration contient également des implémentations fonctionnelles.

Configurer l'instance Looker

L'intégration sans cookies présente des points communs avec l'intégration signée de Looker. Pour utiliser l'intégration sans cookies, un administrateur doit activer l'authentification SSO d'intégration. Toutefois, contrairement à l'intégration signée de Looker, l'intégration sans cookies n'utilise pas le paramètre Secret d'intégration. L'intégration sans cookies utilise un jeton Web JSON (JWT) sous la forme d'un paramètre Secret JWT d'intégration, qui peut être défini ou réinitialisé sur la page Intégrer de la section Plate-forme du menu Admin.

La définition du secret JWT n'est pas obligatoire, car la toute première tentative de création d'une session d'intégration sans cookies crée le JWT. Évitez de réinitialiser ce jeton, car cela invaliderait toutes les sessions d'intégration sans cookies actives.

Contrairement au secret d'intégration, le secret JWT d'intégration n'est jamais exposé, car il n'est utilisé qu'en interne sur le serveur Looker.

Implémentation du client d'application

Cette section inclut des exemples d'implémentation de l'intégration sans cookies dans le client d'application et contient les sous-sections suivantes :

Installer ou mettre à jour le SDK d'intégration Looker

Les versions suivantes du SDK Looker sont requises pour utiliser l'intégration sans cookies :

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

Utiliser le SDK d'intégration Looker

Une nouvelle méthode d'initialisation a été ajoutée au SDK d'intégration pour lancer la session sans cookies. Cette méthode accepte deux chaînes d'URL ou deux fonctions de rappel. Les chaînes d'URL doivent faire référence à des points de terminaison dans le serveur d'application d'intégration. Les détails d'implémentation de ces points de terminaison sur le serveur d'application sont abordés dans la section Implémentation du serveur d'application de ce document.

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

L'exemple suivant montre comment les rappels sont utilisés. Les rappels ne doivent être utilisés que lorsque l'application cliente d'intégration doit connaître l'état de la session d'intégration Looker. Vous pouvez également utiliser l'événement session:status, ce qui rend inutile l'utilisation de rappels avec le SDK d'intégration.

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
)

Utiliser l'API windows.postMessage de Looker

Vous pouvez consulter un exemple détaillé d'utilisation de l'API windows.postMessage dans les fichiers message_example.ts et message_utils.ts du dépôt Git du SDK d'intégration. Les points clés de l'exemple sont détaillés ici.

L'exemple suivant montre comment créer l'URL de l'iFrame. La fonction de rappel est identique à l'exemple acquireEmbedSessionCallback vu précédemment.

  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}`
  }

L'exemple suivant montre comment écouter les requêtes de jeton, générer de nouveaux jetons et les envoyer à Looker. La fonction de rappel est identique à l'exemple generateEmbedTokensCallback précédent.

      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
  }

Implémentation du serveur d'application

Cette section inclut des exemples d'implémentation de l'intégration sans cookies dans le serveur d'application et contient les sous-sections suivantes :

Implémentation de base

L'application d'intégration doit implémenter deux points de terminaison côté serveur qui appellent des points de terminaison Looker. Cela permet de s'assurer que le jeton de référence de session reste sécurisé. Voici les points de terminaison :

  1. Acquérir une session : si un jeton de référence de session existe déjà et est toujours actif, les requêtes de session rejoignent la session existante. Acquérir une session est appelé lorsqu'un iFrame est créé.
  2. Générer des jetons : Looker déclenche des appels à ce point de terminaison de manière périodique.

Acquérir une session

Cet exemple en TypeScript utilise la session pour enregistrer ou restaurer le jeton de référence de session. Le point de terminaison ne doit pas nécessairement être implémenté en 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
  }
}

À partir de Looker 23.8, le domaine d'intégration peut être inclus lors de l'acquisition de la session sans cookies. Il s'agit d'une alternative à l'ajout du domaine d'intégration à l'aide du panneau Admin > Intégrer de Looker. Looker enregistre le domaine d'intégration dans la base de données interne de Looker. Il n'apparaît donc pas dans le panneau Admin > Intégrer. Au lieu de cela, le domaine d'intégration est associé à la session sans cookies et n'existe que pendant la durée de la session. Consultez les bonnes pratiques de sécurité si vous décidez de profiter de cette fonctionnalité.

Générer des jetons

Cet exemple en TypeScript utilise la session pour enregistrer ou restaurer le jeton de référence de session. Le point de terminaison ne doit pas nécessairement être implémenté en TypeScript.

Il est important de savoir comment gérer les réponses 400, qui se produisent lorsque les jetons ne sont pas valides. Bien qu'une réponse 400 ne devrait pas se produire, si c'est le cas, il est recommandé de mettre fin à la session d'intégration Looker. Vous pouvez mettre fin à la session d'intégration Looker en détruisant l'iFrame d'intégration ou en définissant la valeur session_reference_token_ttl sur zéro dans le message session:tokens. Si vous définissez la valeur session_reference_token_ttl sur zéro, l'iFrame Looker affiche une boîte de dialogue indiquant que la session a expiré.

Une réponse 400 n'est pas renvoyée lorsque la session d'intégration expire. Si la session d'intégration a expiré, une réponse 200 est renvoyée avec la valeur session_reference_token_ttl définie sur zéro.

  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
  }

Points à observer avant de configurer des événements

L'application d'intégration doit suivre le jeton de référence de session et le sécuriser. Ce jeton doit être associé à l'utilisateur de l'application intégrée. Le jeton de l'application d'intégration peut être stocké de l'une des manières suivantes :

  • Dans la session de l'utilisateur de l'application intégrée
  • Dans un cache côté serveur disponible dans un environnement en cluster
  • Dans une table de base de données associée à l'utilisateur

Si la session est stockée sous forme de cookie, le cookie doit être chiffré. L'exemple du dépôt du SDK d'intégration utilise un cookie de session pour stocker le jeton de référence de session.

Lorsque la session d'intégration Looker expire, une boîte de dialogue s'affiche dans l'iFrame intégré. À ce stade, l'utilisateur ne pourra rien faire dans l'instance intégrée. Lorsque cela se produit, les session:status événements sont générés, ce qui permet à l'application d'intégration de détecter l'état actuel de l'application Looker intégrée et d'effectuer une action.

Une application d'intégration peut détecter si la session d'intégration a expiré en vérifiant si la valeur session_reference_token_ttl renvoyée par le point de terminaison generate_tokens est égale à zéro. Si la valeur est égale à zéro, la session d'intégration a expiré. Envisagez d'utiliser une fonction de rappel pour générer des jetons lors de l'initialisation de l'intégration sans cookies. La fonction de rappel peut ensuite déterminer si la session d'intégration a expiré et détruire l'iFrame intégré au lieu d'utiliser la boîte de dialogue par défaut indiquant que la session intégrée a expiré.

Exécuter l'exemple d'intégration sans cookies de Looker

Le dépôt du SDK d'intégration contient un serveur et un client d'expression de nœud écrits en TypeScript qui implémentent une application d'intégration. Les exemples présentés précédemment sont issus de cette implémentation. Les informations suivantes supposent que votre instance Looker a été configurée pour utiliser l'intégration sans cookies, comme décrit précédemment.

Vous pouvez exécuter le serveur comme suit :

  1. Cloner le dépôt du SDK d'intégration : git clone git@github.com:looker-open-source/embed-sdk.git
  2. Modifier le répertoire : cd embed-sdk
  3. Installer les dépendances : npm install
  4. Configurer le serveur, comme indiqué dans la section Configurer le serveur de ce document.
  5. Exécuter le serveur : npm run server

Configurer le serveur

Créez un fichier .env à la racine du dépôt cloné (inclus dans .gitignore).

Le format est le suivant :

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