Looker Embed with BigQuery OAuth
This implementation guide explains how to embed Looker dashboards backed by Google BigQuery with OAuth into your custom application smoothly, eliminating the "double authentication" phase in the iframe. There is a reference example repository, looker_oauth, made by Sam Pitcher. The code samples here are in Python, but can be done in any server-side framework.

GCP & Looker Setup
GCP OAuth Credentials
- In the Google Cloud Console, create a single OAuth 2.0 Client ID.
- Update your Authorized redirect URIs to list BOTH:
- Your Looker instance native redirect URI (
https://example.cloud.looker.com/external_oauth/redirect). - Your host application's OAuth callback URL, for example,
https://app.example.com/auth/callback
- Your Looker instance native redirect URI (
Connect BigQuery to Looker
- In the Looker Admin panel, proceed to connections and establish a Google BigQuery connection.
- Select Authentication with OAuth and plug in your client credentials from GCP.
- Find the generated application ID by running all_external_oauth_applications via the Looker SDK or API. We recommend using the API Explorer if you have it installed; here is a relative link for use in your Looker UI:
/extensions/marketplace_extension_api_explorer::api-explorer/4.0/methods/Connection/all_external_oauth_applications
Application Level Login & Token Fetching
When users access your app, you must authorize them through Google OAuth 2.0. In your authorization redirect URL, configure exactly these dimensions:
Scopes & Access Type
Make sure your framework requests:
https://www.googleapis.com/auth/bigquery.readonly(Mandatory for BigQuery interaction).access_type='offline'andprompt='consent'(Mandatory to retrieve a refresh token, so sessions don't expire in 60 minutes).
Sample Callback Logic
Once Google redirects to your server with the temporary authorization code, invoke standard Google OAuth API calls to fetch tokens:
# Capture Code dimension
code = request.args.get("code")
# Prepare token request using your standard Web Application Client
token_response = requests.post(
"https://oauth2.googleapis.com/token",
data={
"code": code,
"client_id": GOOGLE_CLIENT_ID,
"client_secret": GOOGLE_CLIENT_SECRET,
"redirect_uri": REDIRECT_URI,
"grant_type": "authorization_code",
}
)
response_payload = token_response.json()
access_token = response_payload.get("access_token")
refresh_token = response_payload.get("refresh_token")
expires_in = int(response_payload.get("expires_in"))
Token Synchronization via Looker SDK
Immediately after capturing Google tokens (access/refresh), proactively insert them into Looker using an Admin Looker SDK instance:
Locate the Embed User Identity
In this article, we won't go into the details of Signed Embedding or Cookieless Embedding; we assume you already know what they are, and that a user on the Looker side has already been created. In either of these methods, Looker creates unique embed users tied to the external_user_id that you pass in the SSO URLs. Fetch the user's internal Looker identifier using user_for_credential:
looker_user = sdk.user_for_credential(
credential_type='embed',
user_id=current_user.your_user_id # The external_user_id you use in SSO
)
If this is the absolute first time that a user authenticates into Looker with this external_user_id and you're using signed embedding, then user_for_credential will error. You should catch this error, then create an SSO embed URL and fetch the URL to create the user.
Inject OAuth State into Looker
Construct the user state update parameters and pass them to create_oauth_application_user_state:
body = looker_sdk.models40.CreateOAuthApplicationUserStateRequest(
user_id=looker_user.id,
oauth_application_id=LOOKER_OAUTH_APPLICATION_ID,
access_token=access_token,
access_token_expires_at=datetime.datetime.now() + datetime.timedelta(seconds=expires_in),
refresh_token=refresh_token,
refresh_token_expires_at=datetime.datetime.now() + datetime.timedelta(days=180) # Common refresh expiry
)
sdk.create_oauth_application_user_state(body)
Creating the SSO URL
Once the user's access token matches successfully in Looker, issue a standard Signed Embed URL for them to use when loading the iframe. When creating the Signed Embed URL payload via create_sso_embed_url. If you are using cookieless_embedding, see this document on acquiring user attributes
Make sure to provide the same exact user identification (like their email) used above.
When to Trigger
We strongly recommend using the embed-sdk package to kick off this flow with getEmbedSDK().init() & getEmbedSDK().preload() and then display the iframe without any data, and then use getEmbedSDK.loadExplore() or getEmbedSDK.loadDashboard() to load the proper data into the iframe when you need it.
Troubleshooting Checklist
If users are still prompted for authentication within the iframe, verify the following:
- Missing Refresh Token: Ensure you requested
access_type='offline'andprompt='consent'in the Google OAuth redirect. Without this, Google won't return a refresh token, and Looker will be unable to refresh expired access tokens after 60 minutes automatically. - Scope Mismatch: Verify that the scopes requested on application login cover exactly the necessary BigQuery scopes (e.g.,
https://www.googleapis.com/auth/bigquery.readonly). - Mismatched External User ID: The
external_user_idused in the Signed SSO Embed URL must exactly match theuser_idused to pull the user identity inuser_for_credentialbefore state injection. - Looker User Provisioning: In Signed SSO Embedding, Looker only creates the user profile on the first successful load of an SSO URL. If you try to fetch the user state before they've ever visited,
user_for_credentialwill fail. In your server-side logic, ifuser_for_credentialfails, provision the user by either fetching the URL or properly capturing the error.