Autenticação da API Looker usando OAuth

O Looker usa o OAuth para permitir que os aplicativos cliente OAuth se autentiquem na API Looker sem expor IDs do cliente e secrets do cliente ao navegador que executa o aplicativo cliente OAuth.

Os aplicativos da Web que usam OAuth precisam atender aos seguintes requisitos:

  • A autenticação usando OAuth está disponível apenas com a API Looker 4.0.
  • Os aplicativos cliente OAuth precisam ser registrados no Looker usando a API antes que os usuários do aplicativo possam se autenticar no Looker.
  • Os aplicativos clientes precisam usar HTTPS para todas as solicitações à API Looker. Os aplicativos clientes que quiserem usar as APIs SubtleCrypto fornecidas pelo navegador precisam ser hospedados por HTTPS.

Suporte para CORS da API Looker

A API Looker permite ser chamada no navegador e em diferentes origens usando o protocolo Compartilhamento de recursos entre origens (CORS). O suporte ao Looker CORS tem os seguintes requisitos:

  • Somente origens listadas na lista de permissões de domínios incorporados podem chamar a API usando CORS.
  • Somente tokens de acesso recebidos do OAuth ou da chamada do endpoint da API /login podem ser usados para fazer chamadas para a API do Looker usando CORS.

    O endpoint da API /login não pode ser chamado usando solicitações CORS. Os aplicativos clientes que desejam chamar a API Looker usando solicitações CORS precisam usar o processo de login do OAuth descrito em Fazer login do usuário com OAuth ou recuperar um token do servidor do aplicativo ou de chamadas de API que não sejam CORS.

Visão geral da autenticação OAuth

Uma visão geral do processo de autenticação OAuth é a seguinte:

  1. Registre o aplicativo cliente OAuth com a API Looker.
  2. Adicione a origem do seu aplicativo cliente OAuth à lista de permissões de domínios incorporados para a chamada da API de troca de código e para quaisquer chamadas seguintes da API CORS.
  3. Redirecione o URL do navegador para o endpoint /auth no nome do host da IU do Looker (não o nome do host da API Looker) quando o aplicativo cliente do OAuth tentar autenticar um usuário. Por exemplo, https://instance_name.looker.com.
  4. Se o usuário estiver autenticado e conectado ao Looker, o Looker retornará um redirecionamento de OAuth para o aplicativo cliente de OAuth imediatamente. Se o usuário ainda não tiver feito login no Looker no dispositivo e navegador atuais, a tela de login do Looker será exibida, e o usuário precisará fazer login na conta de usuário do Looker usando o protocolo de autenticação regular.
  5. Usando o código de autorização retornado no redirecionamento OAuth, seu aplicativo cliente OAuth precisa fazer uma chamada para o endpoint /token no nome do host da API Looker, por exemplo, https://instance_name.looker.com:19999. O nome do host da API pode ser igual ou diferente do nome do host da IU do Looker. O endpoint /token existe apenas no host da API Looker, e o endpoint /auth existe apenas no host da IU do Looker.
  6. Se o código de autorização transmitido ao endpoint /token for válido, o Looker retornará uma API access_token, que é ativada para solicitações de API CORS do domínio do aplicativo do cliente OAuth.

Como registrar um aplicativo cliente OAuth

Cada aplicativo cliente OAuth que tentar autenticar na API Looker usando OAuth deve ser registrado primeiro na instância do Looker antes de autorizar o acesso. Para registrar um aplicativo cliente OAuth:

  1. Abra o API Explorer na instância do Looker.
  2. Usando o menu suspenso de versões, escolha a versão 4.0 - estável da API.
  3. No método Auth, encontre o endpoint da API register_oauth_client_app(). Também é possível pesquisar "oauth app" no campo Search. É possível usar register_oauth_client_app() para registrar o aplicativo cliente OAuth no Looker. Clique no botão Executar e insira os parâmetros no API Explorer e clique novamente em Executar para registrar o aplicativo cliente OAuth ou use o endpoint da API register_oauth_client_app() de forma programática. Os parâmetros register_oauth_client_app() necessários são:

    • client_guid: um ID globalmente exclusivo para o aplicativo.
    • redirect_uri: o URI em que o app receberá um redirecionamento de OAuth que inclui um código de autorização
    • display_name: o nome do aplicativo que é exibido aos usuários dele.
    • description: uma descrição do aplicativo que é exibida para os usuários em uma página de divulgação e confirmação quando eles fazem login pela primeira vez no aplicativo

    Os valores nos parâmetros client_guid e redirect_uri precisam ser iguais aos valores fornecidos pelo aplicativo cliente OAuth exatamente. Caso contrário, a autenticação será negada.

Como fazer login do usuário usando o OAuth

  1. Navegue o usuário até o endpoint /auth no host da IU. Exemplo:

    async function oauth_login() {
      const code_verifier = secure_random(32)
      const code_challenge = await sha256_hash(code_verifier)
      const params = {
        response_type: 'code',
        client_id: '123456',
        redirect_uri: 'https://mywebapp.com:3000/authenticated',
        scope: 'cors_api',
        state: '1235813',
        code_challenge_method: 'S256',
        code_challenge: code_challenge,
      }
      const url = `${base_url}?${new URLSearchParams(params).toString()}` // Replace base_url with your full Looker instance's UI host URL, plus the `/auth` endpoint.
      log(url)
    
      // Stash the code verifier we created in sessionStorage, which
      // will survive page loads caused by login redirects
      // The code verifier value is needed after the login redirect
      // to redeem the auth_code received for an access_token
      //
      sessionStorage.setItem('code_verifier', code_verifier)
    
      document.location = url
    }
    
    function array_to_hex(array) {
      return Array.from(array).map(b => b.toString(16).padStart(2,'0')).join('')
    }
    
    function secure_random(byte_count) {
      const array = new Uint8Array(byte_count);
      crypto.getRandomValues(array);
      return array_to_hex(array)
    }
    
    async function sha256_hash(message) {
      const msgUint8 = new TextEncoder().encode(message)
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8)
      return base64.urlEncode(hashBuffer))  // Refers to the implementation of base64.encode stored at https://gist.github.com/jhurliman/1250118
    }
    

    O exemplo de código acima depende das APIs SubtleCrypto fornecidas pelo navegador, mas o navegador permite o uso dessas funções somente de páginas da Web seguras (HTTPS).

    O Looker tentará autenticar o usuário usando o sistema de autenticação em que a instância do Looker está configurada.

    • Se o usuário já tiver feito login no Looker no navegador atual (o que significa que há um estado de cookie de login ativo), o usuário não receberá uma solicitação para inserir as credenciais de login.
    • Se esta for a primeira vez que este usuário faz login usando este aplicativo do cliente OAuth, o Looker mostrará uma página de divulgação e confirmação para o usuário confirmar e aceitar. O texto do parâmetro description usado quando o aplicativo foi registrado será exibido. A descrição deve indicar o que o aplicativo pretende fazer com a conta do Looker do usuário. Quando o usuário clicar em Aceitar, a página redirecionará para o aplicativo redirect_uri.
    • Se o usuário já tiver feito login no Looker no navegador atual e já tiver confirmado a página de divulgação, o login do OAuth será instantâneo , sem interrupções visuais.
  2. A API Looker retornará um redirecionamento de OAuth para o aplicativo cliente de OAuth. Salve o código de autorização listado no parâmetro URI. Veja a seguir um exemplo de URI de redirecionamento OAuth:

    https://mywebapp.com:3000/authenticated?&code=asdfasdfassdf&state=...
    

    O código de autorização é mostrado depois de &code= no URI. No exemplo acima, o código é: asdfasdfassdf.

  3. Faça uma solicitação da Web para o endpoint /token na API Looker, transmitindo o código de autorização e as informações do aplicativo. Exemplo:

    async function redeem_auth_code(response_str) {
      const params = new URLSearchParams(response_str)
      const auth_code = params.get('code')
    
      if (!auth_code) {
        log('ERROR: No authorization code in response')
        return
      }
      log(`auth code received: ${auth_code}`)
      log(`state: ${params.get('state')}`)
    
      const code_verifier = sessionStorage.getItem('code_verifier')
      if (!code_verifier) {
        log('ERROR: Missing code_verifier in session storage')
        return
      }
      sessionStorage.removeItem('code_verifier')
      const response = await
      fetch('https://mycompany.looker.com:19999/api/token', {  // This is the URL of your Looker instance's API web service
        method: 'POST',
        mode: 'cors',    // This line is required so that the browser will attempt a CORS request.
        body: stringify({
          grant_type: 'authorization_code',
          client_id: '123456',
          redirect_uri: 'https://mywebapp.com:3000/authenticated',
          code: auth_code,
          code_verifier: code_verifier,
        }),
        headers: {
          'x-looker-appid': 'Web App Auth & CORS API Demo', // This header is optional.
          'Content-Type': 'application/json;charset=UTF-8'  // This header is required.
        },
      }).catch((error) => {
        log(`Error: ${error.message}`)
      })
    
      const info = await response.json()
      log(`/api/token response: ${stringify(info)}`)
    
      // Store the access_token and other info,
      // which in this example is done in sessionStorage
    
      const expires_at = new Date(Date.now() + (info.expires_in * 1000))
      info.expires_at = expires_at
      log(`Access token expires at ${expires_at.toLocaleTimeString()} local time.`)
      sessionStorage.setItem('access_info', stringify(info))
      access_info = info
    }
    

    Uma resposta bem-sucedida fornece ao aplicativo cliente OAuth uma API access_token. A resposta também conterá um refresh_token, que pode ser usado mais tarde para receber um novo access_token sem interação do usuário. Uma refresh_token tem a duração de um mês. Armazene o refresh_token com segurança.

    Todos os tokens nesse sistema podem ser revogados pelo administrador do Looker a qualquer momento.