Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
00ff824
fix(oauth2): don't start the OAuth2 dance for embedded guests
hughhhh Oct 7, 2026
9f2d7ab
fix(snowflake): allow OAuth2 client config from the connection dialog
hughhhh Oct 7, 2026
b774851
feat(db): embedded-only fallback credential on OAuth2 connections
hughhhh Oct 7, 2026
33b369e
feat(db): support Snowflake embedded fallback key pairs
hughhhh Oct 14, 2026
e69700f
Merge pull request #5 from hughhhh/w-7/snowflake-embedded-fallback-pem
hughhhh Oct 14, 2026
55bd9b4
refactor(db): drive the embedded fallback credential from the engine …
hughhhh Oct 14, 2026
67a4403
Merge apache/master into hughhhh/embedded-oauth2-fallback
hughhhh Oct 14, 2026
0c3b16f
fix(db): address embedded OAuth2 fallback review concerns
hughhhh Oct 14, 2026
ba7904c
fix(db): resolve embedded fallback review findings
hughhhh Oct 15, 2026
f88330a
test(db): isolate embedded fallback eligibility checks
hughhhh Oct 15, 2026
5a0ac6c
fix(db): refuse embedded guests on a connection that lost its OAuth2 …
hughhhh Oct 15, 2026
74c1c47
fix(db): QA secret-handling fixes for the embedded credential fallback
hughhhh Oct 15, 2026
4a5cb34
feat(import): carry Secure Extra in bundles and ask for its secrets o…
hughhhh Oct 15, 2026
8277dee
fix(snowflake): run embedded guests with the fallback user's default …
hughhhh Oct 15, 2026
9a301fd
fix(embedded): refuse a guest with no applicable credential as a 400
hughhhh Oct 16, 2026
aea27b5
fix(snowflake): drop the connection's authenticator on the embedded l…
hughhhh Oct 17, 2026
d380d14
fix(embedded): readable errors and an admin log when a guest can't co…
hughhhh Oct 17, 2026
fdf237e
fix(embedded): clearer guest credential section and accurate setup docs
hughhhh Oct 17, 2026
3c9dfdd
docs(embedded): say what a guest on an OAuth2 connection actually sees
hughhhh Oct 17, 2026
aca5dab
fix(embedded): log a rejected fallback credential on the raw connecti…
hughhhh Oct 17, 2026
bdf7917
fix(embedded): no connection credentials on a guest login; bundles ca…
hughhhh Oct 19, 2026
dca0eb3
fix(embedded): refuse a half-filled embedded credential on import
hughhhh Oct 30, 2026
084c0a4
Merge remote-tracking branch 'origin/master' into hughhhh/embedded-oa…
hughhhh Oct 30, 2026
780cd01
chore(embedded): regenerate the OpenAPI spec and translation template
hughhhh Oct 30, 2026
248b23d
fix(embedded): type the Secure Extra action's object payload
hughhhh Oct 30, 2026
aa638a1
fix(embedded): bundles skip a Secure Extra block an engine masked whole
hughhhh Oct 30, 2026
37eb661
fix(embedded): overwrite imports ask for a secret stored as the mask
hughhhh Oct 30, 2026
e932e3d
fix(embedded): dashboard imports with overwrite_all ask for missing s…
hughhhh Oct 30, 2026
73a6c41
Merge remote-tracking branch 'origin/master' into hughhhh/embedded-oa…
hughhhh Oct 30, 2026
3a720fc
Merge remote-tracking branch 'pr/45068' into ws/import
hughhhh Oct 30, 2026
3608687
Merge remote-tracking branch 'origin/master' into ws/base
hughhhh Oct 31, 2026
e6a6807
Merge branch 'ws/base' into ws/import
hughhhh Oct 31, 2026
3af66e3
fix(embedded): refuse an incomplete imported credential with a 400
hughhhh Oct 31, 2026
794b088
Merge branch 'master' into oauth2/embedded-import-completeness
hughhhh Nov 2, 2026
37a2ad4
fix(embedded): address review of the import credential checks
hughhhh Nov 2, 2026
cccf052
fix(embedded): address review of the credential and import checks
hughhhh Nov 2, 2026
82bfec9
fix(embedded): address second review of import and credential handling
hughhhh Nov 2, 2026
104eeea
test(embedded): pin the partial bundle marker and correct the docs
hughhhh Nov 2, 2026
f02cc08
fix(embedded): address third review of bundles, filters and key inputs
hughhhh Nov 2, 2026
d8698aa
Merge remote-tracking branch 'origin/master' into HEAD
hughhhh Nov 2, 2026
8fdb1ca
test(embedded): stop the dashboard import test depending on test order
hughhhh Nov 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,35 @@ assists people when migrating to a new version.

## Next

- `EMBEDDED_CREDENTIAL_FALLBACK` (new, off by default) changes behaviour for embedded
guests on database connections that authenticate users individually via OAuth2 with
**Impersonate logged in user** enabled. Ordinary service-account connections retain
their existing behavior, even with a deployment-wide OAuth2 client configured. With
the flag on, a guest whose request has no applicable embedded credential — none
configured on the connection, or one missing its username, password, or private key
required by the selected authentication method — is refused
with a `CONNECTION_ACCESS_DENIED_ERROR` instead of connecting with the credential in
the connection's own SQLAlchemy URI. Queries that do run under an embedded credential
get a dedicated cache partition distinct from every logged-in username, including
a separate partition for guests without credentials, so they no longer share a
DATA-cache entry (or, under `GLOBAL_ASYNC_QUERIES`, a deduplicated chart task) with a logged-in user's
per-user result; existing cached entries for such charts are effectively invalidated
for guests. A malformed or incomplete `embedded_credentials` is rejected by
`POST`/`PUT /api/v1/database/`, by `validate_parameters`, and by database and asset
import (HTTP 400, naming the missing fields) rather than stored and ignored while
both embedding flags are enabled. Validation
uses the engine's credential rules and edited credentials rather than stale stored
values, and rejects whitespace-only usernames. Disabling either flag preserves stored credentials without blocking unrelated edits. Restored async guest
queries use the same credential as synchronous queries. Connection-mutator hooks
receive the selected fallback username. Snowflake OAuth2 scope is
configured explicitly; a role scope selects that role, and omitting it uses the
user's default role. Deployments that leave the fallback flag off are unaffected, except
that, whatever the flag, dashboard, chart and dataset exports now carry any masked
OAuth2 client and embedded credential blocks, and overwriting a connection from a
dashboard bundle merges them into its Secure Extra. A destination still on an earlier
release replaces its whole Secure Extra with those blocks instead, so upgrade import
destinations first.

- With a Redis Sentinel coordination backend (`DISTRIBUTED_COORDINATION_CONFIG`
using `RedisSentinelCache`), coordination commands now honor `CACHE_REDIS_DB` and
`CACHE_REDIS_USER`. Previously they always ran on DB 0 and without the ACL user.
Expand Down
108 changes: 108 additions & 0 deletions docs/docs/using-superset/embedding.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,113 @@ When enabled, the **Logout** menu item is removed from the user avatar dropdown

Must be `True` to enable the embedded SDK and the guest token endpoint. Without this flag, `embedDashboard` will fail to load.

### `EMBEDDED_CREDENTIAL_FALLBACK`

Allows a database connection that authenticates logged-in users per-user via OAuth2 to
also carry a single Snowflake username with either a password or a PEM key pair, used
**only** for embedded guest requests.

This exists because the two authentication models do not meet. An embedded viewer signs
in with a guest token rather than a Superset account, so there is no per-user OAuth2
token to resolve for them — and an external viewer may have no identity on the
analytical database at all. Without a fallback, embedded dashboards on a per-user OAuth2
connection cannot run queries.

```python
# superset_config.py
FEATURE_FLAGS = {
"EMBEDDED_SUPERSET": True,
"EMBEDDED_CREDENTIAL_FALLBACK": True,
}
```

With both flags on, engines that support it (currently Snowflake) show an **Embedded
guest credentials** section on the **Basic** tab of the connection dialog. The section
is editable only when the connection has an OAuth2 client and **Impersonate logged in
user** is on; otherwise it is disabled and states what is missing.

#### Setting up the credential

1. Enable `EMBEDDED_SUPERSET` and `EMBEDDED_CREDENTIAL_FALLBACK` (above).
2. Open the Snowflake connection for editing. On the **Basic** tab, expand **OAuth2
client information** and enter the client ID, client secret, authorization and token
request URIs, and scope. Alternatively, configure a deployment-wide client for
Snowflake in `DATABASE_OAUTH2_CLIENTS`.
3. On the **Advanced** tab, under **Security**, turn on **Impersonate logged in user**.
On a new connection this option appears only after you connect, so connect first and
then edit the connection.
4. Back on the **Basic** tab, expand **Embedded guest credentials**, enter the Snowflake
username, choose **Password** or **Key pair**, and fill in the secret.
5. Save. The section header shows **Configured** once a credential is stored.

Configure the Snowflake OAuth2 scopes explicitly to match your integration. For
example, `session:role:ANALYST refresh_token` selects the `ANALYST` role and requests a
refresh token. Omitting a role scope uses the user's default role; the dialog does not
prefill a scope or require a specific role scope.

For key-pair authentication, enter the Snowflake username, its PEM private key, and an
optional passphrase; register the corresponding public key with that Snowflake user. The
credential is stored encrypted in the connection's *Secure Extra* under
`embedded_credentials`. Passwords, private keys, and passphrases are masked on read,
while the username stays visible so an administrator can see which database user
embedded queries run as.

The credential must be complete: a username with no password or private key, or the
reverse, is rejected when both embedding flags are enabled. A whitespace-only username
is invalid. Validation uses the engine's credential rules and rejects malformed JSON
or non-object credential values. It checks the edited credential, so an incomplete
imported credential can be completed or cleared.

To remove the credential, expand **Embedded guest credentials**, click **Remove embedded
guest credentials** (or clear every field), and save. This deletes the
`embedded_credentials` key from *Secure Extra*. Removal stays available while the section
is otherwise disabled.

#### Requirements and limitations

- Both `EMBEDDED_SUPERSET` and `EMBEDDED_CREDENTIAL_FALLBACK` must be enabled. While
either is off, a stored credential is preserved, unused, and does not block unrelated
edits.
- The connection needs an OAuth2 client — per-connection **OAuth2 client information**
or a deployment-wide `DATABASE_OAUTH2_CLIENTS` entry — and **Impersonate logged in
user** must be on. Superset refuses to save a credential otherwise, and it never
applies to a connection without OAuth2.
- Embedded viewers run with the embedded account's **default Snowflake role**. The
connection's configured role and authenticator are not used for guest connections.
- The embedded account needs `USAGE` on the connection's warehouse.
- Supported secrets are a password, a Snowflake programmatic access token entered as the
password, or a key pair (PEM private key with an optional passphrase).
- Alerts, reports, connection tests, and logged-in users never use the credential; they
keep using the connection's own credential or their per-user OAuth2 token.
- With `GLOBAL_ASYNC_QUERIES` enabled, guest queries use the same fallback as
synchronous guest queries, but logged-in users' async queries are not covered by it.

Understand what this grants before enabling it:

- **Every embedded viewer of that connection queries as that one database user.** Guest
tokens carry no database identity, so per-user attribution and any database-side
row-level security keyed to the user do not apply. Use a dedicated account with the
narrowest access the embedded dashboards need, and enforce per-viewer restrictions
with Superset's own [row-level security](#security-notes) rules in the guest token.
- **Logged-in users are unaffected.** They continue to authenticate individually via
OAuth2 and have no route to the stored credential.
- **The guest token's `username` claim is never used to connect.** Whoever mints the
token controls that claim, so it is deliberately kept out of the connection identity.
Connection-mutator hooks receive the selected fallback connection username.
- **An embedded viewer never silently falls back to the connection's base credential.**
With this flag on, a guest on a per-user OAuth2 connection with impersonation enabled
that has no applicable credential —
none configured, or one that is incomplete — is refused with an error rather than
connected as whichever account the connection URL carries. Deployments that leave the
flag off keep their existing behaviour.
- **Guest results are cached separately.** Queries run under the fallback credential get
their own cache partition, distinct from every logged-in username, so an embedded
viewer and a logged-in user never share a cached result (or, with
`GLOBAL_ASYNC_QUERIES`, a deduplicated query task) for the same chart. Missing or incomplete credentials also receive a separate cache key, so a
warm logged-in cache cannot bypass the missing-credential refusal.
- Turning the flag back off is a kill switch, not a deletion: the stored credential stops
being offered and stops being used, but is preserved.

---

## URL Parameters
Expand Down Expand Up @@ -214,6 +321,7 @@ One caveat when the host page lives on a different site than Superset: the defau
- **Row-level security** — pass `rls` rules in the guest token request to restrict which rows are visible to the embedded user. Semantic views cannot enforce guest-token SQL clauses, so queries and cached-result reads are rejected when a global rule or a rule scoped to the semantic view applies. For hosts, a global guest rule deliberately refuses every semantic view, and a dataset-scoped rule can also refuse a semantic view even when the rule was intended for a SQL dataset. Read permissions do not override these restrictions. Semantic views remain accessible when no guest rule applies; SQL datasets continue to enforce their applicable rules.
- **Allowed domains** — restrict which host origins can embed a dashboard by setting **Allowed Domains** per-dashboard in the _Embed_ settings modal. Superset checks the request's `Referer` header against this list before serving the embedded view; an empty list allows any origin, so configure this explicitly for production.
- **Redacted errors** — API responses to a guest token report a generic `An error occurred while fetching the data.` instead of the underlying error, since engine errors quote catalog, schema, table and column names. Errors Superset raises itself — access denials, timeouts, payload validation — keep their message, and the full error is always available in the server logs.
- **OAuth2 connections and guests** — a guest cannot complete an OAuth2 authorization, so Superset does not start one for them, and an embedded viewer on an OAuth2 connection with no applicable credential is never sent into a login flow they cannot finish. With `EMBEDDED_CREDENTIAL_FALLBACK` off, the connection attempt fails with the database driver's authentication error. With it on, Superset refuses the query before connecting. Either way the viewer sees the generic `An error occurred while fetching the data.` message, and the reason is in the server logs. To serve embedded dashboards from such a connection, see [`EMBEDDED_CREDENTIAL_FALLBACK`](#embedded_credential_fallback).


## Guest-token request-header size diagnostics
Expand Down
Loading
Loading