From 2738220062be43f3ba2d205b5199bf1ec8d15bd7 Mon Sep 17 00:00:00 2001 From: Jahnvi Thakkar Date: Fri, 11 Jul 2025 16:17:37 +0530 Subject: [PATCH 1/3] FEAT: Adding Default Auth --- mssql_python/helpers.py | 85 +++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/mssql_python/helpers.py b/mssql_python/helpers.py index db9700e72..5df1b108b 100644 --- a/mssql_python/helpers.py +++ b/mssql_python/helpers.py @@ -103,82 +103,91 @@ def add_driver_name_to_app_parameter(connection_string): # Initialize variables app_found = False modified_parameters = [] - has_aad_interactive = False - has_aad_device_code = False + # Track authentication types + auth_type = None # Iterate through the key-value pairs for param in parameters: param = param.strip() if not param: continue - - if param.lower().startswith("authentication="): - # Handle AAD Interactive authentication - key, auth_value = param.split("=", 1) - if auth_value.lower() == "activedirectoryinteractive": - has_aad_interactive = True - # Only keep the auth parameter on Windows + + key_value = param.split("=", 1) + if len(key_value) != 2: + continue + key, value = key_value + key_lower = key.lower() + value_lower = value.lower() + + if key_lower == "authentication": + if value_lower == "activedirectoryinteractive": + auth_type = "interactive" if platform.system().lower() != "windows": modified_parameters.append(param) continue - if auth_value.lower() == "activedirectorydevicecode": - has_aad_device_code = True - - if param.lower().startswith("app="): + elif value_lower == "activedirectorydevicecode": + auth_type = "devicecode" + continue + elif value_lower == "activedirectorydefault": + auth_type = "default" + continue + + if key_lower == "app": app_found = True - key, _ = param.split("=", 1) - modified_parameters.append(f"{key}=MSSQL-Python") + modified_parameters.append("APP=MSSQL-Python") else: modified_parameters.append(param) # If APP key is not found, append it if not app_found: modified_parameters.append("APP=MSSQL-Python") - - if has_aad_device_code: - # Remove Uid, Pwd, Connection Timeout, Encrypt, TrustServerCertificate + # Remove sensitive parameters for AAD auth + if auth_type in ("default", "devicecode", "interactive"): + exclude_keys = [ + "uid=", "pwd=", "connection timeout=", "encrypt=", "trustservercertificate=", "authentication=" + ] modified_parameters = [ param for param in modified_parameters - if not any(key in param.lower() for key in ["uid=", "pwd=", "connection timeout=", "encrypt=", "trustservercertificate=", "authentication="]) + if not any(param.lower().startswith(exclude) for exclude in exclude_keys) ] - modified_parameters.append("Connection Timeout=180") # Add default connection timeout - # Handle AAD Device Code auth + + # Handle each AAD authentication type + if auth_type == "default": try: - from azure.identity import DeviceCodeCredential + from azure.identity import DefaultAzureCredential import struct except ImportError: raise ImportError("Please install azure-identity: pip install azure-identity") + credential = DefaultAzureCredential() + token_bytes = credential.get_token("https://database.windows.net/.default").token.encode("UTF-16-LE") + token_struct = struct.pack(f" Date: Fri, 11 Jul 2025 16:43:25 +0530 Subject: [PATCH 2/3] Making changes in README.md file --- README.md | 8 ++++++-- mssql_python/helpers.py | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 62ffec1a3..e146d3814 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,16 @@ EntraID authentication is now fully supported on MacOS and Linux but with certai | Authentication Method | Windows Support | macOS/Linux Support | Notes | |----------------------|----------------|---------------------|-------| | ActiveDirectoryPassword | ✅ Yes | ✅ Yes | Username/password-based authentication | -| ActiveDirectoryInteractive | ✅ Yes | ❌ No | Only works on Windows | +| ActiveDirectoryInteractive | ✅ Yes | ✅ Yes | Interactive login via browser; requires user interaction | | ActiveDirectoryMSI (Managed Identity) | ✅ Yes | ✅ Yes | For Azure VMs/containers with managed identity | | ActiveDirectoryServicePrincipal | ✅ Yes | ✅ Yes | Use client ID and secret or certificate | | ActiveDirectoryIntegrated | ✅ Yes | ❌ No | Only works on Windows (requires Kerberos/SSPI) | +| ActiveDirectoryDeviceCode | ✅ Yes | ✅ Yes | Device code flow for authentication; suitable for environments without browser access | +| ActiveDirectoryDefault | ✅ Yes | ✅ Yes | Uses default authentication method based on environment and configuration | -> **NOTE**: For using Access Token, the connection string *must not* contain `UID`, `PWD`, `Authentication`, or `Trusted_Connection` keywords. + +> **NOTE**: For using Access Token, the connection string **must not** contain `UID`, `PWD`, `Authentication`, or `Trusted_Connection` keywords. +> **NOTE**: For using ActiveDirectoryDeviceCode, make sure to specify a `Connect Timeout` that provides enough time to go through the device code flow authentication process. ### Enhanced Pythonic Features diff --git a/mssql_python/helpers.py b/mssql_python/helpers.py index 5df1b108b..46546a454 100644 --- a/mssql_python/helpers.py +++ b/mssql_python/helpers.py @@ -145,7 +145,7 @@ def add_driver_name_to_app_parameter(connection_string): # Remove sensitive parameters for AAD auth if auth_type in ("default", "devicecode", "interactive"): exclude_keys = [ - "uid=", "pwd=", "connection timeout=", "encrypt=", "trustservercertificate=", "authentication=" + "uid=", "pwd=", "encrypt=", "trustservercertificate=", "authentication=" ] modified_parameters = [ param for param in modified_parameters @@ -165,7 +165,6 @@ def add_driver_name_to_app_parameter(connection_string): return ";".join(modified_parameters) + ";", {1256: token_struct} if auth_type == "devicecode": - modified_parameters.append("Connection Timeout=180") try: from azure.identity import DeviceCodeCredential import struct From 0828626a3ab9267ddd53b1c87e68cc7da234bdcf Mon Sep 17 00:00:00 2001 From: Jahnvi Thakkar Date: Fri, 11 Jul 2025 16:48:51 +0530 Subject: [PATCH 3/3] Making changes in README.md file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e146d3814..88c103a94 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ By adhering to the DB API 2.0 specification, the mssql-python module ensures com ### Support for Microsoft Entra ID Authentication -The Microsoft mssql-python driver enables Python applications to connect to Microsoft SQL Server, Azure SQL Database, or Azure SQL Managed Instance using Microsoft Entra ID identities. It supports various authentication methods, including username and password, Microsoft Entra managed identity, and Integrated Windows Authentication in a federated, domain-joined environment. Additionally, the driver supports Microsoft Entra interactive authentication and Microsoft Entra managed identity authentication for both system-assigned and user-assigned managed identities. +The Microsoft mssql-python driver enables Python applications to connect to Microsoft SQL Server, Azure SQL Database, or Azure SQL Managed Instance using Microsoft Entra ID identities. It supports a variety of authentication methods, including username and password, Microsoft Entra managed identity (system-assigned and user-assigned), Integrated Windows Authentication in a federated, domain-joined environment, interactive authentication via browser, device code flow for environments without browser access, and the default authentication method based on environment and configuration. This flexibility allows developers to choose the most suitable authentication approach for their deployment scenario. EntraID authentication is now fully supported on MacOS and Linux but with certain limitations as mentioned in the table: