OAuth を使用した Looker API 認証

Looker では、OAuth を使用して、OAuth クライアント アプリケーションを OAuth API に認証します。その際、OAuth クライアント アプリケーションを実行しているブラウザにクライアント ID とクライアント シークレットは公開されません。

OAuth を使用するウェブ アプリケーションは、次の要件を満たす必要があります。

  • OAuth による認証は、Looker API 4.0 でのみ使用できます。
  • アプリケーションのクライアントを Looker に認証する前に、OAuth クライアント アプリケーションを API を使用して Looker に登録する必要があります。
  • クライアント アプリケーションは、Looker API へのすべてのリクエストに対して HTTPS を使用する必要があります。ブラウザで提供される SubtleCrypto API を使用するクライアント アプリケーションは、HTTPS でホストされている必要があります。

Looker API CORS のサポート

Looker API では、クロスオリジン リソース シェアリング(CORS)プロトコルを使用してブラウザ内および複数のオリジンで呼び出すことができます。Looker CORS のサポートには次の要件があります。

  • 埋め込みドメインの許可リストに記載されているオリジンのみが、CORS を使用して API を呼び出すことができます。
  • OAuth または /login API エンドポイントの呼び出しから取得したアクセス トークンのみを使用し、CORS を使用して Looker API を呼び出せます。

    /login API エンドポイントは、CORS リクエストを使用して呼び出すことはできません。CORS リクエストを使用して Looker API を呼び出すクライアント アプリケーションでは、OAuth を使用したユーザー ログインの実行で説明している OAuth ログイン プロセスを使用するか、アプリケーション サーバーや CORS 以外の API 呼び出しからトークンを取得する必要があります。

OAuth 認証の概要

OAuth 認証プロセスの概要は次のとおりです。

  1. Looker API に OAuth クライアント アプリケーションを登録します。
  2. コード交換 API 呼び出しとその後の CORS API 呼び出しのために、OAuth クライアント アプリケーションの送信元を埋め込みドメイン許可リストに追加します。
  3. OAuth クライアント アプリケーションがユーザーを認証しようとすると、ブラウザの URL を(Looker API ホスト名ではなく)Looker UI ホスト名の /auth エンドポイントにリダイレクトします。例: https://instance_name.looker.com
  4. ユーザーが正常に認証され、Looker にログインすると、Looker は OAuth クライアント アプリケーションへの OAuth リダイレクトを直ちに返します。ユーザーが現在のデバイスとブラウザで Looker にまだログインしていない場合、Looker のログイン画面が表示され、通常の認証プロトコルを使用して Looker ユーザー アカウントにログインするよう求められます。
  5. OAuth クライアント アプリケーションは、OAuth リダイレクトで返された認証コードを使用して、Looker API ホスト名(例: https://instance_name.looker.com:19999)で /token エンドポイントを呼び出します。API ホスト名は Looker UI ホスト名と同じ場合もあれば、異なる場合もあります。/token エンドポイントは Looker API ホストにのみ存在し、/auth エンドポイントは Looker UI ホストにのみ存在します。
  6. /token エンドポイントに渡された認証コードが有効な場合、Looker は OAuth クライアント アプリケーションのドメインからの CORS API リクエストに対して有効な API access_token を返します。

OAuth クライアント アプリケーションの登録

OAuth を使用して Looker API への認証を試みるすべての OAuth クライアント アプリケーションは、Looker がアクセスを承認する前に、まず Looker インスタンスに登録する必要があります。OAuth クライアント アプリケーションを登録するには:

  1. Looker インスタンスで API Explorer を開きます。
  2. バージョンのプルダウン メニューを使用して、4.0 - Stable バージョンの API を選択します。
  3. [Auth] メソッドで、register_oauth_client_app() API エンドポイントを見つけます。[Search] フィールドで「oauth app」を検索することもできます。register_oauth_client_app() を使用して OAuth クライアント アプリケーションを Looker に登録できます。[Run It] ボタンをクリックし、API Explorer にパラメータを入力して、再度 [Run It] をクリックして OAuth クライアント アプリケーションを登録するか、プログラムで register_oauth_client_app() API エンドポイントを使用します。必要な register_oauth_client_app() パラメータは次のとおりです。

    • client_guid: アプリケーションのグローバルに一意の ID
    • redirect_uri: 認証コードを含む OAuth リダイレクトをアプリケーションが受信する URI
    • display_name: アプリケーションのユーザーに表示されるアプリの名前
    • description: ユーザーが初めてアプリケーションにログインしたときに、開示ページと確認ページでユーザーに表示されるアプリケーションの説明

    client_guid パラメータと redirect_uri パラメータの値は、OAuth クライアント アプリケーションが指定すると完全に一致する必要があります。そうでない場合、認証は拒否されます。

OAuth を使用したユーザー ログインの実行

  1. ユーザーを UI ホストの /auth エンドポイントに移動します。例:

    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
    }
    

    上記のサンプルコードはブラウザが提供する SubtleCrypto API に依存していますが、ブラウザでは、保護された(HTTPS)ウェブページからのみこれらの機能を使用できます。

    Looker は、Looker インスタンスが構成されている認証システムを使用してユーザーの認証を試みます。

    • ユーザーが現在のブラウザで Looker にすでにログインしている場合(つまり、ライブ ログイン Cookie の状態がある場合)、ユーザーはログイン認証情報の入力を求められません。
    • ユーザーがこの OAuth クライアント アプリケーションを使用して初めてログインした場合は、Looker に開示と確認のページが表示され、ユーザーはこれに同意して承認できます。アプリの登録時に使用された description パラメータのテキストが表示されます。説明には、アプリケーションがユーザーの Looker アカウントで何をするのかを示す必要があります。ユーザーが [同意する] をクリックすると、アプリケーションはアプリケーション redirect_uri にリダイレクトされます。
    • ユーザーが現在のブラウザで Looker にログイン済みで、すでに開示ページの確認が済んでいる場合、OAuth ログインはすぐに行われ、視覚的な中断はありません。
  2. Looker API から OAuth クライアント アプリケーションへの OAuth リダイレクトが返されます。URI パラメータに表示されている認証コードを保存します。OAuth リダイレクト URI の例を次に示します。

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

    認証コードは URI の &code= の後に表示されます。上の例では、認証コードは asdfasdfassdf です。

  3. Looker API の /token エンドポイントにウェブ リクエストを送信し、認証コードとアプリケーション情報を渡します。例:

    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
    }
    

    成功すると、OAuth クライアント アプリケーションに API access_token が返されます。レスポンスには refresh_token も含まれます。これを使用して、後でユーザーの操作なしで新しい access_token を取得できます。refresh_token の有効期間は 1 か月です。refresh_token は安全に保管してください。

    このシステム内のすべてのトークンは、Looker 管理者によっていつでも取り消すことができます。