Skip to content

Add preferred_username support for Trino impersonation - #7773

Open
ottergottaott wants to merge 1 commit into
getredash:masterfrom
ottergottaott:trino-preferred-username
Open

Add preferred_username support for Trino impersonation#7773
ottergottaott wants to merge 1 commit into
getredash:masterfrom
ottergottaott:trino-preferred-username

Conversation

@ottergottaott

@ottergottaott ottergottaott commented Jul 23, 2026

Copy link
Copy Markdown

What type of PR is this?

  • Feature

Description

Add support for using the JWT/OIDC preferred_username claim as the Trino impersonation user.

Redash already supports Trino impersonation using the Redash user's email or name. In SSO setups, those values are not always the identity expected by Trino access-control policies:

  • email can be otter@gotta.ott
  • name can be a display name like Otter Gottaott
  • for newly auto-created JWT users, Redash sets name to the email
  • preferred_username can be the actual login/short username, for example ottergottaott

This change stores preferred_username from a valid JWT payload in User.details and adds Preferred Username as a Trino impersonation attribute option. When selected, Trino receives user.details["preferred_username"], with fallback to the configured datasource username if the claim is missing.

Expected compatible Trino versions: no Trino server-version dependency. This only changes the user value passed to the existing Python Trino client connection.

How is this tested?

  • Unit tests (pytest, jest)
  • E2E Tests (Cypress)
  • Manually
  • N/A

Manual testing:
Verified locally with Keycloak + oauth2-proxy + Redash JWT auth that:
Keycloak emits preferred_username
Redash stores it in users.details
Trino datasource UI exposes Preferred Username in Impersonation User Attribute

Related Tickets & Documents

N/A

Mobile & Desktop Screenshots/Recordings (if there are UI changes)

N/A

Review in cubic

@ottergottaott
ottergottaott force-pushed the trino-preferred-username branch from 128ca57 to a1780f0 Compare July 23, 2026 15:23

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="redash/authentication/__init__.py">

<violation number="1" location="redash/authentication/__init__.py:200">
P2: Trino continues impersonating a stale `preferred_username` when a later JWT omits (or clears) the claim, rather than using the configured datasource username. Remove the stored key when the claim is absent/empty so the documented fallback applies to the current identity.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +200 to +209
preferred_username = payload.get("preferred_username")
if preferred_username:
user_details = user.details or {}

if user_details.get("preferred_username") != preferred_username:
user.details = {
**user_details,
"preferred_username": preferred_username,
}
models.db.session.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Trino continues impersonating a stale preferred_username when a later JWT omits (or clears) the claim, rather than using the configured datasource username. Remove the stored key when the claim is absent/empty so the documented fallback applies to the current identity.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At redash/authentication/__init__.py, line 200:

<comment>Trino continues impersonating a stale `preferred_username` when a later JWT omits (or clears) the claim, rather than using the configured datasource username. Remove the stored key when the claim is absent/empty so the documented fallback applies to the current identity.</comment>

<file context>
@@ -197,6 +197,17 @@ def jwt_token_load_user_from_request(request):
     except models.NoResultFound:
         user = create_and_login_user(current_org, payload["email"], payload["email"])
 
+    preferred_username = payload.get("preferred_username")
+    if preferred_username:
+        user_details = user.details or {}
</file context>
Suggested change
preferred_username = payload.get("preferred_username")
if preferred_username:
user_details = user.details or {}
if user_details.get("preferred_username") != preferred_username:
user.details = {
**user_details,
"preferred_username": preferred_username,
}
models.db.session.commit()
preferred_username = payload.get("preferred_username")
user_details = user.details or {}
updated_details = {**user_details}
if preferred_username:
updated_details["preferred_username"] = preferred_username
else:
updated_details.pop("preferred_username", None)
if updated_details != user_details:
user.details = updated_details
models.db.session.commit()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant