Tutorial: Create a passwordless connection to a database service via Service Connector

Passwordless connections use managed identities to access Azure services. With this approach, you don't have to manually track and manage secrets for managed identities. These tasks are securely handled internally by Azure.

Service Connector enables managed identities in app hosting services like Azure Spring Apps, Azure App Service, and Azure Container Apps. Service Connector also configures database services, such as Azure Database for PostgreSQL, Azure Database for MySQL, and Azure SQL Database, to accept managed identities.

In this tutorial, you use the Azure CLI to complete the following tasks:

  • Check your initial environment with the Azure CLI.
  • Create a passwordless connection with Service Connector.
  • Use the environment variables or configurations generated by Service Connector to access a database service.

Prerequisites

Set up your environment

Account

Sign in with the Azure CLI via az login. If you're using Azure Cloud Shell or are already logged in, confirm your authenticated account with az account show.

Install the Service Connector passwordless extension

Install the Service Connector passwordless extension for the Azure CLI:

az extension add --name serviceconnector-passwordless --upgrade

Create a passwordless connection

Next, we use Azure App Service as an example to create a connection using managed identity.

If you use:

Note

If you use the Azure portal, go to the Service Connector blade of Azure App Service, Azure Spring Apps, or Azure Container Apps, and select Create to create a connection. The Azure portal will automatically compose the command for you and trigger the command execution on Cloud Shell.

The following Azure CLI command uses a --client-type parameter. Run the az webapp connection create postgres-flexible -h to get the supported client types, and choose the one that matches your application.

az webapp connection create postgres-flexible \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_NAME \
    --target-resource-group $RESOURCE_GROUP \
    --server $POSTGRESQL_HOST \
    --database $DATABASE_NAME \
    --user-identity client-id=XX subs-id=XX \
    --client-type java

Azure Database for MySQL - Flexible Server requires a user-assigned managed identity to enable Microsoft Entra authentication. For more information, see Set up Microsoft Entra authentication for Azure Database for MySQL - Flexible Server. You can use the following command to create a user-assigned managed identity:

USER_IDENTITY_NAME=<YOUR_USER_ASSIGNED_MANAGEMED_IDENTITY_NAME>
IDENTITY_RESOURCE_ID=$(az identity create \
    --name $USER_IDENTITY_NAME \
    --resource-group $RESOURCE_GROUP \
    --query id \
    --output tsv)

Important

After creating the user-assigned managed identity, ask your Global Administrator or Privileged Role Administrator to grant the following permissions for this identity:

  • User.Read.All
  • GroupMember.Read.All
  • Application.Read.All

For more information, see the Permissions section of Active Directory authentication.

Then, connect your app to a MySQL database with a system-assigned managed identity using Service Connector.

The following Azure CLI command uses a --client-type parameter. Run the az webapp connection create mysql-flexible -h to get the supported client types, and choose the one that matches your application.

az webapp connection create mysql-flexible \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_NAME \
    --target-resource-group $RESOURCE_GROUP \
    --server $MYSQL_HOST \
    --database $DATABASE_NAME \
    --user-identity client-id=XX subs-id=XX mysql-identity-id=$IDENTITY_RESOURCE_ID \
    --client-type java

The following Azure CLI command uses a --client-type parameter. Run the az webapp connection create sql -h to get the supported client types, and choose the one that matches your application.

az webapp connection create sql \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_NAME \
    --target-resource-group $RESOURCE_GROUP \
    --server $SQL_HOST \
    --database $DATABASE_NAME \
    --user-identity client-id=XX subs-id=XX \
    --client-type dotnet

This Service Connector command completes the following tasks in the background:

  • Enable system-assigned managed identity, or assign a user identity for the app $APPSERVICE_NAME hosted by Azure App Service/Azure Spring Apps/Azure Container Apps.
  • Set the Microsoft Entra admin to the current signed-in user.
  • Add a database user for the system-assigned managed identity, user-assigned managed identity, or service principal. Grant all privileges of the database $DATABASE_NAME to this user. The username can be found in the connection string in preceding command output.
  • Set configurations named AZURE_MYSQL_CONNECTIONSTRING, AZURE_POSTGRESQL_CONNECTIONSTRING, or AZURE_SQL_CONNECTIONSTRING to the Azure resource based on the database type.
    • For App Service, the configurations are set in the App Settings blade.
    • For Spring Apps, the configurations are set when the application is launched.
    • For Container Apps, the configurations are set to the environment variables. You can get all configurations and their values in the Service Connector blade in the Azure portal.

Connect to a database with Microsoft Entra authentication

After creating the connection, you can use the connection string in your application to connect to the database with Microsoft Entra authentication. For example, you can use the following solutions to connect to the database with Microsoft Entra authentication.

For .NET, there's not a plugin or library to support passwordless connections. You can get an access token for the managed identity or service principal using client library like Azure.Identity. Then you can use the access token as the password to connect to the database. When using the code below, uncomment the part of the code snippet for the authentication type you want to use.

using Azure.Identity;
using Azure.Core;
using Npgsql;

// Uncomment the following lines according to the authentication type.
// For system-assigned identity.
// var sqlServerTokenProvider = new DefaultAzureCredential();

// For user-assigned identity.
// var sqlServerTokenProvider = new DefaultAzureCredential(
//     new DefaultAzureCredentialOptions
//     {
//         ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTID");
//     }
// );

// For service principal.
// var tenantId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_TENANTID");
// var clientId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTID");
// var clientSecret = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTSECRET");
// var sqlServerTokenProvider = new ClientSecretCredential(tenantId, clientId, clientSecret);

// Acquire the access token. 
AccessToken accessToken = await sqlServerTokenProvider.GetTokenAsync(
    new TokenRequestContext(scopes: new string[]
    {
        "https://ossrdbms-aad.database.windows.net/.default"
    }));

// Combine the token with the connection string from the environment variables provided by Service Connector.
string connectionString =
    $"{Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CONNECTIONSTRING")};Password={accessToken.Token}";

// Establish the connection.
using (var connection = new NpgsqlConnection(connectionString))
{
    Console.WriteLine("Opening connection using access token...");
    connection.Open();
}

Next, if you have created tables and sequences in PostgreSQL flexible server before using Service Connector, you need to connect as the owner and grant permission to <aad-username> created by Service Connector. The username from the connection string or configuration set by Service Connector should look like aad_<connection name>. If you use the Azure portal, select the expand button next to the Service Type column and get the value. If you use Azure CLI, check configurations in the CLI command output.

Then, execute the query to grant permission

az extension add --name rdbms-connect

az postgres flexible-server execute -n <postgres-name> -u <owner-username> -p "<owner-password>" -d <database-name> --querytext "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"<aad-username>\";GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"<aad username>\";"

The <owner-username> and <owner-password> is the owner of the existing table that can grant permissions to others. <aad-username> is the user created by Service Connector. Replace them with the actual value.

Validate the result with the command:

az postgres flexible-server execute -n <postgres-name> -u <owner-username> -p "<owner-password>" -d <database-name> --querytext "SELECT distinct(table_name) FROM information_schema.table_privileges WHERE grantee='<aad-username>' AND table_schema='public';" --output table

For .NET, there's not a plugin or library to support passwordless connections. You can get an access token for the managed identity or service principal using client library like Azure.Identity. Then you can use the access token as the password to connect to the database. When using the code below, uncomment the part of the code snippet for the authentication type you want to use.

using Azure.Core;
using Azure.Identity;
using MySqlConnector;

// Uncomment the following lines according to the authentication type.
// For system-assigned managed identity.
// var credential = new DefaultAzureCredential();

// For user-assigned managed identity.
// var credential = new DefaultAzureCredential(
//     new DefaultAzureCredentialOptions
//     {
//         ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTID");
//     });

// For service principal.
// var tenantId = Environment.GetEnvironmentVariable("AZURE_MYSQL_TENANTID");
// var clientId = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTID");
// var clientSecret = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTSECRET");
// var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);

var tokenRequestContext = new TokenRequestContext(
    new[] { "https://ossrdbms-aad.database.windows.net/.default" });
AccessToken accessToken = await credential.GetTokenAsync(tokenRequestContext);
// Open a connection to the MySQL server using the access token.
string connectionString =
    $"{Environment.GetEnvironmentVariable("AZURE_MYSQL_CONNECTIONSTRING")};Password={accessToken.Token}";

using var connection = new MySqlConnection(connectionString);
Console.WriteLine("Opening connection using access token...");
await connection.OpenAsync();

// do something

For more code samples, see Connect to Azure databases from App Service without secrets using a managed identity.

  1. Install dependencies.

    dotnet add package Microsoft.Data.SqlClient
    
  2. Get the Azure SQL Database connection string from the environment variable added by Service Connector.

    using Microsoft.Data.SqlClient;
    
    string connectionString = 
        Environment.GetEnvironmentVariable("AZURE_SQL_CONNECTIONSTRING")!;
    
    using var connection = new SqlConnection(connectionString);
    connection.Open();
    

    For more information, see Using Active Directory Managed Identity authentication.

For more information, see Homepage for client programming to Microsoft SQL Server.

Deploy the application to an Azure hosting service

Finally, deploy your application to an Azure hosting service. That source service can use a managed identity to connect to the target database on Azure.

For Azure App Service, you can deploy the application code via the az webapp deploy command. For more information, see Quickstart: Deploy an ASP.NET web app.

Then you can check the log or call the application to see if it can connect to the Azure database successfully.

Troubleshooting

Permission

If you encounter any permission-related errors, confirm the Azure CLI signed-in user with the command az account show. Make sure you log in with the correct account. Next, confirm that you have the following permissions that might be required to create a passwordless connection with Service Connector.

Permission Operation
Microsoft.DBforPostgreSQL/flexibleServers/read Required to get information of database server
Microsoft.DBforPostgreSQL/flexibleServers/write Required to enable Microsoft Entra authentication for database server
Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write Required to create firewall rule in case the local IP address is blocked
Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/delete Required to revert the firewall rule created by Service Connector to avoid security issue
Microsoft.DBforPostgreSQL/flexibleServers/administrators/read Required to check if Azure CLI login user is a database server Microsoft Entra administrator
Microsoft.DBforPostgreSQL/flexibleServers/administrators/write Required to add Azure CLI login user as database server Microsoft Entra administrator
Permission Operation
Microsoft.DBforMySQL/flexibleServers/read Required to get information of database server
Microsoft.DBforMySQL/flexibleServers/write Required to add the provided User assigned managed identity to database server
Microsoft.DBforMySQL/flexibleServers/firewallRules/write Required to create firewall rule in case the local IP address is blocked
Microsoft.DBforMySQL/flexibleServers/firewallRules/delete Required to revert the firewall rule created by Service Connector to avoid security issue
Microsoft.DBforMySQL/flexibleServers/administrators/read Required to check if Azure CLI login user is a database server Microsoft Entra administrator
Microsoft.DBforMySQL/flexibleServers/administrators/write Required to add Azure CLI login user as database server Microsoft Entra administrator
Permission Operation
Microsoft.Sql/servers/read Required to get information of database server
Microsoft.Sql/servers/firewallRules/write Required to create firewall rule in case the local IP address is blocked
Microsoft.Sql/servers/firewallRules/delete Required to revert the firewall rule created by Service Connector to avoid security issue
Microsoft.Sql/servers/administrators/read Required to check if Azure CLI login user is a database server Microsoft Entra administrator
Microsoft.Sql/servers/administrators/write Required to add Azure CLI login user as database server Microsoft Entra administrator

In some cases, the permissions aren't required. For example, if the Azure CLI-authenticated user is already an Active Directory Administrator on SQL server, you don't need to have the Microsoft.Sql/servers/administrators/write permission.

Microsoft Entra ID

If you get an error ERROR: AADSTS530003: Your device is required to be managed to access this resource., ask your IT department for help with joining this device to Microsoft Entra ID. For more information, see Microsoft Entra joined devices.

Service Connector needs to access Microsoft Entra ID to get information of your account and managed identity of hosting service. You can use the following command to check if your device can access Microsoft Entra ID:

az ad signed-in-user show

If you don't log in interactively, you might also get the error and Interactive authentication is needed. To resolve the error, log in with the az login command.

Network connectivity

If your database server is in Virtual Network, ensure your environment that runs the Azure CLI command can access the server in the Virtual Network.

If your database server is in Virtual Network, ensure your environment that runs the Azure CLI command can access the server in the Virtual Network.

If your database server disallows public access, ensure your environment that runs the Azure CLI command can access the server through the private endpoint.

Next steps

For more information about Service Connector and passwordless connections, see the following resources: