Skip to content

Commit b45e5ef

Browse files
Merge pull request #36532 from dlevy-msft-sql/dlevy-pyodbc-to-mssql-python
Convert Python samples from pyodbc to mssql-python
2 parents e836d32 + 6faad62 commit b45e5ef

12 files changed

Lines changed: 146 additions & 121 deletions

azure-sql/database/azure-sql-passwordless-migration-python.md

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ title: Migrate a Python Application to Use Passwordless Connections
33
description: Learn how to migrate a Python application to use passwordless connections with Azure SQL Database.
44
author: WilliamDAssafMSFT
55
ms.author: wiassaf
6-
ms.reviewer: rotabor, mathoma
7-
ms.date: 06/13/2025
6+
ms.reviewer: dlevy, rotabor, mathoma
7+
ms.date: 01/29/2026
88
ms.service: azure-sql-database
99
ms.subservice: security
1010
ms.topic: how-to
@@ -23,6 +23,8 @@ ms.custom:
2323

2424
Application requests to Azure SQL Database must be authenticated. Although there are multiple options for authenticating to Azure SQL Database, you should prioritize passwordless connections in your applications when possible. Traditional authentication methods that use passwords or secret keys create security risks and complications. Visit the [passwordless connections for Azure services](/azure/developer/intro/passwordless-overview) hub to learn more about the advantages of moving to passwordless connections. The following tutorial explains how to migrate an existing Python application to connect to Azure SQL Database to use passwordless connections instead of a username and password solution.
2525

26+
The [mssql-python](/sql/connect/python/mssql-python/python-sql-driver-mssql-python) driver provides built-in support for Microsoft Entra authentication, making passwordless connections straightforward with minimal code changes.
27+
2628
## Configure the Azure SQL Database
2729

2830
[!INCLUDE [configure-the-azure-sql-database](../includes/passwordless/configure-the-azure-sql-database.md)]
@@ -43,40 +45,39 @@ Create a user in Azure SQL Database. The user should correspond to the Azure acc
4345

4446
### Update the local connection configuration
4547

46-
Existing application code that connects to Azure SQL Database using the [Python SQL Driver - pyodbc](/sql/connect/python/pyodbc/python-sql-driver-pyodbc) continues to work with passwordless connections with minor changes. For example, the following code works with both SQL authentication and passwordless connections when running locally and when deployed to Azure App Service.
48+
Migrating to passwordless connections with [mssql-python](/sql/connect/python/mssql-python/python-sql-driver-mssql-python) requires only a connection string change. The driver has built-in support for Microsoft Entra authentication modes, eliminating the need for manual token handling.
4749

4850
```python
49-
import os
50-
import pyodbc, struct
51-
from azure.identity import DefaultAzureCredential
51+
from os import getenv
52+
from dotenv import load_dotenv
53+
from mssql_python import connect
54+
55+
load_dotenv()
5256

53-
connection_string = os.environ["AZURE_SQL_CONNECTIONSTRING"]
57+
connection_string = getenv("AZURE_SQL_CONNECTIONSTRING")
5458

5559
def get_all():
56-
with get_conn() as conn:
60+
with connect(connection_string) as conn:
5761
cursor = conn.cursor()
5862
cursor.execute("SELECT * FROM Persons")
5963
# Do something with the data
6064
return
61-
62-
def get_conn():
63-
credential = DefaultAzureCredential(exclude_interactive_browser_credential=False)
64-
token_bytes = credential.get_token("https://database.windows.net/.default").token.encode("UTF-16-LE")
65-
token_struct = struct.pack(f'<I{len(token_bytes)}s', len(token_bytes), token_bytes)
66-
SQL_COPT_SS_ACCESS_TOKEN = 1256 # This connection option is defined by microsoft in msodbcsql.h
67-
conn = pyodbc.connect(connection_string, attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct})
68-
return conn
6965
```
7066

71-
> [!TIP]
72-
> In this example code, the App Service environment variable `WEBSITE_HOSTNAME` is used to determine what environment the code is running in. For other deployment scenarios, you can use other environment variables to determine the environment.
67+
To update the referenced connection string (`AZURE_SQL_CONNECTIONSTRING`) for local development, create a `.env` file in your project folder with the passwordless connection string format using `ActiveDirectoryDefault` authentication:
7368

74-
To update the referenced connection string (`AZURE_SQL_CONNECTIONSTRING`) for local development, use the passwordless connection string format:
75-
76-
```
77-
Driver={ODBC Driver 18 for SQL Server};Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30
69+
```text
70+
AZURE_SQL_CONNECTIONSTRING=Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;Authentication=ActiveDirectoryDefault
7871
```
7972

73+
`ActiveDirectoryDefault` automatically discovers credentials from multiple sources (Azure CLI, environment variables, Visual Studio, etc.) without requiring interactive login. This approach is convenient for development but adds latency because it tries each credential source in sequence.
74+
75+
> [!IMPORTANT]
76+
> `ActiveDirectoryDefault` is intended for local development only. It tries multiple authentication methods in sequence, which adds latency and can cause unexpected behavior in production. For production applications, use the specific authentication method for your scenario:
77+
> - **Azure App Service/Functions**: Use `ActiveDirectoryMSI` (managed identity)
78+
> - **Interactive user login**: Use `ActiveDirectoryInteractive`
79+
> - **Service principal**: Use `ActiveDirectoryServicePrincipal`
80+
8081
### Test the app
8182

8283
Run your app locally and verify that the connections to Azure SQL Database are working as expected. Keep in mind that it can take several minutes for changes to Azure users and roles to propagate through your Azure environment. Your application is now configured to run locally without developers having to manage secrets in the application itself.
@@ -104,7 +105,8 @@ Complete the following steps in the Azure portal to associate the user-assigned
104105
- Azure Container Apps
105106
- Azure virtual machines
106107
- Azure Kubernetes Service
107-
- Navigate to the overview page of your web app.
108+
109+
1. Navigate to the overview page of your web app.
108110

109111
1. Select **Identity** from the left navigation.
110112

@@ -132,12 +134,12 @@ Complete the following steps in the Azure portal to associate the user-assigned
132134

133135
### Update the connection string
134136

135-
Update your Azure app configuration to use the passwordless connection string format. The format should be the same used in your local environment.
137+
Update your Azure app configuration to use the passwordless connection string format with `ActiveDirectoryMSI` authentication for managed identity.
136138

137139
Connection strings can be stored as environment variables in your app hosting environment. The following instructions focus on App Service, but other Azure hosting services provide similar configurations.
138140

139141
```connectionstring
140-
Driver={ODBC Driver 18 for SQL Server};Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30
142+
Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;Authentication=ActiveDirectoryMSI
141143
```
142144

143145
`<database-server-name>` is the name of your Azure SQL Database server and `<database-name>` is the name of your Azure SQL Database.
@@ -149,16 +151,21 @@ To use the user-assigned managed identity, create an `AZURE_CLIENT_ID` environme
149151
Save your changes and restart the application if it doesn't do so automatically.
150152

151153
> [!NOTE]
152-
> The example connection code shown in this migration guide uses the [DefaultAzureCredential](/python/api/azure-identity/azure.identity.defaultazurecredential) class when deployed. Specifically, it uses the DefaultAzureCredential without passing the user-assigned managed identity client ID to the constructor. In this scenario, the fallback is to check for the AZURE_CLIENT_ID environment variable. If the AZURE_CLIENT_ID environment variable doesn't exist, a system-assigned managed identity will be used if configured.
154+
> When using a user-assigned managed identity, include the client ID in the connection string using the `User Id` parameter:
155+
>
156+
> ```connectionstring
157+
> Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;Authentication=ActiveDirectoryMSI;User Id=<managed-identity-client-id>
158+
> ```
153159
>
154-
> If you pass the managed identity client ID in the DefaultAzureCredential constructor, the connection code can still be used locally and deployed because the authentication process falls back to interactive authentication in the local scenario. For more information, see the [Azure Identity client library for Python](/python/api/overview/azure/identity-readme#defaultazurecredential).
160+
> If you omit the `User Id` parameter, the driver uses the system-assigned managed identity if one is configured.
155161
156162
### Test the application
157163
158164
Test your app to make sure everything is still working. It can take a few minutes for all of the changes to propagate through your Azure environment.
159165
160166
## Related content
161167
168+
- [mssql-python driver documentation](/sql/connect/python/mssql-python/python-sql-driver-mssql-python)
162169
- [Passwordless overview](/azure/developer/intro/passwordless-overview)
163170
- [Managed identity best practices](/azure/active-directory/managed-identities-azure-resources/managed-identity-best-practice-recommendations)
164171
- [Tutorial: Secure a database in Azure SQL Database](/azure/azure-sql/database/secure-database-tutorial)

0 commit comments

Comments
 (0)