Compartilhar via


Conectar-se ao SQL do Azure com a autenticação do Microsoft Entra e o SqlClient

Aplicável a: .NET Framework .NET .NET Standard

Baixar ADO.NET

Este artigo descreve como se conectar a fontes de dados do SQL do Azure usando a autenticação do Microsoft Entra em um aplicativo .NET com o SqlClient.

Observação

Embora o Microsoft Entra ID seja o novo nome do Azure Active Directory (Azure AD), para evitar a interrupção de ambientes existentes, o Azure AD ainda permanecerá em alguns elementos codificados, como campos de interface do usuário, provedores de conexão, códigos de erro e cmdlets. Neste artigo, os dois nomes são intercambiáveis.

Visão geral

A autenticação do Microsoft Entra usa identidades no Microsoft Entra ID para acessar fontes de dados do SQL do Azure, como o Banco de Dados SQL do Azure, a Instância Gerenciada de SQL do Azure e o Azure Synapse Analytics. O namespace Microsoft.Data.SqlClient permite que aplicativos cliente especifiquem as credenciais do Microsoft Entra em diferentes modos de autenticação ao se conectarem ao Banco de Dados SQL do Azure e à Instância Gerenciada de SQL do Azure. Para usar a autenticação Microsoft Entra com SQL do Azure, é necessário configurar e gerenciar a autenticação Microsoft Entra com SQL do Azure.

Quando você define a propriedade de conexão Authentication na cadeia de conexão, o cliente pode escolher um modo de autenticação preferencial do Microsoft Entra de acordo com o valor fornecido:

  • A versão mais antiga do Microsoft.Data.SqlClient dá suporte a Active Directory Password para o .NET Framework, .NET Core e .NET Standard. Ela também dá suporte à autenticação Active Directory Integrated e Active Directory Interactive para o .NET Framework.

  • A partir do Microsoft.Data.SqlClient 2.0.0, o suporte à autenticação Active Directory Integrated e Active Directory Interactive foi estendido para o .NET Framework, .NET Core e .NET Standard.

    Um novo modo de autenticação Active Directory Service Principal também foi adicionado no SqlClient 2.0.0. Ele usa a ID do cliente e o segredo de uma identidade de entidade de serviço para realizar a autenticação.

  • Mais modos de autenticação foram adicionados no Microsoft.Data.SqlClient 2.1.0, incluindo Active Directory Device Code Flow e Active Directory Managed Identity (também conhecido como Active Directory MSI). Esses novos modos permitem que o aplicativo adquira um token de acesso para se conectar ao servidor.

Para obter informações sobre a autenticação do Microsoft Entra além do que as seções a seguir descrevem, consulte Usar a autenticação do Microsoft Entra.

Configuração da autenticação do Microsoft Entra

Quando o aplicativo está se conectando a fontes de dados do SQL do Azure usando a autenticação do Microsoft Entra, ele precisa fornecer um modo de autenticação válido. A tabela a seguir lista os modos de autenticação com suporte. O aplicativo especifica um modo usando a propriedade de conexão Authentication na cadeia de conexão.

Valor Descrição Versão do Microsoft.Data.SqlClient
Senha do Active Directory Autentique com o nome de usuário e a senha de uma identidade do Microsoft Entra 1.0+
Integrado ao Active Directory Autentique-se com uma identidade Microsoft Entra usando a Autenticação Integrada do Windows (IWA) 2.0.0+1
Interativa do Active Directory Autentique com a identidade do Microsoft Entra usando a autenticação interativa 2.0.0+1
Principal de Serviço do Active Directory Autenticar com uma entidade de serviço do Microsoft Entra usando sua ID do cliente e segredo 2.0.0+
Fluxo de código de dispositivo do Active Directory Autenticar com uma identidade do Microsoft Entra usando o modo de Fluxo de código do dispositivo 2.1.0+
Identidade gerenciada do Active Directory,
MSI do Active Directory
Autentique-se usando uma identidade gerenciada atribuída pelo sistema ou atribuída pelo usuário do Microsoft Entra. 2.1.0+
Active Directory Padrão Execute uma autenticação com uma identidade do Microsoft Entra usando mecanismos sem senha e não interativos, incluindo: Identidades Gerenciadas, o Visual Studio Code, o Visual Studio, a CLI do Azure etc. 3.0.0+
Identidade da carga de trabalho do Active Directory Autentique-se com uma identidade do Microsoft Entra usando uma Identidade Gerenciada Atribuída pelo Usuário federada para se conectar ao Banco de Dados SQL a partir de ambientes de cliente do Azure que são habilitados para a Identidade de Carga de Trabalho. 5.2.0+

1 Antes do Microsoft.Data.SqlClient 2.0.0, os modos de autenticação Active Directory Integrated e Active Directory Interactive eram compatíveis somente com o .NET Framework.

Usando autenticação de senha

O modo de autenticação Active Directory Password dá suporte à autenticação para fontes de dados do Azure com o Microsoft Entra ID para usuários nativos ou federados do Microsoft Entra. Quando você estiver usando esse modo, as credenciais do usuário deverão ser fornecidas na cadeia de conexão. O exemplo a seguir mostra como usar a autenticação Active Directory Password.

// Use your own server, database, user ID, and password.
string ConnectionString = @"Server=demo.database.windows.net;"
   + "Authentication=Active Directory Password; Encrypt=True; Database=testdb;"
   + "User Id=user@domain.com; Password=<password>";

using (SqlConnection conn = new SqlConnection(ConnectionString)) {
    conn.Open();
}

Como usar a autenticação integrada

Para usar o modo de autenticação Active Directory Integrated, você deve ter uma instância do Active Directory local que esteja conectada ao Microsoft Entra ID na nuvem. Você pode federar usando os AD FS (Serviços de Federação do Active Directory), por exemplo.

Com esse modo, quando você estiver conectado a um computador conectado ao domínio, poderá acessar as fontes de dados do SQL do Azure sem que as credenciais sejam solicitadas. Não é possível especificar o nome de usuário e a senha na cadeia de conexão para aplicativos .NET Framework. Nos aplicativos .NET Core e .NET Standard, o nome de usuário é opcional na cadeia de conexão. Não é possível definir a propriedade Credential de SqlConnection nesse modo.

O snippet de código a seguir é um exemplo de quando a autenticação Active Directory Integrated está em uso.

// Use your own server and database.
string ConnectionString1 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Integrated; Encrypt=True; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString1)) {
    conn.Open();
}

// User ID is optional for .NET Core and .NET Standard.
string ConnectionString2 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Integrated; Encrypt=True; Database=testdb;"
  + "User Id=user@domain.com";

using (SqlConnection conn = new SqlConnection(ConnectionString2)) {
    conn.Open();
}

Usando a autenticação interativa

A autenticação Active Directory Interactive dá suporte à tecnologia de autenticação multifator para se conectar a fontes de dados do SQL do Azure. Se você fornecer esse modo de autenticação na cadeia de conexão, uma tela de autenticação do Azure será exibida e solicitará que o usuário insira credenciais válidas. Não é possível especificar a senha na cadeia de conexão.

Não é possível definir a propriedade Credential de SqlConnection nesse modo. Com o Microsoft.Data.SqlClient 2.0.0 e posterior, é possível usar o nome de usuário na cadeia de conexão quando se está no modo interativo.

O exemplo a seguir mostra como usar a autenticação Active Directory Interactive.

// Use your own server, database, and user ID.
// User ID is optional.
string ConnectionString1 = @"Server=demo.database.windows.net;"
   + "Authentication=Active Directory Interactive; Encrypt=True;" 
   + "Database=testdb; User Id=user@domain.com";

using (SqlConnection conn = new SqlConnection(ConnectionString1)) {
    conn.Open();
}

// User ID is not provided.
string ConnectionString2 = @"Server=demo.database.windows.net;"
   + "Authentication=Active Directory Interactive; Encrypt=True;"
   + "Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString2)) {
    conn.Open();
}

Usar a autenticação de entidade de serviço

No modo de autenticação Active Directory Service Principal, o aplicativo cliente pode se conectar a fontes de dados do SQL do Azure fornecendo a ID do cliente e o segredo de uma identidade de entidade de serviço. A autenticação de entidade de serviço envolve:

  1. Configuração de um registro de aplicativo com um segredo.
  2. Concessão de permissões para o aplicativo na instância do Banco de Dados SQL do Azure.
  3. Conexão com a credencial correta.

O exemplo a seguir mostra como usar a autenticação Active Directory Service Principal.

// Use your own server, database, app ID, and secret.
string ConnectionString = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Service Principal; Encrypt=True;"
  + "Database=testdb; User Id=AppId; Password=<password>";

using (SqlConnection conn = new SqlConnection(ConnectionString)) {
    conn.Open();
}

Usando a autenticação de fluxo de código do dispositivo

Com a MSAL.NET (Biblioteca de Autenticação da Microsoft para .NET), a autenticação Active Directory Device Code Flow permite que o aplicativo cliente se conecte a fontes de dados do SQL do Azure em dispositivos e sistemas operacionais que não têm um navegador da Web interativo. A autenticação interativa será executada em outro dispositivo. Para saber mais sobre a autenticação de fluxo de código de dispositivo, confira Fluxo de código do dispositivo OAuth 2.0.

Quando esse modo estiver em uso, não será possível definir a propriedade Credential de SqlConnection. Além disso, o nome de usuário e a senha não devem ser especificados na cadeia de conexão.

O trecho de código a seguir é um exemplo de uso da autenticação Active Directory Device Code Flow.

Observação

O tempo limite para Active Directory Device Code Flow é padrão para a configuração de Connect Timeout da conexão. Especifique um Connect Timeout que forneça tempo suficiente para percorrer o processo de autenticação de fluxo de código do dispositivo.

// Use your own server and database and increase Connect Timeout as needed for
// device code flow.
string ConnectionString = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Device Code Flow; Encrypt=True;"
  + "Database=testdb; Connect Timeout=180;";

using (SqlConnection conn = new SqlConnection(ConnectionString)) {
    conn.Open();
}

Usar autenticação de identidade gerenciada

A autenticação com identidades gerenciadas para recursos do Azure é o método de autenticação recomendado para acesso programático ao SQL. Um aplicativo cliente pode usar a identidade gerenciada atribuída pelo sistema ou pelo usuário de um recurso para autenticar-se no SQL com o Microsoft Entra ID, fornecendo a identidade e usando-a para obter tokens de acesso. Esse método elimina a necessidade de gerenciar credenciais e segredos e pode simplificar o gerenciamento do acesso.

Há dois tipos de identidades gerenciadas:

  • A identidade gerenciada atribuída pelo sistema é criada como parte de um recurso do Azure (como sua instância gerenciada de SQL ou o servidor lógico) e compartilha o ciclo de vida desse recurso. As identidades atribuídas pelo sistema só podem ser associadas a um único recurso do Azure.
  • Uma identidade gerenciada atribuída pelo usuário é criada como um recurso autônomo do Azure. Ela pode ser atribuída a uma ou mais instâncias de um serviço do Azure.

Para saber mais sobre identidades gerenciadas, confira Sobre as identidades gerenciadas para recursos do Azure.

Desde o Microsoft.Data.SqlClient 2.1.0, o driver dá suporte à autenticação para o Banco de Dados SQL do Azure, o Azure Synapse Analytics e a Instância Gerenciada de SQL do Azure adquirindo tokens de acesso por meio de identidade gerenciada. Para usar essa autenticação, especifique Active Directory Managed Identity ou Active Directory MSI na cadeia de conexão; nenhuma senha será necessária. Também não é possível definir a propriedade Credential de SqlConnection nesse modo.

Para usar uma identidade gerenciada atribuída pelo usuário, será preciso obter a ID do cliente da identidade gerenciada ao usar o Microsoft.Data.SqlClient v3.0 ou posterior. Caso esteja usando o Microsoft.Data.SqlClient v2.1, será preciso obter a ID de objeto da identidade gerenciada.

O exemplo a seguir mostra como usar a autenticação Active Directory Managed Identity com uma identidade gerenciada atribuída pelo sistema.

// For system-assigned managed identity
// Use your own values for Server and Database.
string ConnectionString1 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Managed Identity; Encrypt=True;"
  + "Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString1)) {
    conn.Open();
}

string ConnectionString2 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory MSI; Encrypt=True; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString2)) {
    conn.Open();
}

O exemplo a seguir mostrará uma autenticação de Active Directory Managed Identity usando uma identidade gerenciada atribuída pelo usuário com o Microsoft.Data.SqlClient v3.0 ou posterior.

// For user-assigned managed identity
// Use your own values for Server, Database, and User Id.

// With Microsoft.Data.SqlClient v3.0+
string ConnectionString1 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Managed Identity; Encrypt=True;"
  + "User Id=ClientIdOfManagedIdentity; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString1)) {
    conn.Open();
}

// With Microsoft.Data.SqlClient v3.0+
string ConnectionString2 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory MSI; Encrypt=True;"
  + "User Id=ClientIdOfManagedIdentity; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString2)) {
    conn.Open();
}

O exemplo a seguir mostrará uma autenticação de Active Directory Managed Identity usando uma identidade gerenciada atribuída pelo usuário com o Microsoft.Data.SqlClient v2.1.

// For user-assigned managed identity
// Use your own values for Server, Database, and User Id.

// With Microsoft.Data.SqlClient v2.1
string ConnectionString1 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Managed Identity; Encrypt=True;"
  + "User Id=ObjectIdOfManagedIdentity; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString1)) {
    conn.Open();
}

// With Microsoft.Data.SqlClient v2.1
string ConnectionString2 = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory MSI; Encrypt=True;"
  + "User Id=ObjectIdOfManagedIdentity; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString2)) {
    conn.Open();
}

Usar autenticação padrão

Disponível a partir da versão 3.0, esse modo de autenticação amplia as possibilidades de autenticação do usuário. Este modo estende as soluções de logon para o ambiente do cliente, o Visual Studio Code, o Visual Studio, a CLI do Azure etc.

Com esse modo de autenticação, o driver obtém um token passando "DefaultAzureCredential" da biblioteca do Azure Identity para adquirir um token de acesso. Esse modo tenta usar um conjunto de tipos de credenciais para obter um token de acesso em sequência. O conjunto de credenciais varia de acordo com a versão da biblioteca Azure Identity usada. As diferenças específicas da versão são observadas na lista. Para conhecer o comportamento específico da versão do Azure Identity, confira a documentação da API do Azure.Identity.

Importante

O Padrão do Active Directory é uma opção conveniente para simplificar as diferenças de cadeia de conexão entre ambientes diferentes. No entanto, ele pode vir com impactos de desempenho porque precisa procurar em vários locais informações de autenticação. Se você vir velocidades de conexão lentas usando o Active Directory Default, use uma opção de autenticação diferente que direciona especificamente o método de autenticação que você está usando em seu ambiente. "Active Directory Default" não é recomendado para ambientes que têm tempos de resposta de nível de serviço rigorosos.

  • EnvironmentCredential
    • Habilita a autenticação com o Microsoft Entra ID usando o cliente e o segredo, ou nome de usuário e senha, detalhes configurados nas seguintes variáveis de ambiente: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, AZURE_USERNAME, AZURE_PASSWORD (Mais detalhes)
  • WorkloadIdentityCredential
    • Habilita a autenticação de identidade de carga de trabalho do Microsoft Entra no Kubernetes e em outros hosts com suporte à identidade de carga de trabalho. Para obter mais informações, consulte Identidades de Carga de Trabalho do Microsoft Entra. Disponível a partir da versão 1.10 do Azure Identity e Microsoft.Data.SqlClient 5.1.4.
  • ManagedIdentityCredential
    • Tenta executar uma autenticação no Microsoft Entra ID usando uma identidade gerenciada atribuída ao ambiente de implantação. "ID do cliente" de "Identidade Gerenciada Atribuída ao Usuário" é lida da propriedade de conexão "ID de Usuário".
  • SharedTokenCacheCredential
    • Executa uma autenticação usando tokens compartilhados entre aplicativos da Microsoft no cache local.
  • VisualStudioCredential
    • Habilita a autenticação com Microsoft Entra ID usando dados do Visual Studio
  • VisualStudioCodeCredential
    • Habilita a autenticação com o Microsoft Entra ID usando dados do Visual Studio Code.
  • AzurePowerShellCredential
    • Permite a autenticação no Microsoft Entra ID usando o Azure PowerShell. Disponível a partir da versão 1.6 do Azure Identity e Microsoft.Data.SqlClient 5.0.
  • AzureCliCredential
    • Habilita a autenticação com Microsoft Entra ID usando a CLI do Azure para obter um token de acesso.
  • AzureDeveloperCliCredential
    • Habilita a autenticação com o Microsoft Entra ID usando a Azure Developer CLI para obter um token de acesso. Disponível a partir da versão 1.10 do Azure Identity e Microsoft.Data.SqlClient 5.1.4.

Observação

InteractiveBrowserCredential está desabilitado na implementação do driver do Active Directory Default e o Active Directory Interactive é a única opção disponível para adquirir um token usando a autenticação interativa/MFA.

No momento, não há outras opções de personalização disponíveis.

O exemplo a seguir mostrará de que modo usar uma autenticação do Active Directory Padrão.

// Use your own server, database
string ConnectionString = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Default; Encrypt=True; Database=testdb;";

using (SqlConnection conn = new SqlConnection(ConnectionString)) {
    conn.Open();
}

Usando a autenticação de identidade de carga de trabalho

Disponível a partir da versão 5.2, como acontece com identidades gerenciadas, o modo de autenticação de identidade de carga de trabalho usa o valor do parâmetro User ID na cadeia de conexão para sua ID do cliente, se especificado. Mas, ao contrário da identidade gerenciada, WorkloadIdentityCredentialOptions padroniza seu valor a partir de variáveis de ambiente: AZURE_TENANT_ID, AZURE_CLIENT_ID e AZURE_FEDERATED_TOKEN_FILE. No entanto, somente a ID do cliente pode ser substituída pela cadeia de conexão.

O exemplo a seguir demonstra uma autenticação de Active Directory Workload Identity usando uma identidade gerenciada atribuída pelo usuário com o Microsoft.Data.SqlClient v5.2 ou posterior.

// Use your own values for Server, Database, and User Id.
// With Microsoft.Data.SqlClient v5.2+
string ConnectionString = @"Server=demo.database.windows.net;"
  + "Authentication=Active Directory Workload Identity; Encrypt=True;"
  + "User Id=ClientIdOfManagedIdentity; Database=testdb";

using (SqlConnection conn = new SqlConnection(ConnectionString)) {
    conn.Open();
}

Personalização da autenticação do Microsoft Entra

Além de usar a autenticação do Active Directory incorporada ao driver, o Microsoft.Data.SqlClient 2.1.0 e posterior fornece aos aplicativos a opção de personalizar a autenticação do Microsoft Entra. A personalização é baseada na classe ActiveDirectoryAuthenticationProvider, que é derivada da classe abstrata SqlAuthenticationProvider.

Durante a autenticação do Microsoft Entra, o aplicativo cliente pode definir sua própria classe ActiveDirectoryAuthenticationProvider ao:

  • Usar um método de retorno de chamada personalizado.
  • Passar uma ID do cliente de aplicativo para a biblioteca MSAL por meio do driver SqlClient a fim de buscar tokens de acesso.

O exemplo a seguir mostra como usar um retorno de chamada personalizado quando a autenticação Active Directory Device Code Flow está em uso.

using System;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Data.SqlClient;

namespace CustomAuthenticationProviderExamples
{
    public class Program
    {
        public static void Main()
        {
            SqlAuthenticationProvider authProvider = new ActiveDirectoryAuthenticationProvider(CustomDeviceFlowCallback);
            SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, authProvider);
            using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Device Code Flow;Database=<db>;"))
            {
                sqlConnection.Open();
                Console.WriteLine("Connected successfully!");
            }
        }

        private static Task CustomDeviceFlowCallback(DeviceCodeResult result)
        {
            // Provide custom logic to process result information and read device code.
            Console.WriteLine(result.Message);
            return Task.FromResult(0);
        }
    }
}

Com uma classe ActiveDirectoryAuthenticationProvider personalizada, uma ID do cliente de aplicativo definida pelo usuário pode ser passada para o SqlClient quando um modo de autenticação do Microsoft Entra com suporte está em uso. Os modos de autenticação do Microsoft Entra com suporte incluem Active Directory Password, Active Directory Integrated, Active Directory Interactive, Active Directory Service Principal e Active Directory Device Code Flow.

A ID do cliente de aplicativo também é configurável por meio de SqlAuthenticationProviderConfigurationSection ou SqlClientAuthenticationProviderConfigurationSection. A propriedade de configuração applicationClientId aplica-se ao .NET Framework 4.6+ e ao .NET Core 2.1+.

O snippet de código a seguir é um exemplo de uso de uma classe ActiveDirectoryAuthenticationProvider personalizada com uma ID do cliente de aplicativo definida pelo usuário quando a autenticação Active Directory Interactive está em uso.

using System;
using Microsoft.Data.SqlClient;

namespace CustomAuthenticationProviderExamples
{
    public class Program
    {
        public static void Main()
        {
            // Supported for all authentication modes supported by ActiveDirectoryAuthenticationProvider
            ActiveDirectoryAuthenticationProvider provider = new ActiveDirectoryAuthenticationProvider("<application_client_id>");
            if (provider.IsSupported(SqlAuthenticationMethod.ActiveDirectoryInteractive))
            {
                SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, provider);
            }
            
            using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Interactive;Database=<db>;"))
            {
                sqlConnection.Open();
                Console.WriteLine("Connected successfully!");
            }
        }
    }
}

O exemplo a seguir mostra como definir uma ID do cliente de aplicativo por meio de uma seção de configuração.

<configuration>
  <configSections>
    <section name="SqlClientAuthenticationProviders"
             type="Microsoft.Data.SqlClient.SqlClientAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
  </configSections>
  <SqlClientAuthenticationProviders applicationClientId ="<GUID>" />
</configuration>

<!--or-->

<configuration>
  <configSections>
    <section name="SqlAuthenticationProviders"
             type="Microsoft.Data.SqlClient.SqlAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
  </configSections>
  <SqlAuthenticationProviders applicationClientId ="<GUID>" />
</configuration>

Usando AccessTokenCallback

Disponível a partir da versão 5.2, há uma nova propriedade AccessTokenCallback em SqlConnection. Use a propriedade AccessTokenCallback para definir uma função personalizada que retorna um token de acesso de acordo com os parâmetros de entrada. Usar o retorno de chamada é melhor do que usar a propriedade AccessToken porque permite que o token de acesso seja atualizado em um pool de conexões. Ao usar a propriedade AccessToken, o token não pode ser atualizado após a abertura da conexão. Também não há data de expiração associada fornecida pela propriedade. Depois que o token expira, novas solicitações de conexão falham com um erro de autenticação do servidor e os pools que o usam devem ser limpos manualmente.

Importante

Um AccessTokenCallback deve retornar tokens de acesso do mesmo contexto de segurança para os mesmos parâmetros de entrada. Se o contexto de segurança for diferente, uma conexão em pool com o contexto de segurança errado poderá ser retornada para uma solicitação de conexão.

Observação

AccessTokenCallback faz parte da chave usada para identificar pools de conexões. Evite criar um retorno de chamada de função para cada criação de um SqlConnection, pois isso resulta em um novo pool todas as vezes. Faça referência à mesma instância de uma função para conexões que você deseja que sejam consideradas para o pool. A chave do pool de conexões inclui parâmetros passados para o retorno de chamada para pools de conexão de partição adequadamente.

O snippet de código a seguir é um exemplo de uso da propriedade AccessTokenCallback em Microsoft.Data.SqlClient v5.2 em diante.

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        OpenSqlConnection();
        Console.ReadLine();
    }

    const string defaultScopeSuffix = "/.default";

    // Reuse credential objects to take advantage of underlying token caches.
    private static ConcurrentDictionary<string, DefaultAzureCredential> credentials = new ConcurrentDictionary<string, DefaultAzureCredential>();

    // Use a shared callback function for connections that should be in the same connection pool.
    private static Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> myAccessTokenCallback =
        async (authParams, cancellationToken) =>
        {
            string scope = authParams.Resource.EndsWith(defaultScopeSuffix)
                ? authParams.Resource
                : $"{authParams.Resource}{defaultScopeSuffix}";

            DefaultAzureCredentialOptions options = new DefaultAzureCredentialOptions();
            options.ManagedIdentityClientId = authParams.UserId;

            // Reuse the same credential object if we are using the same MI Client Id.
            AccessToken token = await credentials.GetOrAdd(authParams.UserId, new DefaultAzureCredential(options)).GetTokenAsync(
                new TokenRequestContext(new string[] { scope }),
                cancellationToken);

            return new SqlAuthenticationToken(token.Token, token.ExpiresOn);
        };

    private static void OpenSqlConnection()
    {
        // (Optional) Pass a User-Assigned Managed Identity Client ID.
        // This will ensure different MI Client IDs are in different connection pools.
        string connectionString = "Server=myServer.database.windows.net;Encrypt=Mandatory;UserId=<ManagedIdentitityClientId>;";

        using (SqlConnection connection = new SqlConnection(connectionString)
        {
            // The callback function is part of the connection pool key. Using a static callback function
            // ensures connections will not create a new pool per connection just for the callback.
            AccessTokenCallback = myAccessTokenCallback
        })
        {
            connection.Open();
            Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
            Console.WriteLine("State: {0}", connection.State);
        }
    }
}

Suporte para um provedor de autenticação SQL personalizado

Com mais flexibilidade, o aplicativo cliente também pode usar seu próprio provedor de autenticação do Microsoft Entra em vez de usar a classe ActiveDirectoryAuthenticationProvider. O provedor de autenticação personalizado precisa ser uma subclasse de SqlAuthenticationProvider com métodos substituídos. Ele deve registrar o provedor personalizado, substituindo um ou mais dos métodos de autenticação Active Directory* existentes.

Importante

Um provedor de autenticação deve retornar tokens de acesso do mesmo contexto de segurança para os mesmos parâmetros de entrada. Se o contexto de segurança for diferente, uma conexão em pool com o contexto de segurança errado poderá ser retornada para uma solicitação de conexão.

O exemplo a seguir mostra como usar um novo provedor para a autenticação Active Directory Device Code Flow.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Microsoft.Identity.Client;

namespace CustomAuthenticationProviderExamples
{
    /// <summary>
    /// Example demonstrating creating a custom device code flow authentication provider and attaching it to the driver.
    /// This is helpful for applications that wish to override the Callback for the Device Code Result implemented by the SqlClient driver.
    /// </summary>
    public class CustomDeviceCodeFlowAzureAuthenticationProvider : SqlAuthenticationProvider
    {
        private const string ClientId = "my-client-id";
        private const string ClientName = "My Application Name";
        private const string DefaultScopeSuffix = "/.default";

        // Maintain a copy of the PublicClientApplication object to cache the underlying access tokens it provides
        private static IPublicClientApplication pcApplication;

        public override async Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters)
        {
            string[] scopes = [ parameters.Resource.EndsWith(DefaultScopeSuffix) ? parameters.Resource : parameters.Resource + DefaultScopeSuffix ];

            IPublicClientApplication app = pcApplication;
            if (app == null)
            {
                pcApplication = app = PublicClientApplicationBuilder.Create(ClientId)
                    .WithAuthority(parameters.Authority)
                    .WithClientName(ClientName)
                    .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                    .Build();
            }

            AuthenticationResult result;
            using CancellationTokenSource connectionTimeoutCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(parameters.ConnectionTimeout));

            try
            {
                IEnumerable<IAccount> accounts = await app.GetAccountsAsync();
                result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                    .ExecuteAsync(connectionTimeoutCancellation.Token);
            }
            catch (MsalUiRequiredException)
            {
                result = await app.AcquireTokenWithDeviceCode(scopes, deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult))
                    .ExecuteAsync(connectionTimeoutCancellation.Token);
            }

            return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn);
        }

        public override bool IsSupported(SqlAuthenticationMethod authenticationMethod)
            => authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow);

        private static Task CustomDeviceFlowCallback(DeviceCodeResult result)
        {
            Console.WriteLine(result.Message);
            return Task.CompletedTask;
        }
    }

    public class Program
    {
        public static void Main()
        {
            // Register our custom authentication provider class to override Active Directory Device Code Flow
            SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, new CustomDeviceCodeFlowAzureAuthenticationProvider());
            using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Device Code Flow;Database=<db>;"))
            {
                sqlConnection.Open();
                Console.WriteLine("Connected successfully!");
            }
        }
    }
}

Além de melhorar a experiência de autenticação Active Directory Interactive, o Microsoft.Data.SqlClient 2.1.0 e posterior fornece as seguintes APIs para aplicativos cliente a fim de personalizar a autenticação interativa e a autenticação de fluxo de código de dispositivo.

public class ActiveDirectoryAuthenticationProvider
{
    // For .NET Framework targeted applications only
    // Sets a reference to the current System.Windows.Forms.IWin32Window that triggers
    // the browser to be shown. 
    // Used to center the browser pop-up onto this window.
    public void SetIWin32WindowFunc(Func<IWin32Window> iWin32WindowFunc);

    // For .NET Standard targeted applications only
    // Sets a reference to the ViewController (if using .NET for iOS), Activity
    // (if using .NET for Android) IWin32Window, or IntPtr (if using .NET Framework). 
    // Used for invoking the browser for Active Directory Interactive authentication.
    public void SetParentActivityOrWindowFunc(Func<object> parentActivityOrWindowFunc);

    // For .NET Framework, .NET Core, and .NET Standard targeted applications
    // Sets a callback method that's invoked with a custom web UI instance that lets
    // the user sign in with Azure AD, present consent if needed, and get back the
    // authorization code. 
    // Applicable when working with Active Directory Interactive authentication.
    public void SetAcquireAuthorizationCodeAsyncCallback(Func<Uri, Uri, CancellationToken,
                                       Task<Uri>> acquireAuthorizationCodeAsyncCallback);

    // For .NET Framework, .NET Core, and .NET Standard targeted applications
    // Clears cached user tokens from the token provider.
    public static void ClearUserTokenCache();
}

Confira também