앱에서 MSAL(Microsoft 인증 라이브러리)을 사용하여 인증하는 방법

클러스터를 사용하여 프로그래밍 방식으로 인증하려면 Azure Data Explorer 특정 Microsoft Entra ID에서 액세스 토큰을 요청해야 합니다. 이 액세스 토큰은 클러스터에 요청을 발급할 때 ID 증명 역할을 합니다. MSAL(Microsoft 인증 라이브러리)흐름 중 하나를 사용하여 액세스 토큰을 만들 수 있습니다.

이 문서에서는 MSAL을 사용하여 클러스터에 보안 주체를 인증하는 방법을 설명합니다. MSAL을 직접 사용하여 보안 주체를 인증하는 것은 주로 OBO(On-Behalf-of) 인증 또는 SPA(단일 페이지 애플리케이션) 인증이 필요한 웹 애플리케이션과 관련이 있습니다. 다른 경우에는 인증 프로세스를 간소화할 때 Kusto 클라이언트 라이브러리 를 사용하는 것이 좋습니다.

이 문서에서는 기본 인증 시나리오, 성공적인 인증을 위해 제공할 정보 및 인증에 MSAL 사용에 대해 알아봅니다.

인증 시나리오

기본 인증 시나리오는 다음과 같습니다.

  • 사용자 인증: 사용자 ID를 확인하는 데 사용됩니다.

  • 애플리케이션 인증: 구성된 자격 증명을 사용하여 사람의 개입 없이 리소스에 액세스해야 하는 애플리케이션의 ID를 확인하는 데 사용됩니다.

  • OBO(On-Behalf-of) 인증: 애플리케이션이 해당 애플리케이션에 대한 토큰을 토큰과 교환하여 Kusto 서비스에 액세스할 수 있도록 허용합니다. 이 흐름은 MSAL을 사용하여 구현해야 합니다.

  • SPA(단일 페이지 애플리케이션) 인증: 클라이언트 쪽 SPA 웹 애플리케이션에서 사용자를 로그인하고 클러스터에 액세스하기 위한 토큰을 가져올 수 있습니다. 이 흐름은 MSAL을 사용하여 구현해야 합니다.

사용자 및 애플리케이션 인증의 경우 Kusto 클라이언트 라이브러리를 사용하는 것이 좋습니다. OBO 및 SPA 인증의 경우 Kusto 클라이언트 라이브러리를 사용할 수 없습니다.

인증 매개 변수

토큰 획득 프로세스 중에 클라이언트는 다음 매개 변수를 제공해야 합니다.

매개 변수 이름 Description
리소스 ID Microsoft Entra 액세스 토큰을 발급할 리소스 ID입니다. 리소스 ID는 포트 정보 및 경로가 없는 클러스터 URI입니다.

: 클러스터의 리소스 ID는 help 입니다 https://help.kusto.windows.net.
테넌트 ID Microsoft Entra Microsoft Entra ID는 다중 테넌트 서비스이며 모든 organization 사용자 계정 및 애플리케이션과 같은 보안 관련 개체를 보유하는 디렉터리라는 개체를 만들 수 있습니다. Microsoft Entra ID는 종종 디렉터리를 테넌트라고 합니다. 각 테넌트마다 GUID 형식의 테넌트 ID가 있습니다. 대부분의 경우 organization 도메인 이름을 사용하여 Microsoft Entra 테넌트 ID를 지정할 수도 있습니다.

: organization "Contoso"에는 테넌트 ID 12345678-a123-4567-b890-123a456b789c 와 도메인 이름이 contoso.com있을 수 있습니다.
Microsoft Entra 기관 URI 인증에 사용되는 엔드포인트입니다. Microsoft Entra 디렉터리 또는 테넌트는 Microsoft Entra 기관 URI를 결정합니다. URI는 https://login.microsoftonline.com/{tenantId} 여기서 {tenantId} 는 테넌트 ID 또는 도메인 이름입니다.

: 예를 들면 입니다 https://login.microsoftonline.com/12345678-a123-4567-b890-123a456b789c.

참고

Microsoft Entra 서비스 엔드포인트는 국가별 클라우드에서 변경됩니다. 국가별 클라우드에 배포된 Azure Data Explorer 서비스로 작업할 때 해당 국가별 클라우드 Microsoft Entra 서비스 엔드포인트를 설정합니다.

MSAL을 사용하여 사용자 인증 수행

다음 코드 샘플에서는 MSAL을 사용하여 클러스터에 대한 권한 부여 토큰을 가져오는 방법을 보여줍니다. 권한 부여는 대화형 로그인 UI를 시작하는 방식으로 수행됩니다. 는 appRedirectUri 인증이 성공적으로 완료된 후 Microsoft Entra ID가 리디렉션되는 URL입니다. MSAL은 이 리디렉션에서 권한 부여 코드를 추출합니다.

var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";

var authClient = PublicClientApplicationBuilder.Create("<appId>")
    .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
    .WithRedirectUri("<appRedirectUri>")
    .Build();

var result = authClient.AcquireTokenInteractive(
    new[] { $"{kustoUri}/.default" } // Define scopes for accessing Azure Data Explorer cluster
).ExecuteAsync().Result;

var bearerToken = result.AccessToken;

var request = WebRequest.Create(new Uri(kustoUri));
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

참고

  • 가능한 경우 Kusto 클라이언트 라이브러리를 사용하는 것이 좋습니다. 이러한 라이브러리는 Kusto 연결 문자열 인증 속성을 제공할 수 있도록 하여 인증 프로세스를 간소화합니다.
  • Kusto 클라이언트 라이브러리를 사용하면 Microsoft Entra 토큰이 사용자 컴퓨터의 로컬 토큰 캐시에 저장되어 자격 증명을 묻는 메시지가 표시되는 횟수를 줄입니다. 캐시 파일은 %APPDATA%\Kusto\userTokenCache.data 이며 로그인한 사용자만 액세스할 수 있습니다.

MSAL을 사용하여 애플리케이션 인증 수행

다음 코드 샘플에서는 MSAL을 사용하여 클러스터에 대한 권한 부여 토큰을 가져오는 방법을 보여줍니다. 이 흐름에서는 프롬프트가 표시되지 않습니다. 애플리케이션은 Microsoft Entra ID로 등록해야 하며 앱 키 또는 Microsoft Entra ID에서 발급한 X509v2 인증서가 있어야 합니다. 애플리케이션을 설정하려면 Microsoft Entra 애플리케이션 프로비저닝을 참조하세요.

var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";

var authClient = ConfidentialClientApplicationBuilder.Create("<appId>")
    .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
    .WithClientSecret("<appKey>") // Can be replaced by .WithCertificate to authenticate with an X.509 certificate
    .Build();

var result = authClient.AcquireTokenForClient(
    new[] { $"{kustoUri}/.default" } // Define scopes for accessing Azure Data Explorer cluster
).ExecuteAsync().Result;
var bearerToken = result.AccessToken;

var request = WebRequest.Create(new Uri(kustoUri));
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

참고

가능한 경우 Kusto 클라이언트 라이브러리를 사용하는 것이 좋습니다. 이러한 라이브러리는 Kusto 연결 문자열 인증 속성을 제공할 수 있도록 하여 인증 프로세스를 간소화합니다.

OBO(On-Behalf-of) 인증 수행

웹 애플리케이션 또는 서비스가 사용자 또는 애플리케이션과 클러스터 간의 중재자 역할을 하는 경우 대신 인증이 관련됩니다.

이 시나리오에서는 애플리케이션이 임의 리소스에 대한 Microsoft Entra 액세스 토큰을 보냅니다. 그런 다음, 애플리케이션은 해당 토큰을 사용하여 Azure Data Explorer 리소스에 대한 새 Microsoft Entra 액세스 토큰을 획득합니다. 그런 다음 애플리케이션은 원래 Microsoft Entra 액세스 토큰으로 표시된 보안 주체를 대신하여 클러스터에 액세스할 수 있습니다. 이 흐름을 OAuth 2.0 대신 인증 흐름이라고 합니다. 일반적으로 Microsoft Entra ID가 있는 여러 구성 단계가 필요하며 경우에 따라 Microsoft Entra 테넌트 관리자의 특별한 동의가 필요할 수 있습니다.

대신 인증을 수행하려면 다음을 수행합니다.

  1. Microsoft Entra 애플리케이션을 프로비전합니다.

  2. 애플리케이션과 클러스터 간에 트러스트 관계를 설정합니다. 이렇게 하려면 위임된 권한 구성의 단계를 수행합니다.

  3. 서버 코드에서 MSAL을 사용하여 토큰 교환을 수행합니다.

    var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";
    
    var authClient = ConfidentialClientApplicationBuilder.Create("<appId>")
        .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
        .WithClientSecret("<appKey>") // Can be replaced by .WithCertificate to authenticate with an X.509 certificate
        .Build();
    
    var result = authClient.AcquireTokenOnBehalfOf(
        new[] { $"{kustoUri}/.default" }, // Define scopes for accessing your cluster
        new UserAssertion("<userAccessToken>") // Encode the "original" token that will be used for exchange
    ).ExecuteAsync().Result;
    var accessTokenForAdx = result.AccessToken;
    
  4. 토큰을 사용하여 쿼리를 실행합니다. 예를 들면 다음과 같습니다.

    var request = WebRequest.Create(new Uri(kustoUri));
    request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", accessTokenForAdx));
    

SPA(단일 페이지 애플리케이션) 인증 수행

SPA 웹 클라이언트에 대한 인증의 경우 OAuth 권한 부여 코드 흐름을 사용합니다.

이 시나리오에서는 앱이 Microsoft Entra ID로 로그인하도록 리디렉션됩니다. 그런 다음, Microsoft Entra ID는 URI의 권한 부여 코드를 사용하여 앱으로 다시 리디렉션됩니다. 그런 다음, 앱은 액세스 토큰을 가져오기 위해 토큰 엔드포인트에 요청합니다. 토큰은 클라이언트가 토큰을 자동으로 획득하여 다시 사용할 수 있는 24시간 동안 유효합니다.

Microsoft ID 플랫폼 React,AngularJavaScript와 같은 다양한 사용 사례에 대한 자세한 자습서가 있습니다.

웹 클라이언트에 대한 인증을 설정하려면 다음을 수행합니다.

  1. Microsoft Entra 애플리케이션을 프로비전합니다.

  2. 인증 코드 흐름을 사용하여MSAL.js 2.0에 설명된 대로 앱을 구성합니다.

  3. MSAL.js 2.0 라이브러리를 사용하여 사용자를 로그인하고 클러스터에 인증합니다. Microsoft ID 플랫폼 React,AngularJavaScript와 같은 다양한 사용 사례에 대한 자세한 자습서가 있습니다.

    다음 예제에서는 MSAL.js 라이브러리를 사용하여 Azure Data Explorer 액세스합니다.

    import * as msal from "@azure/msal-browser";
    
    const msalConfig = {
      auth: {
        clientId: "<AAD client application ID>",
        authority: "https://login.microsoftonline.com/<AAD tenant ID>",
      },
    };
    
    const msalInstance = new msal.PublicClientApplication(msalConfig);
    const myAccounts = msalInstance.getAllAccounts();
    
    // If no account is logged in, redirect the user to log in.
    if (myAccounts === undefined || myAccounts.length === 0) {
      try {
        await msalInstance.loginRedirect({
          scopes: ["https://help.kusto.windows.net/.default"],
        });
      } catch (err) {
        console.error(err);
      }
    }
    const account = myAccounts[0];
    const name = account.name;
    window.document.getElementById("main").innerHTML = `Hi ${name}!`;
    
    // Get the access token required to access the specified Azure Data Explorer cluster.
    const accessTokenRequest = {
      account,
      scopes: ["https://help.kusto.windows.net/.default"],
    };
    let acquireTokenResult = undefined;
    try {
      acquireTokenResult = await msalInstance.acquireTokenSilent(accessTokenRequest);
    } catch (error) {
      if (error instanceof InteractionRequiredAuthError) {
        await msalInstance.acquireTokenRedirect(accessTokenRequest);
      }
    }
    
    const accessToken = acquireTokenResult.accessToken;
    
    // Make requests to the specified cluster with the token in the Authorization header.
    const fetchResult = await fetch("https://help.kusto.windows.net/v2/rest/query", {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
      method: "POST",
      body: JSON.stringify({
        db: "Samples",
        csl: "StormEvents | count",
      }),
    });
    const jsonResult = await fetchResult.json();
    
    // The following line extracts the first cell in the result data.
    const count = jsonResult.filter((x) => x.TableKind === "PrimaryResult")[0].Rows[0][0];