如何使用 AAD 进行身份验证以便访问 Azure 数据资源管理器How-To Authenticate with AAD for Azure Data Explorer Access

访问 Azure 数据资源管理器的推荐方法是通过 Azure Active Directory 服务(有时也称为 Azure AD ,或简称为 AAD )进行身份验证。The recommended way to access Azure Data Explorer is by authenticating to the Azure Active Directory service (sometimes also called Azure AD , or simply AAD ). 这样做可以通过一个两阶段过程来确保 Azure 数据资源管理器永远不会看到访问主体的目录凭据:Doing so guarantees that Azure Data Explorer never sees the accessing principal's directory credentials, by using a two-stage process:

  1. 在第一步中,客户端与 AAD 服务通信,向其证明身份,并请求一个针对客户端打算访问的特定 Azure 数据资源管理器终结点颁发的访问令牌。In the first step, the client communicates with the AAD service, authenticates to it, and requests an access token issued specifically for the particular Azure Data Explorer endpoint the client intends to access.
  2. 在第二步中,客户端向 Azure 数据资源管理器发出请求,并向 Azure 数据资源管理器提供在第一步中获取的访问令牌作为身份证明。In the second step the client issues requests to Azure Data Explorer, providing the access token acquired in the first step as a proof of identity to Azure Data Explorer.

然后,Azure 数据资源管理器代表由 AAD 向其颁发访问令牌的安全主体执行请求,并使用此标识执行所有授权检查。Azure Data Explorer then executes the request on behalf of the security principal for which AAD issued the access token, and all authorization checks are performed using this identity.

大多数情况下,建议使用 Azure 数据资源管理器 SDK 之一以编程方式访问该服务,因为它们避免了实现上述流(以及许多其他流)时的很多麻烦。In most cases, the recommendation is to use one of Azure Data Explorer SDKs to access the service programmatically, as they remove much of the hassle of implementing the flow above (and much else). 有关示例,请参阅 .NET SDKSee, for example, the .NET SDK. 然后,通过 Kusto 连接字符串设置身份验证属性。The authentication properties are then set by the Kusto connection string. 如果无法做到这一点,请继续阅读,详细了解如何自行实现此流程。If that is not possible, please read on for detailed information on how to implement this flow yourself.

主要身份验证方案包括:The main authenticating scenarios are:

  • 对登录用户进行身份验证的客户端应用程序A client application authenticating a signed-in user . 在此方案中,一个交互式(客户端)应用程序将触发 AAD 提示来提示用户输入凭据(例如用户名和密码)。In this scenario, an interactive (client) application triggers an AAD prompt to the user for credentials (such as username and password). 请参阅用户身份验证See user authentication,

  • “无外设”应用程序A "headless" application . 在此方案中,应用程序在运行时无需用户提供凭据,而是使用用户已为其配置的某些凭据,向 AAD 证明自己的身份。In this scenario an application is running with no user present to provide credentials, and instead the application authenticates as "itself" to AAD using some credentials it has been configured with. 请参阅应用程序身份验证See application authentication.

  • 代理身份验证On-behalf-of authentication . 在此方案中(有时称为“Web 服务”或“Web 应用”方案),应用程序从另一个应用程序获取 AAD 访问令牌,然后将其“转换”为可与 Azure 数据资源管理器配合使用的另一个 AAD 访问令牌。In this scenario, sometimes called the "web service" or "web app" scenario, the application gets an AAD access token from another application, and then "converts" it to an another AAD access token that can be used with Azure Data Explorer. 换句话说,该应用程序充当提供了凭据的用户或应用程序与 Azure 数据资源管理器服务之间的中介。In other words, the application acts as a mediator between the user or application that provided credentials and the Azure Data Explorer service. 请参阅代理身份验证See on-behalf-of authentication.

指定用于 Azure 数据资源管理器的 AAD 资源Specifying the AAD resource for Azure Data Explorer

从 AAD 获取访问令牌时,客户端必须告诉 AAD 应当将令牌颁发给哪个 AAD 资源When acquiring an access token from AAD, the client must tell AAD which AAD resource the token should be issued to. Azure 数据资源管理器终结点的 AAD 资源是终结点的 URI,其中不包括端口信息和路径。The AAD resource of a Azure Data Explorer endpoint is the URI of the endpoint, barring the port information and the path. 例如:For example:

https://help.kusto.chinacloudapi.cn

指定 AAD 租户 IDSpecifying the AAD tenant ID

AAD 是一项多租户服务,每个组织都可以在 AAD 中创建一个称为 目录 的对象。AAD is a multi-tenant service, and every organization can create an object called directory in AAD. 目录对象保存与安全性相关的对象,例如用户帐户、应用程序和组。The directory object holds security-related objects such as user accounts, applications, and groups. AAD 通常将目录称为 租户AAD often refers to the directory as a tenant . AAD 租户通过 GUID( 租户 ID )进行标识。AAD tenants are identifies by a GUID ( tenant ID ). 在许多情况下,AAD 租户还可以通过组织的域名进行标识。In many cases, AAD tenants can also be identified by the domain name of the organization.

例如,名为“Contoso”的组织可能具有租户 ID 4da81d62-e0a8-4899-adad-4349ca6bfe24 和域名 contoso.comFor example, an organization called "Contoso" might have the tenant ID 4da81d62-e0a8-4899-adad-4349ca6bfe24 and the domain name contoso.com.

指定 AAD 颁发机构Specifying the AAD authority

AAD 有许多用于身份验证的终结点:AAD has a number of endpoints for authentication:

  • 当承载着要进行身份验证的主体的租户已知时(换言之,当知道用户或应用程序在哪个 AAD 目录中时),AAD 终结点是 https://login.partner.microsoftonline.cn/{tenantId}When the tenant hosting the principal being authenticated is known (in other words, when one knows which AAD directory the user or application are in), the AAD endpoint is https://login.partner.microsoftonline.cn/{tenantId}. 在这里,{tenantId} 是组织在 AAD 中的租户 ID,或者是组织的域名(例如 contoso.com)。Here, {tenantId} is either the organization's tenant ID in AAD, or its domain name (e.g. contoso.com).

  • 当承载着要进行身份验证的主体的租户未知时,可以通过将上面的 {tenantId} 替换为值 common 来使用“common”终结点。When the tenant hosting the principal being authenticated is not known, the "common" endpoint can be used by replacing the {tenantId} above with the value common.

备注

用于身份验证的 AAD 终结点也称为 AAD 颁发机构 URL 或简称为 AAD 颁发机构The AAD endpoint used for authentication is also called AAD authority URL or simply AAD authority .

AAD 令牌缓存AAD token cache

使用 Azure 数据资源管理器 SDK 时,AAD 令牌存储在本地计算机上每个用户的令牌缓存(一个名为 %APPDATA%\Kusto\tokenCache.data 的文件,该文件只能由已登录用户访问或解密)中。系统在提示用户输入凭据之前,会检查缓存中是否有令牌,从而大大减少用户必须输入凭据的次数。When using the Azure Data Explorer SDK, the AAD tokens are stored on the local machine in a per-user token cache (a file called %APPDATA%\Kusto\tokenCache.data which can only be accessed or decrypted by the signed-in user.) The cache is inspected for tokens before prompting the user for credentials, thus greatly reducing the number of times a user has to enter credentials.

备注

AAD 令牌缓存可减少用户在访问 Azure 数据资源管理器时显示交互式提示的次数,但不会减少它们的填写。The AAD token cache reduces the number of interactive prompts that a user would be presented with accessing Azure Data Explorer, but does not reduce them complete. 此外,用户无法提前预测系统何时会提示其输入凭据。Additionally, users cannot anticipate in advance when they will be prompted for credentials. 这意味着,如果需要支持非交互式登录(例如,在计划任务时),则不能尝试使用用户帐户来访问 Azure 数据资源管理器,因为当提示登录用户输入凭据时,如果在非交互式登录下运行,则提示会失败。This means that one must not attempt to use a user account to access Azure Data Explorer if there's a need to support non-interactive logons (such as when scheduling tasks for example), because when the time comes for prompting the logged on user for credentials that prompt will fail if running under non-interactive logon.

用户身份验证User authentication

使用用户身份验证访问 Azure 数据资源管理器的最简单方法是使用 Azure 数据资源管理器 SDK,并将 Azure 数据资源管理器连接字符串的 Federated Authentication 属性设置为 trueThe easiest way to access Azure Data Explorer with user authentication is to use the Azure Data Explorer SDK and set the Federated Authentication property of the Azure Data Explorer connection string to true. 第一次使用 SDK 向服务发送请求时,系统会向用户显示一个用于输入 AAD 凭据的登录窗体,身份验证成功后请求就会发送。The first time the SDK is used to send a request to the service the user will be presented with a sign-in form to enter the AAD credentials, and on successful authentication the request will be sent.

不使用 Azure 数据资源管理器 SDK 的应用程序仍然可以使用 AAD 客户端库 (ADAL),而不实现 AAD 服务安全协议客户端。Applications that do not use the Azure Data Explorer SDK can still use the AAD client library (ADAL) instead of implementing the AAD service security protocol client. 有关从 .NET 应用程序执行此操作的示例,请参阅 [https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet ]。Please see [https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet] for an example of doing so from a .NET application.

若要针对 Azure 数据资源管理器访问对用户进行身份验证,必须先向应用程序授予 Access Kusto 委托权限。To authenticate users for Azure Data Explorer access, an application must first be granted the Access Kusto delegated permission. 以获取详细信息。for details.

下面的简短代码片段演示了如何使用 ADAL 获取 AAD 用户令牌来访问 Azure 数据资源管理器(启动登录 UI):The following brief code snippet demonstrates using ADAL to acquire an AAD user token to access Azure Data Explorer (launches logon UI):

// Create an HTTP request
WebRequest request = WebRequest.Create(new Uri("https://{serviceNameAndRegion}.kusto.chinacloudapi.cn"));

// Create Auth Context for AAD (common or tenant-specific endpoint):
AuthenticationContext authContext = new AuthenticationContext("AAD Authority URL");

// Acquire user token for the interactive user for Kusto:
AuthenticationResult result = authContext.AcquireTokenAsync("https://{serviceNameAndRegion}.kusto.chinacloudapi.cn", "your client app id",
    new Uri("your client app resource id"), new PlatformParameters(PromptBehavior.Auto)).GetAwaiter().GetResult();

// Extract Bearer access token and set the Authorization header on your request:
string bearerToken = result.AccessToken;
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

应用程序身份验证Application authentication

下面的简短代码片段演示了如何使用 ADAL 获取 AAD 应用程序令牌来访问 Azure 数据资源管理器。The following brief code snippet demonstrates using ADAL to acquire an AAD application token to access Azure Data Explorer. 此流中没有提示,应用程序必须向 AAD 注册并配备有执行应用程序身份验证所需的凭据(例如 AAD 颁发的应用密钥或已预先向 AAD 注册的 X509v2 证书)。In this flow no prompt is presented, and the application must be registered with AAD and equipped with credentials needed to perform application authentication (such as an app key issued by AAD, or an X509v2 certificate that has been pre-registered with AAD).

// Create an HTTP request
WebRequest request = WebRequest.Create(new Uri("https://{serviceNameAndRegion}.kusto.chinacloudapi.cn"));

// Create Auth Context for AAD (common or tenant-specific endpoint):
AuthenticationContext authContext = new AuthenticationContext("AAD Authority URL");

// Acquire application token for Kusto:
ClientCredential applicationCredentials = new ClientCredential("your application client ID", "your application key");
AuthenticationResult result =
        authContext.AcquireTokenAsync("https://{serviceNameAndRegion}.kusto.chinacloudapi.cn", applicationCredentials).GetAwaiter().GetResult();

// Extract Bearer access token and set the Authorization header on your request:
string bearerToken = result.AccessToken;
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

代理身份验证On-behalf-of authentication

在此方案中,向应用程序发送了由该应用程序管理的任意资源的 AAD 访问令牌,该应用程序使用该令牌为 Azure 数据资源管理器资源获取新的 AAD 访问令牌,以便应用程序可以代表原始 AAD 访问令牌指示的主体访问 Kusto。In this scenario an application was sent an AAD access token for some arbitrary resource managed by the application, and it uses that token to acquire a new AAD access token for the Azure Data Explorer resource so that the application could access Kusto on behalf of the principal indicated by the original AAD access token.

此流称为 OAuth2 令牌交换流This flow is called the OAuth2 token exchange flow. 它通常需要执行与 AAD 相关的多个配置步骤,并且在某些情况下(取决于 AAD 租户配置)可能需要 AAD 租户管理员的特别许可。It generally requires multiple configuration steps with AAD, and in some cases (depending on the AAD tenant configuration) might require special consent from the administrator of the AAD tenant.

步骤 1:在应用程序与 Azure 数据资源管理器服务之间建立信任关系Step 1: Establish trust relationship between your application and the Azure Data Explorer service

  1. 打开 Azure 门户,确保你已登录到正确的租户(在右上角查看用于登录门户的标识)。Open the Azure portal and make sure that you are signed-in to the correct tenant (see top/right corner for the identity used to sign-in to the portal).

  2. 在资源窗格中,单击“Azure Active Directory”、“应用注册”。 On the resources pane, click Azure Active Directory , then App registrations .

  3. 找到使用代理流的应用程序并将其打开。Locate the application that uses the on-behalf-of flow and open it.

  4. 单击“API 权限”,然后选择“添加权限”。Click API permissions , then Add a permission .

  5. 搜索名为 Azure 数据资源管理器 的应用程序并选择它。Search for the application named Azure Data Explorer and select it.

  6. 选择 user_impersonation / Access KustoSelect user_impersonation / Access Kusto .

  7. 单击“添加权限”。Click Add permission .

步骤 2:在服务器代码中执行令牌交换Step 2: Perform token exchange in your server code

// Create Auth Context for AAD (common or tenant-specific endpoint):
AuthenticationContext authContext = new AuthenticationContext("AAD Authority URL");

// Exchange your token for a Kusto token.
// You will need to provide your application's client ID and secret to authenticate your application
var tokenForKusto = authContext.AcquireTokenAsync(
    "https://{serviceNameAndRegion}.kusto.chinacloudapi.cn",
    new ClientCredential(customerAadWebApplicationClientId, customerAAdWebApplicationSecret),
    new UserAssertion(customerAadWebApplicationToken)).GetAwaiter().GetResult();

步骤 3:向 Kusto 客户端库提供令牌并执行查询Step 3: Provide the token to Kusto client library and execute queries

var kcsb = new KustoConnectionStringBuilder(string.Format(
    "https://{0}.kusto.chinacloudapi.cn;fed=true;UserToken={1}",
    clusterName,
    tokenForKusto.AccessToken));
var client = KustoClientFactory.CreateCslQueryProvider(kcsb);
var queryResult = client.ExecuteQuery(databaseName, query, null);

Web 客户端 (JavaScript) 身份验证和授权Web Client (JavaScript) authentication and authorization

详细信息Details

如果客户端是在用户浏览器中运行的 JavaScript 代码,则使用隐式授权流。When the client is a JavaScript code running in the user's browser, the implicit grant flow is used. 在身份验证成功后,会立即在重定向 URI 中(在 URI 片段中)提供授权客户端应用程序访问 Azure 数据资源管理器服务的令牌;此流中不提供刷新令牌,因此客户端无法长时间缓存令牌并重新使用它。The token granting the client application access to the Azure Data Explorer service is provided immediately following a successful authentication as part of the redirect URI (in a URI fragment); no refresh token is given in this flow, so the client can't cache the token for prolonged periods of time and reuse it.

与原生客户端流一样,应该有两个相互之间具有已配置的关系的 AAD 应用程序(服务器和客户端)。Like in the native client flow, there should be two AAD applications (Server and Client) with a configured relationship between them.

AdalJs 需要在进行任何 access_token 调用之前获取 id_token。AdalJs requires getting an id_token before any access_token calls are made.

访问令牌是通过调用 AuthenticationContext.login() 方法获取的,access_token 是通过调用 Authenticationcontext.acquireToken() 获取的。Access token is obtains by calling the AuthenticationContext.login() method, and access_tokens are obtained by calling Authenticationcontext.acquireToken().

  • 使用正确的配置创建 AuthenticationContext:Create an AuthenticationContext with the right configuration:
var config = {
    tenant: "microsoft.com",
    clientId: "<Web AAD app with current website as reply URL. for example, KusDash uses f86897ce-895e-44d3-91a6-aaeae54e278c>",
    redirectUri: "<where you'd like AAD to redirect after authentication succeeds (or fails).>",
    postLogoutRedirectUri: "where you'd like AAD to redirect the browser after logout."
};

var authContext = new AuthenticationContext(config);
  • 如果尚未登录,请先调用 authContext.login(),然后再尝试 acquireToken()Call authContext.login() before trying to acquireToken() if you are not logged in. (若要了解你是否已登录,一个好办法是调用 authContext.getCachedUser(),看它是否返回 falsea good way ot know if you're logged in or not is to call authContext.getCachedUser() and see if it returns false)
  • 每次加载页面时都调用 authContext.handleWindowCallback()Call authContext.handleWindowCallback() whenever your page loads. 这段代码从 AAD 截获重定向,然后从片段 URL 中提取令牌并缓存它。This is the piece of code that intercepts the redirect back from AAD and pulls the token out of the fragment URL and caches it.
  • 调用 authContext.acquireToken() 以获取实际的访问令牌,此时你已拥有有效的 ID 令牌。Call authContext.acquireToken() to get the actual access token, now that you have a valid ID token. acquireToken 的第一个参数将是 Kusto 服务器 AAD 应用程序资源 URL。The first parameter to acquireToken will be the Kusto server AAD application resource URL.
 authContext.acquireToken("<Kusto cluster URL>", callbackThatUsesTheToken);
  • 在 callbackThatUsesTheToken 中,可以使用此令牌作为 Azure 数据资源管理器请求中的持有者令牌。in the callbackThatUsesTheToken you can use the token as a bearer token in the Azure Data Explorer request. 例如:for example:
var settings = {
    url: "https://" + clusterAndRegionName + ".kusto.chinacloudapi.cn/v1/rest/query",
    type: "POST",
    data: JSON.stringify({
        "db": dbName,
        "csl": query,
        "properties": null
    }),
    contentType: "application/json; charset=utf-8",
    headers: { "Authorization": "Bearer " + token },
    dataType: "json",
    jsonp: false,
    success: function(data, textStatus, jqXHR) {
        if (successCallback !== undefined) {
            successCallback(data.Tables[0]);
        }

    },
    error: function(jqXHR, textStatus, errorThrown) {
        if (failureCallback !==  undefined) {
            failureCallback(textStatus, errorThrown, jqXHR.responseText);
        }

    },
};

$.ajax(settings).then(function(data) {/* do something wil the data */});

警告 - 在进行身份验证时,如果收到以下异常或类似的异常:ReferenceError: AuthenticationContext is not definedWarning - if you get the following or similar exception when authenticating: ReferenceError: AuthenticationContext is not defined 可能是因为在全局命名空间中没有 AuthenticationContext。it's probably because you don't have AuthenticationContext in the global namespace. 遗憾的是,AdalJS 当前有一个未公开的要求,即身份验证上下文需在全局命名空间中定义。Unfortunately AdalJS currently has an undocumented requirement that the authentication context will be defined in the global namespace.