Autenticação da API Looker usando o OAuth

O Looker usa OAuth para permitir que aplicativos cliente OAuth façam a autenticação na API Looker sem expor IDs e chaves secretas do cliente ao navegador que está executando o aplicativo cliente OAuth.

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

  • A autenticação usando o 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 fazer a autenticação no Looker.
  • Os aplicativos cliente precisam usar HTTPS para todas as solicitações à API Looker. Os aplicativos cliente que querem usar as APIs SubtleCrypto fornecidas pelo navegador precisam ser hospedados em HTTPS.

Suporte ao CORS da API Looker

A API Looker pode ser chamada no navegador e entre origens usando o protocolo de compartilhamento de recursos de origem cruzada (CORS, na sigla em inglês). O suporte ao CORS do Looker tem os seguintes requisitos:

  • Somente as origens listadas na lista de permissões de domínio incorporado podem chamar a API usando o CORS.

  • Somente tokens de acesso obtidos do OAuth ou da chamada do endpoint de API /login podem ser usados para fazer chamadas à API Looker usando o CORS.

Visão geral da autenticação OAuth

Confira a seguir uma visão geral do processo de autenticação OAuth:

  1. Registre o aplicativo cliente OAuth na API Looker.
  2. Adicione a origem do aplicativo cliente OAuth à sua lista de permissões de domínio incorporado para a chamada de API de troca de código e todas as chamadas de API CORS subsequentes.

  3. Redirecione o URL do navegador para o endpoint /auth no nome do host da interface do Looker (não o nome do host da API Looker) quando o aplicativo cliente OAuth tentar autenticar um usuário. Por exemplo, https://instance_name.looker.com.

  4. Se o usuário for autenticado e fizer login no Looker, o Looker vai retornar um redirecionamento OAuth para o aplicativo cliente OAuth imediatamente. Se o usuário ainda não tiver feito login no Looker no dispositivo e no navegador, a tela de login do Looker será exibida e o usuário será solicitado a fazer login na conta de usuário do Looker usando o protocolo de autenticação normal.

  5. Usando o código de autorização retornado no redirecionamento OAuth, o 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 interface do Looker. O endpoint /token existe apenas no host da API Looker, e o endpoint /auth existe apenas no host da interface do Looker.

  6. Se o código de autorização transmitido ao endpoint /token for válido, o Looker vai retornar um access_token da API ativado para solicitações de API CORS do domínio do aplicativo cliente OAuth.

Como registrar um aplicativo cliente OAuth

Todo aplicativo cliente OAuth que tentar fazer a autenticação na API Looker usando o OAuth precisa ser registrado na instância do Looker antes que o Looker autorize o acesso. Para registrar um aplicativo cliente OAuth:

  1. Abra o API Explorer na instância do Looker.
  2. No menu suspenso de versão, escolha a versão 4.0 - estável da API.
  3. No método Auth, encontre o endpoint de API register_oauth_client_app(). Você também pode pesquisar "oauth app" no campo Pesquisar. É 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 APIs Explorer. Clique em Executar novamente para registrar o aplicativo cliente OAuth ou use o endpoint de API register_oauth_client_app() de forma programática. Os parâmetros register_oauth_client_app() obrigatórios são:

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

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

Como fazer login do usuário usando o OAuth

  1. Navegue até o endpoint /auth no host da UI. Por 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 Looker vai tentar autenticar o usuário usando o sistema de autenticação para o qual a instância do Looker está configurada.

    • Se o usuário já tiver feito login no Looker no navegador atual (ou seja, há um estado de cookie de login ativo), ele não será solicitado a inserir as credenciais de login.
    • Se esta for a primeira vez que o usuário faz login usando esse aplicativo cliente OAuth, o Looker vai mostrar uma página de divulgação e confirmação para o usuário reconhecer e aceitar. O texto do parâmetro description usado quando o aplicativo foi registrado será exibido. A descrição precisa 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 será redirecionada para o redirect_uri do aplicativo.
    • Se o usuário já tiver feito login no Looker no navegador atual e já tiver reconhecido a página de divulgação, o login do OAuth será instantâneo, sem interrupção visual.
  2. A API Looker vai retornar um redirecionamento OAuth para o aplicativo cliente OAuth. Salve o código de autorização listado no parâmetro URI. Confira a seguir um exemplo de URI de redirecionamento OAuth:

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

    O código de autorização é mostrado após &code= no URI. Neste exemplo, o código de autorização é 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. Por 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 vai fornecer ao aplicativo cliente OAuth um access_token da API. A resposta também vai conter um refresh_token, que você pode usar mais tarde para receber um novo access_token sem interação do usuário. Um refresh_token tem um ciclo de vida 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.