aminghadersohi commented on code in PR #44705:
URL: https://github.com/apache/superset/pull/44705#discussion_r4140766803


##########
superset/db_engine_specs/databricks.py:
##########
@@ -335,7 +352,21 @@ def needs_oauth2(cls, ex: Exception) -> bool:
         if isinstance(ex, cls.oauth2_exception):
             return True
         message = str(ex).lower()
-        return any(signal in message for signal in 
cls.oauth2_auth_failure_signals)
+        if any(signal in message for signal in 
cls.oauth2_auth_failure_signals):
+            return True
+        # A rejected bearer token fails the request with HTTP 401 and a message
+        # such as "Credential was not sent or was of an unsupported type for 
this
+        # API", which no signal above matches; the connector reports the status
+        # in ``RequestError.context["http-code"]``. 403 is left out on 
purpose: it
+        # also means a missing permission, which re-authorizing cannot fix.
+        error = getattr(ex, "orig", None) or ex
+        context = getattr(error, "context", None)
+        if isinstance(context, dict):
+            try:
+                return int(context.get("http-code") or 0) == 401

Review Comment:
   You're reading it right: for Databricks the user's OAuth2 token only reaches 
the connection through `impersonate_user`, so without impersonation a 401 comes 
from the shared credential and re-authorizing can't fix it.
   
   `needs_oauth2` only receives the exception, so I gated the step that sends 
the user to the prompt instead. In c5e4c5e, 
`DatabricksDynamicBaseEngineSpec.start_oauth2_dance` returns without 
redirecting when `database.impersonate_user` is off. Every caller 
(`_handle_oauth2_error`, `check_for_oauth2`, `execute`, test connection, the 
forced-refresh retry) then raises the original error, so the admin sees the 
actual failure. This applies to the older message signals (`unauthorized`, 
`http 401`, ...) as well as the new `http-code` check. 
`test_start_oauth2_dance_requires_impersonation` covers both specs.
   
   One remaining edge: `ValidateDatabaseParametersCommand` treats 
`needs_oauth2` as "valid, authorize later" without starting the dance. That 
check is engine-agnostic and predates this PR, so I left it alone here.
   



##########
superset/db_engine_specs/databricks.py:
##########
@@ -437,6 +468,13 @@ def update_params_from_encrypted_extra(
         consumed by ``Database.get_oauth2_config``; it is not a Databricks 
driver
         connection argument, so it must be stripped here to avoid poisoning the
         connection when OAuth2 is configured on the database itself.
+
+        ``connect_args`` are merged key by key, so credentials kept in the 
secure
+        extra (an access token, an OAuth M2M client secret) do not discard the
+        ``connect_args`` from ``extra`` or Superset's own (e.g. the 
User-Agent).
+        With user impersonation enabled, shared credentials are dropped: the
+        user's OAuth2 token set by ``impersonate_user`` is the only credential,
+        instead of being silently replaced by a shared one.
         """
         if not database.encrypted_extra:

Review Comment:
   Agreed. Done in c5e4c5e. `impersonate_user` now drops every key in 
`DATABRICKS_SHARED_CREDENTIAL_CONNECT_ARGS` from the `extra` connect_args. It 
then writes the user's token as `access_token` only when `extra` had one, which 
keeps the Python connector path. So the filter runs whenever impersonation is 
on, whether or not there is a secure extra. 
`update_params_from_encrypted_extra` now filters only the secure side, and the 
`key == "access_token"` special case is gone from there.
   
   New test 
`test_impersonate_user_drops_shared_credentials_without_secure_extra` covers 
impersonation on with no `encrypted_extra` and `auth_type`/`oauth_client_*` in 
`extra`. It fails on the previous head. 
`test_update_params_impersonation_keeps_only_the_user_token` now runs 
`impersonate_user` then `update_params_from_encrypted_extra`, in the same order 
as `_get_sqla_engine`.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to