次の方法で共有


Microsoft Entra 認証と SqlClient を使用して Azure SQL に接続する

適用対象: .NET Framework .NET .NET Standard

ADO.NET のダウンロード

この記事では、.NET アプリケーションから SqlClient で Microsoft Entra 認証を使用して Azure SQL データ ソースに接続する方法について説明します。

Microsoft Entra ID はAzure Active Directory (Azure AD) の新しい名前ですが、既存の環境の中断を防ぐために、UI フィールド、接続プロバイダー、エラー コード、コマンドレットなど、ハードコーディングされた一部の要素でAzure AD が残ります。 この記事では、2 つの名前は交換可能です。

概要

Microsoft Entra 認証では、Microsoft Entra ID を使用して、Azure SQL データベース、Azure SQL Managed Instance、Azure Synapse Analytics などの Azure SQL データ ソースにアクセスします。 Microsoft.Data.SqlClient 名前空間を使用すると、クライアント アプリケーションで Azure SQL データベースおよび Azure SQL Managed Instance に接続しているときに、さまざまな認証モードで Microsoft Entra 認証情報を指定できます。 Azure SQL で Microsoft Entra 認証を使用するには、Azure SQL で Microsoft Entra 認証を構成して管理する必要があります。

接続文字列の Authentication 接続プロパティを設定すると、クライアントでは、指定された値に従って優先する Microsoft Entra 認証モードを選択できます。

  • 最初の Microsoft.Data.SqlClient バージョンでは、.NET Framework、.NET Core、および .NET Standard の Active Directory Password がサポートされています。 また、.NET Framework の Active Directory Integrated 認証と Active Directory Interactive 認証もサポートされています。

  • Microsoft.Data.SqlClient 2.0.0 から、Active Directory Integrated 認証と Active Directory Interactive 認証のサポートが .NET Framework、.NET Core、および .NET Standard にわたって拡張されました。

    SqlClient 2.0.0 には、新しい Active Directory Service Principal 認証モードも追加されています。 サービス プリンシパル ID のクライアント ID とシークレットを使用して認証を行います。

  • Microsoft.Data.SqlClient 2.1.0 には、他にも認証モードが追加されています (Active Directory Device Code FlowActive Directory Managed Identity (別名 Active Directory MSI) など)。 これらの新しいモードにより、アプリケーションでサーバーに接続するためのアクセス トークンを取得できます。

次のセクションで説明する以外の Microsoft Entra 認証の詳細については、「Microsoft Entra 認証を使用する」を参照してください。

Microsoft Entra 認証の設定

アプリケーションが Microsoft Entra 認証を使用して Azure SQL データ ソースに接続するときは、有効な認証モードを指定する必要があります。 次の表に、サポートされている認証モードの一覧を示します。 アプリケーションでは、接続文字列の Authentication 接続プロパティを使用してモードを指定します。

説明 Microsoft.Data.SqlClient のバージョン
Active Directory パスワード Microsoft Entra ID のユーザー名とパスワードによる認証 1.0 以降
Active Directory 統合 統合 Windows 認証 (IWA) を使用した Microsoft Entra ID での認証 2.0.0 以降1
Active Directory 対話型 対話型認証を使用した Microsoft Entra ID での認証 2.0.0 以降1
Active Directory サービス プリンシパル クライアント ID とシークレットを使用した Microsoft Entra サービス プリンシパルでの認証 2.0.0 以降
Active Directory デバイス コード フロー デバイス コード フロー モードを使用した Microsoft Entra ID での認証 2.1.0 以降
Active Directory Managed Identity、
Active Directory MSI
Microsoft Entra のシステム割り当てまたはユーザー割り当て マネージド ID を使用した認証 2.1.0 以降
Active Directory の既定値 マネージド ID、Visual Studio Code、Visual Studio、Azure CLI など、パスワードレスの非対話型のメカニズムを使用した Microsoft Entra ID での認証 3.0.0 以降
Active Directory のワークロード ID フェデレーション ユーザー割り当てマネージド ID を使用して Microsoft Entra ID で認証し、ワークロード ID に有効にしている Azure クライアント環境から SQL Database に接続します。 5.2.0+

1Microsoft.Data.SqlClient 2.0.0 より前は、Active Directory Integrated および Active Directory Interactive の認証モードは .NET Framework でのみサポートされます。

パスワード認証の使用

Active Directory Password 認証モードでは、ネイティブまたはフェデレーション Microsoft Entra ユーザーの Microsoft Entra ID を使用した Azure データ ソースへの認証がサポートされます。 このモードを使用する場合は、接続文字列にユーザー資格情報を指定する必要があります。 次の例は、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();
}

統合認証の使用

Active Directory Integrated 認証モードを使用するには、クラウドの Microsoft Entra ID に参加しているオンプレミスの Active Directory インスタンスが必要です。 たとえば、Active Directory フェデレーション サービス (AD FS) を使用してフェデレーションを行うことができます。

ドメイン参加済みのマシンにサインインしている場合は、このモードで資格情報の入力を求められることなく、Azure SQL データ ソースにアクセスできます。 .NET Framework アプリケーションの接続文字列にユーザー名とパスワードを指定することはできません。 .NET Core および .NET Standard アプリケーションの接続文字列では、ユーザー名は省略可能です。 このモードでは、SqlConnection の Credential プロパティを設定することはできません。

次のコード スニペットは、Active Directory Integrated 認証が使用されている場合の例です。

// 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();
}

対話型認証の使用

Active Directory Interactive 認証では、Azure SQL データ ソースに接続するための多要素認証テクノロジがサポートされています。 この認証モードを接続文字列で指定すると、Azure 認証画面が表示され、ユーザーは有効な資格情報を入力するように求められます。 接続文字列にパスワードを指定することはできません。

このモードでは、SqlConnection の Credential プロパティを設定することはできません。 Microsoft.Data.SqlClient 2.0.0 以降では、対話モードの場合に接続文字列でのユーザー名の使用が許可されます。

次の例は、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();
}

サービス プリンシパル認証の使用

Active Directory Service Principal 認証モードでは、クライアント アプリケーションは、サービス プリンシパル ID のクライアント ID とシークレットを指定することによって、Azure SQL データ ソースに接続できます。 サービス プリンシパル認証には次が伴います。

  1. シークレットを使用してアプリの登録を設定する。
  2. Azure SQL Database インスタンスのアプリにアクセス許可を付与する。
  3. 正しい資格情報で接続する。

次の例は、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();
}

デバイス コード フロー認証の使用

.NET 用 Microsoft Authentication Library (MSAL.NET) を使用すると、Active Directory Device Code Flow 認証により、クライアント アプリケーションで、対話型の Web ブラウザーがインストールされていないデバイスやオペレーティング システムから Azure SQL データ ソースに接続できます。 対話型認証は、別のデバイスで実行されます。 デバイス コード フロー認証の詳細については、OAuth 2.0 デバイス コード フローに関する記事を参照してください。

このモードを使用している場合、CredentialSqlConnection プロパティを設定することはできません。 また、接続文字列でユーザー名とパスワードを指定することはできません。

次のコード スニペットは、Active Directory Device Code Flow 認証を使用する場合の例です。

Active Directory Device Code Flow のタイムアウトの既定値は、接続の Connect Timeout 設定です。 デバイス コード フローの認証プロセスを余裕を持って実行できる Connect Timeout を指定してください。

// 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();
}

マネージド ID 認証の使用

SQL へのプログラムによるアクセスには、Azure リソース用マネージド ID による認証が推奨される認証方法です。 クライアント アプリケーションは、リソースのシステム割り当てマネージド ID またはユーザー割り当てマネージド ID を使用して、ID を指定し、それを使用してアクセス トークンを取得することで、Microsoft Entra ID を使用して SQL に対する認証を行うことができます。 このメソッドにより、認証情報とシークレットを管理する必要がなくなり、アクセス管理を簡略化できます。

マネージド ID には、次の 2 種類があります。

  • システム割り当てマネージド ID は、Azure リソース (SQL Managed Instance や 論理サーバーなど) の一部として作成され、そのリソースのライフサイクルを共有します。 システム割り当て ID は、1 つの Azure リソースにのみ関連付けることができます。
  • "ユーザー割り当てマネージド ID" は、スタンドアロンの Azure リソースとして作成されます。 Azure サービスの 1 つ以上のインスタンスに割り当てることができます。

マネージド ID の詳細については、Azure リソースのマネージド ID の概要に関する記事を参照してください。

Microsoft.Data.SqlClient 2.1.0 以降、ドライバーでは、マネージド ID を使用してアクセス トークンを取得することによる Azure SQL Database、Azure Synapse Analytics、および Azure SQL Managed Instance への認証がサポートされています。 この認証を使用するには、接続文字列で Active Directory Managed IdentityActive Directory MSI のいずれかを指定します。パスワードは必要ありません。 このモードで CredentialSqlConnection プロパティを設定することはできません。

ユーザー割り当てマネージド ID の場合、Microsoft.Data.SqlClient v3.0 以降を使用するときは、マネージド ID のクライアント ID を指定する必要があります。 Microsoft.Data.SqlClient v2.1 を使用している場合は、マネージド ID のオブジェクト ID を指定する必要があります。

次の例は、システム割り当てマネージド ID で Active Directory Managed Identity 認証を使用する方法を示しています。

// 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();
}

次の例では、ユーザー割り当てマネージド ID と Active Directory Managed Identityを使用する 認証を示します。

// 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();
}

次の例では、ユーザー割り当てマネージド ID と Active Directory Managed Identity を使用する 認証を示します。

// 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();
}

デフォルトの認証方法の使用

この認証モードはバージョン 3.0 以降で使用可能になり、これを使用すると、ユーザー認証の可能性が広がります。 このモードでは、ログイン ソリューションが、クライアント環境、Visual Studio Code、Visual Studio、Azure CLI などに拡張されます。

この認証モードを使用すると、ドライバーでは、Azure Identity ライブラリから "DefaultAzureCredential" を渡してアクセス トークンを取得することによってトークンを取得します。 このモードでは、認証情報タイプのセットを使用して、アクセス トークンの順に取得することが試みられます。 使用する Azure ID ライブラリのバージョンによって認証情報のセットは異なります。 バージョン固有の相違点はリストに記載されています。 Azure ID バージョン固有の動作については、Azure.Identity API のドキュメントを参照してください。

重要

Active Directory の既定値 は、異なる環境間の接続文字列の違いを簡略化するための便利なオプションです。 ただし、複数の場所で認証情報を検索する必要があるため、パフォーマンスに影響を与える可能性があります。 Active Directory Default を使用して接続速度が遅い場合は、環境で使用している認証方法を具体的に対象とする別の認証オプションを使用します。 サービス レベルの応答時間が厳しい環境では、"Active Directory の既定値" は推奨されません。

  • 環境認証情報
    • クライアントとシークレット、またはユーザー名とパスワード、環境変数 AZURE_TENANT_ID、AZURE_CLIENT_ID、AZURE_CLIENT_SECRET、AZURE_CLIENT_CERTIFICATE_PATH、AZURE_USERNAME、AZURE_PASSWORD で構成された詳細を使用して、Microsoft Entra ID への認証を有効にします (詳細)
  • WorkloadIdentityCredential
    • ワークロード ID をサポートする Kubernetes、およびその他のホストで、Microsoft Entra ワークロード ID 認証を有効にします。 詳細については、「Microsoft Entra ワークロード ID」を参照してください。 対応するバージョンは、Azure Identity バージョン 1.10 および Microsoft.Data.SqlClient 5.1.4 以降です。
  • ManagedIdentityCredential
    • デプロイ環境に割り当てられているマネージド ID を使用して、Microsoft Entra ID への認証を試みます。 "ユーザー割り当てマネージド ID" の "クライアント Id" は、 "User Id" 接続プロパティから読み取られます。
  • SharedTokenCacheCredential
    • Microsoft アプリケーション間で共有されるローカル キャッシュ内のトークンを使用して認証を行います。
  • VisualStudioの資格情報
    • Visual Studio からのデータを使用して Microsoft Entra ID による認証を有効化する
  • VisualStudioCodeCredential
    • Visual Studio Code からのデータを使用して Microsoft Entra ID による認証を有効化します。
  • AzurePowerShell資格情報
    • Azure PowerShell を使用した Microsoft Entra ID による認証を有効にします。 対応するバージョンは、Azure Identity バージョン 1.6 および Microsoft.Data.SqlClient 5.0 以降です。
  • AzureCliCredential (英語)
    • Azure CLI を使用して Microsoft Entra ID による認証を有効にして、アクセス トークンを取得します。
  • AzureDeveloperCliCredential
    • Azure Developer CLI を使用して Microsoft Entra ID での認証を有効にして、アクセス トークンを取得します。 対応するバージョンは、Azure Identity バージョン 1.10 および Microsoft.Data.SqlClient 5.1.4 以降です。

Active Directory Default のドライバー実装では InteractiveBrowserCredential が無効になり、MFA/対話型認証を使用してトークンを取得できる唯一のオプションは Active Directory Interactive です。

現在、その他のカスタマイズ オプションは使用できません。

次の例では、Active Directory Default 認証を使用する方法を示します。

// 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();
}

ワークロード ID 認証の使用

マネージド ID と同様に、バージョン 5.2 以降で利用できるワークロード ID 認証モードは、指定されている場合、クライアント ID に接続文字列の User ID パラメーターの値を使用します。 ただし、マネージド ID とは異なり、WorkloadIdentityCredentialOptions の既定値は環境変数 (AZURE_TENANT_ID、AZURE_CLIENT_ID、AZURE_FEDERATED_TOKEN_FILE) です。 ただし、接続文字列によってオーバーライドできるのはクライアント ID のみです。

次の例は、Active Directory Workload Identityでのユーザー割り当てマネージド ID による 認証を示しています。

// 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();
}

Microsoft Entra 認証のカスタマイズ

Microsoft.Data.SqlClient 2.1.0 以降では、ドライバーに組み込まれている Microsoft Entra 認証を使用するだけでなく、Microsoft Entra 認証をカスタマイズするためのオプションがアプリケーションに提供されます。 カスタマイズは、ActiveDirectoryAuthenticationProvider 抽象クラスから派生した SqlAuthenticationProvider クラスに基づきます。

Microsoft Entra 認証中、クライアント アプリケーションは次のいずれかの方法で独自の ActiveDirectoryAuthenticationProvider クラスを定義できます。

  • カスタマイズされたコールバック メソッドを使用する。
  • アクセス トークンをフェッチするために SqlClient ドライバーを使用してアプリケーション クライアント ID を MSAL ライブラリに渡す。

次の例は、Active Directory Device Code Flow 認証を使用している場合にカスタム コールバックを使用する方法を示しています。

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);
        }
    }
}

カスタマイズされた ActiveDirectoryAuthenticationProvider クラスでは、サポートされている Microsoft Entra 認証モードが使用されている場合に、ユーザー定義のアプリケーション クライアント ID を SqlClient に渡すことができます。 サポートされている Microsoft Entra 認証モードには Active Directory PasswordActive Directory IntegratedActive Directory InteractiveActive Directory Service PrincipalActive Directory Device Code Flow があります。

アプリケーション クライアント ID は、SqlAuthenticationProviderConfigurationSection または SqlClientAuthenticationProviderConfigurationSection を使用して構成することもできます。 構成プロパティ applicationClientId は、.NET Framework 4.6 以降と .NET Core 2.1 以降に適用されます。

次のコード スニペットは、ActiveDirectoryAuthenticationProvider 認証が使用されている場合に、カスタマイズされた Active Directory Interactive クラスをユーザー定義のアプリケーション クライアント ID と共に使用する例です。

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!");
            }
        }
    }
}

次の例は、configuration セクションを使用してアプリケーション クライアント ID を設定する方法を示しています。

<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>

AccessTokenCallback の使用

バージョン 5.2 以降で利用できて、SqlConnection に新しい AccessTokenCallback プロパティがあります。 AccessTokenCallback プロパティを使用し、受信パラメーターを指定してアクセス トークンを返すカスタム関数を定義します。 接続プール内でアクセス トークンを更新できるため、AccessToken プロパティを使用するよりも、コールバックを使用することをお勧めします。 AccessToken プロパティを使用するとき、接続を開いた後にトークンを更新することはできません。 プロパティを介して関連付けられた有効期限も指定されません。 トークンの有効期限が切れると、新しい接続要求はサーバー認証エラーで失敗し、使用するプールは手動でクリアする必要があります。

重要

AccessTokenCallbackは、同じ入力パラメーターに対して同じセキュリティ コンテキストのアクセス トークンを返す必要があります。 セキュリティー・コンテキストが異なる場合、接続要求に対して、誤ったセキュリティー・コンテキストを持つプールされた接続が返される可能性があります。

AccessTokenCallback は、接続プールを識別するために使用されるキーの一部です。 SqlConnection を作成するたびに新しい関数コールバックを作成すると、毎回新しいプールが作成されるため、作成しないでください。 同じ関数インスタンスを参照して、プーリングの対象とする接続を設定します。 接続プール・キーには、接続プールを適切にパーティション分割するためのコールバックに渡されるパラメータが含まれます。

次のコード スニペットは、AccessTokenCallback プロパティを使用する例です。

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);
        }
    }
}

カスタム SQL 認証プロバイダーのサポート

柔軟性の向上により、クライアント アプリケーションでは、ActiveDirectoryAuthenticationProvider クラスを使用する代わりに、Microsoft Entra 認証用に独自のプロバイダーを使用することもできます。 カスタム認証プロバイダーは、オーバーライドされたメソッドを含む SqlAuthenticationProvider のサブクラスである必要があります。 さらに、既存の 1 つ以上の Active Directory* 認証方法をオーバーライドして、カスタム プロバイダーを登録する必要があります。

重要

認証プロバイダーは、同じ入力パラメーターに対して同じセキュリティ コンテキストのアクセス トークンを返す必要があります。 セキュリティー・コンテキストが異なる場合、接続要求に対して、誤ったセキュリティー・コンテキストを持つプールされた接続が返される可能性があります。

次の例は、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!");
            }
        }
    }
}

Active Directory Interactive 認証エクスペリエンスの改善に加え、Microsoft.Data.SqlClient 2.1.0 以降では、クライアント アプリケーションで対話型認証とデバイス コード フロー認証をカスタマイズするための次の API が提供されます。

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();
}

関連項目