Skip to content

Commit bfd3629

Browse files
ai: apply changes for #914 (2 review threads)
Addresses: - #3799622645 at src/databricks/sql/backend/kernel/auth_bridge.py:254 - #3799650240 at src/databricks/sql/backend/kernel/auth_bridge.py:300 Signed-off-by: peco-engineer-bot[bot] <peco-engineer-bot[bot]@users.noreply.github.com>
1 parent bc6702f commit bfd3629

2 files changed

Lines changed: 38 additions & 54 deletions

File tree

src/databricks/sql/backend/kernel/auth_bridge.py

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -251,44 +251,19 @@ def kernel_auth_kwargs(
251251
return kwargs
252252

253253
# 3. OAuth U2M — browser authorization-code flow; the kernel runs it.
254-
# Only databricks-oauth reaches here (azure-oauth was rejected up
255-
# front — see the guard near the top of this function).
256-
#
257-
# The kernel's core default U2M app is databricks-sql-connector /
258-
# sql offline_access / port 8030 (PECOBLR-4039). The Python
259-
# connector is an OVERRIDE of that default: on this path we forward
260-
# its OWN full bundle rather than letting the kernel fall back to
261-
# the connector default. Forwarding a bare oauth-u2m would
262-
# authenticate as databricks-sql-connector, breaking parity with
263-
# the Thrift path (which authenticates as databricks-sql-python).
264-
#
265-
# client_id + redirect_port are coupled per OAuth app — each app
266-
# registers its own redirect URI — so both are resolved together:
267-
# an explicit caller value wins; otherwise the connector's
268-
# registered databricks-sql-python bundle is used, mirroring the
269-
# defaults get_python_sql_connector_auth_provider applies on the
270-
# Thrift path. scopes are NOT caller-overridable: the Thrift path
271-
# hardcodes PYSQL_OAUTH_SCOPES for U2M (a caller's oauth_scopes
272-
# kwarg is never read there), so we forward the same fixed scopes
273-
# here to keep the two backends in parity.
274-
#
275-
# Only the redirect PORT is routable into the kernel: it derives
276-
# http://localhost:{port}, with scheme/host/path fixed. The
277-
# connector registers a port *range* for its app but the kernel
278-
# accepts a single port, so we forward the first (canonical)
279-
# registered port. A caller-supplied port only overrides that
280-
# default when an explicit client_id is ALSO supplied — matching
281-
# the Thrift path's coupling (a bare oauth_redirect_port paired
282-
# with the default databricks-sql-python app would resolve to an
283-
# unregistered redirect URI and fail the flow).
254+
# Only databricks-oauth reaches here (azure-oauth rejected up front).
255+
# Forward the connector's own databricks-sql-python bundle instead of
256+
# the kernel's databricks-sql-connector default, for parity with the
257+
# Thrift path. client_id + redirect_port are coupled per app (each
258+
# registers its own redirect URI): a caller port only overrides the
259+
# default when an explicit client_id is also supplied. A caller may
260+
# override oauth_scopes; absent one we forward PYSQL_OAUTH_SCOPES as
261+
# the default.
284262
if auth_type == "databricks-oauth":
285263
redirect_port = opts.get("oauth_redirect_port")
286-
# Validate any caller-supplied oauth_scopes (a bad type is still a
287-
# caller error worth flagging) but do NOT forward it: the Thrift
288-
# path hardcodes PYSQL_OAUTH_SCOPES for U2M, so we do the same for
289-
# parity rather than letting the kernel path honor an override the
290-
# other backend silently ignores.
291-
_normalize_scopes(opts.get("oauth_scopes"))
264+
# Honor a caller-supplied oauth_scopes (normalized to a list of
265+
# strings); fall back to the connector default when none is given.
266+
scopes = _normalize_scopes(opts.get("oauth_scopes"))
292267
kwargs = {
293268
"auth_type": "oauth-u2m",
294269
"client_id": client_id or PYSQL_OAUTH_CLIENT_ID,
@@ -297,7 +272,7 @@ def kernel_auth_kwargs(
297272
if client_id and redirect_port is not None
298273
else PYSQL_OAUTH_REDIRECT_PORT_RANGE[0]
299274
),
300-
"oauth_scopes": list(PYSQL_OAUTH_SCOPES),
275+
"oauth_scopes": scopes if scopes is not None else list(PYSQL_OAUTH_SCOPES),
301276
}
302277
if federation_client_id:
303278
kwargs["identity_federation_client_id"] = federation_client_id

tests/unit/test_kernel_auth_bridge.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ class TestKernelOAuthU2M:
252252
``sql offline_access`` / port 8030 (see PECOBLR-4039). The Python
253253
connector is an OVERRIDE: on the kernel path it forwards its OWN
254254
coupled ``client_id`` + ``redirect_port`` bundle so it authenticates
255-
as ``databricks-sql-python`` rather than the kernel default. Scopes
256-
are fixed to ``PYSQL_OAUTH_SCOPES`` (not caller-overridable), matching
257-
the Thrift path which hardcodes them for U2M.
255+
as ``databricks-sql-python`` rather than the kernel default. A caller
256+
may override ``oauth_scopes``; absent one, ``PYSQL_OAUTH_SCOPES`` is
257+
forwarded as the default.
258258
259259
``azure-oauth`` (Azure AD) is deliberately NOT handled yet — the
260260
kernel can't drive the Azure AD authorization/token flow — so it is
@@ -293,10 +293,9 @@ def test_azure_oauth_not_supported(self, opts):
293293
with pytest.raises(NotSupportedError, match="azure-oauth"):
294294
kernel_auth_kwargs(_FakeOAuthProvider(), opts)
295295

296-
def test_u2m_custom_client_id_and_port_honored_scopes_fixed(self):
297-
# A caller may override the coupled client_id + redirect_port. Scopes
298-
# are NOT caller-overridable (Thrift parity): a supplied oauth_scopes
299-
# is ignored and PYSQL_OAUTH_SCOPES is forwarded regardless.
296+
def test_u2m_custom_client_id_port_and_scopes_honored(self):
297+
# A caller may override the coupled client_id + redirect_port and
298+
# the oauth_scopes. All three are forwarded as supplied.
300299
kwargs = kernel_auth_kwargs(
301300
_FakeOAuthProvider(),
302301
{
@@ -310,14 +309,13 @@ def test_u2m_custom_client_id_and_port_honored_scopes_fixed(self):
310309
"auth_type": "oauth-u2m",
311310
"client_id": "custom-client",
312311
"redirect_port": 9999,
313-
"oauth_scopes": list(PYSQL_OAUTH_SCOPES),
312+
"oauth_scopes": ["custom-scope", "offline_access"],
314313
}
315314

316315
def test_u2m_custom_client_id_only_falls_back_to_connector_defaults(self):
317316
# A custom client_id without explicit scopes/port fills the
318-
# remaining two from the connector defaults — matching the Thrift
319-
# path, where a custom client_id still uses PYSQL_OAUTH_SCOPES and
320-
# the default redirect-port range.
317+
# remaining two from the connector defaults — a custom client_id
318+
# still uses PYSQL_OAUTH_SCOPES and the default redirect-port range.
321319
kwargs = kernel_auth_kwargs(
322320
_FakeOAuthProvider(),
323321
{
@@ -362,19 +360,30 @@ def test_u2m_redirect_port_ignored_without_client_id(self):
362360
)
363361
assert kwargs["redirect_port"] == PYSQL_OAUTH_REDIRECT_PORT_RANGE[0]
364362

365-
def test_u2m_ignores_custom_scopes(self):
366-
# Scopes are fixed for U2M — the Thrift path hardcodes
367-
# PYSQL_OAUTH_SCOPES and never reads a caller oauth_scopes kwarg, so
368-
# the kernel path forwards the same fixed scopes for parity. A
369-
# (well-typed) caller oauth_scopes is validated but not honored.
363+
def test_u2m_honors_custom_scopes(self):
364+
# A caller-supplied oauth_scopes is forwarded to the kernel, even
365+
# without an explicit client_id. Absent one, PYSQL_OAUTH_SCOPES is
366+
# forwarded as the default (see the bare-bundle test above).
370367
kwargs = kernel_auth_kwargs(
371368
_FakeOAuthProvider(),
372369
{
373370
"auth_type": "databricks-oauth",
374371
"oauth_scopes": ["all-apis", "offline_access"],
375372
},
376373
)
377-
assert kwargs["oauth_scopes"] == list(PYSQL_OAUTH_SCOPES)
374+
assert kwargs["oauth_scopes"] == ["all-apis", "offline_access"]
375+
376+
def test_u2m_normalizes_space_delimited_scopes(self):
377+
# A space-delimited oauth_scopes string is normalized to a list,
378+
# mirroring the M2M path.
379+
kwargs = kernel_auth_kwargs(
380+
_FakeOAuthProvider(),
381+
{
382+
"auth_type": "databricks-oauth",
383+
"oauth_scopes": "all-apis offline_access",
384+
},
385+
)
386+
assert kwargs["oauth_scopes"] == ["all-apis", "offline_access"]
378387

379388

380389
class TestKernelIdentityFederationClientId:

0 commit comments

Comments
 (0)