home User Guide Getting Started Help Center Documentation Community Training Certification
Looker keyboard_arrow_down
language keyboard_arrow_down
Looker API Authentication Using CORS

Looker uses the Cross Origin Resource Sharing (CORS) protocol to let web applications make calls to the Looker API from outside a Looker instance’s domain. When using CORS, Looker uses OAuth to let web applications authenticate into the Looker API without exposing client IDs and client secrets to the browser that is running the web application.

Web applications using CORS with the Looker API must meet the following requirements:

When using CORS authentication, the /login API endpoints cannot be called using CORS requests. Web applications wanting to call the Looker API via CORS requests must use the OAuth login process described below.

An overview of the CORS authentication process is as follows:

  1. Register the web application with the Looker API.
  2. When the web application attempts to authenticate a user, make a standard call to the /auth endpoint.
  3. If the user is successfully authenticated and logged in to Looker, Looker returns an OAuth redirect to the web application.
  4. Using the auth code in the OAuth redirect, make a call to the /token endpoint.
  5. Looker returns an API access_token that is enabled for CORS API requests from the web application’s domain.

Registering a Web Application

Every web application that attempts to authenticate into the Looker API using CORS must first be registered with Looker before Looker will authorize access. To register a web application:

  1. Open the API Explorer on your Looker instance. The default URL used to reach your Looker instance’s API Explorer is https://<instance_name>:<port>/api-docs/index.html. The default port for Looker instances hosted on GCP and instances hosted on AWS that were created on or after 07/07/2020 is 443. The default port for Looker instances hosted on AWS that were created before 07/07/2020 is 19999.
  2. At the top of the page, enter your API client ID and client secret and click Log In. If you do not have an API client ID and client secret, your Looker admin can generate them on the Users page in Looker’s Admin menu. See the Users documentation page for more information.
  3. Use the drop-down menu in the upper right of the page to choose the 4.0 - experimental version of the API and click Reload.
  4. Use the register_oauth_client_app() API endpoint to register your web application with Looker. You can enter the parameters in the API Explorer and click the Try it out! button to register the web application, or use the register_oauth_client_app() API endpoint programmatically. The required register_oauth_client_app() parameters are:

    • client_guid: The globally unique ID of the application
    • redirect_uri: The URI where the application will receive an OAuth redirect that includes an auth code
    • display_name: The name of the application that is displayed to users of the application
    • description: A description of the application that is displayed to users on a disclosure and confirmation page when a user first logs in from the application

    The values in the client_guid and redirect_uri parameters must match the values the web application will provide exactly, or authentication will be denied.

Configuring User Login Using CORS

  1. In the web application, to engage the OAuth login with a user of the web application, send a web request to the /auth endpoint in the Looker API. For example:

    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 API web service URL, plus the /auth endpoint.
      // 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

    Looker will attempt to authenticate the user using the authentication system for which the Looker instance is configured.

    • If the user is already logged in to Looker in the current browser (meaning there is a live login cookie state), the user won’t be prompted to enter their login credentials.
    • If this is the first time this user has logged in using this web application, Looker will show a disclosure and confirmation page for the user to acknowledge and accept. The text from the description parameter used when the application was registered will be displayed. The description should indicate what the application intends to do with the user’s Looker account. When the user clicks accept, the page will redirect to the application redirect_uri.
    • If the user is already logged in to Looker in the current browser and has already acknowledged the disclosure page, then the OAuth login is instantaneous with no visual interruption.
  2. The Looker API will return an OAuth redirect to the web application. Store the auth code listed in the URI parameter. The following is an example OAuth redirect URI:


    The auth code is shown after &code= in the URI. in the example above, the auth code is asdfasdfassdf.

  3. Make a web request to the /token endpoint in the Looker API, passing the auth code and your application information. For example:

    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 auth code in response')
      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')
      const response = await fetch('https://self-signed.looker.com:443/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)}`)
      // Stash the access_token and other info in sessionStorage,
      // which will survive page reloads (like a cookie) but is not
      // shared across browser tabs (unlike cookies)
      // Session storage is private to this domain name, AND private to
      // this browser tab, and will be deleted when this browser tab is
      // closed.
      // To clear this sessionStorage value in the web app demo,
      // close the browser tab. SessionStorage survives page reload.
      // Or call logout() below
      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

    A successful response will provide the web application with an API access_token that is enabled for CORS API requests from your web application domain. The response will also contain a refresh_token, which you can use later to get a new access_token without user interaction. A refresh_token has a one-month lifetime. Store the refresh_token securely.

    All tokens in this system can be revoked by the Looker admin at any time.