|
12 | 12 | from databricks.sql.auth.auth import ( |
13 | 13 | get_python_sql_connector_auth_provider, |
14 | 14 | PYSQL_OAUTH_CLIENT_ID, |
| 15 | + PYSQL_OAUTH_REDIRECT_PORT_RANGE, |
| 16 | + PYSQL_OAUTH_SCOPES, |
15 | 17 | ) |
16 | 18 | from databricks.sql.auth.oauth import OAuthManager, Token, ClientCredentialsTokenSource |
17 | 19 | from databricks.sql.auth.authenticators import ( |
@@ -251,6 +253,52 @@ def test_get_python_sql_connector_u2m_foreign_client_id_no_port( |
251 | 253 | self.assertEqual(provider._client_id, "test-custom-u2m-app") |
252 | 254 | self.assertEqual(provider.oauth_manager.port_range, [8030]) |
253 | 255 |
|
| 256 | + @patch.object(DatabricksOAuthProvider, "_initial_get_token") |
| 257 | + def test_get_python_sql_connector_u2m_default_client_id_ignores_redirect_port( |
| 258 | + self, mock__initial_get_token |
| 259 | + ): |
| 260 | + # AUTH-013 / PECOBLR-4039: a caller relying on the driver's DEFAULT |
| 261 | + # client_id must stay pinned to the driver's registered redirect port |
| 262 | + # range even if oauth_redirect_port is supplied - the driver's OAuth app |
| 263 | + # only registers 8020-8024, so honoring an arbitrary port would produce a |
| 264 | + # redirect_uri_mismatch. oauth_redirect_port only applies with a |
| 265 | + # caller-supplied oauth_client_id. |
| 266 | + hostname = "foo.cloud.databricks.com" |
| 267 | + kwargs = {"oauth_redirect_port": 9000} |
| 268 | + mock_http_client = MagicMock() |
| 269 | + auth_provider = get_python_sql_connector_auth_provider( |
| 270 | + hostname, mock_http_client, **kwargs |
| 271 | + ) |
| 272 | + |
| 273 | + provider = auth_provider.external_provider |
| 274 | + self.assertEqual(type(provider).__name__, "DatabricksOAuthProvider") |
| 275 | + self.assertEqual(provider._client_id, PYSQL_OAUTH_CLIENT_ID) |
| 276 | + self.assertEqual( |
| 277 | + provider.oauth_manager.port_range, PYSQL_OAUTH_REDIRECT_PORT_RANGE |
| 278 | + ) |
| 279 | + |
| 280 | + @patch.object(DatabricksOAuthProvider, "_initial_get_token") |
| 281 | + def test_get_python_sql_connector_u2m_default_client_id_ignores_scopes( |
| 282 | + self, mock__initial_get_token |
| 283 | + ): |
| 284 | + # AUTH-013 / PECOBLR-4039: a caller relying on the driver's DEFAULT |
| 285 | + # client_id must stay pinned to the driver's app-specific default scopes |
| 286 | + # even if oauth_scopes is supplied - the driver's OAuth app only has its |
| 287 | + # own default scopes registered, so honoring arbitrary scopes risks a |
| 288 | + # scope error. oauth_scopes only applies with a caller-supplied |
| 289 | + # oauth_client_id. |
| 290 | + hostname = "foo.cloud.databricks.com" |
| 291 | + kwargs = {"oauth_scopes": ["all-apis"]} |
| 292 | + mock_http_client = MagicMock() |
| 293 | + auth_provider = get_python_sql_connector_auth_provider( |
| 294 | + hostname, mock_http_client, **kwargs |
| 295 | + ) |
| 296 | + |
| 297 | + provider = auth_provider.external_provider |
| 298 | + self.assertEqual(type(provider).__name__, "DatabricksOAuthProvider") |
| 299 | + self.assertEqual(provider._client_id, PYSQL_OAUTH_CLIENT_ID) |
| 300 | + self.assertEqual(provider._scopes_as_str, " ".join(PYSQL_OAUTH_SCOPES)) |
| 301 | + |
254 | 302 |
|
255 | 303 | class TestClientCredentialsTokenSource: |
256 | 304 | @pytest.fixture |
|
0 commit comments