Microsoft.Identity.Web을 통한 다운스트림 API 통합

Microsoft. Identity.Web은 ASP.NET Core, OWIN 또는 .NET 애플리케이션에서 Microsoft Graph, Azure 서비스 및 사용자 지정 REST API를 포함하여 다운스트림 API를 호출하는 여러 방법을 제공합니다. 이 문서는 시나리오에 적합한 방법을 선택하고 빠르게 시작하는 데 도움이 됩니다.

접근 방식 선택

이 의사 결정 트리를 사용하여 시나리오에 가장 적합한 방법을 선택합니다.

API 유형/시나리오 의사 결정/조건 권장 클라이언트/클래스
Microsoft Graph Microsoft Graph API를 호출해야 합니다. GraphServiceClient
Azure SDK(스토리지, KeyVault 등) Azure API(Azure SDK)를 호출해야 합니다. Azure SDK 클라이언트를 사용하는 MicrosoftIdentityTokenCredential
토큰 바인딩을 사용하는 사용자 지정 API 인증서 바인딩을 사용하여 보안 강화(mTLS PoP) IDownstreamApi와 ProtocolScheme: "MTLS_POP"
토큰 바인딩을 사용하는 사용자 지정 API HttpClient 통합을 통한 보안 강화(mTLS PoP) MicrosoftIdentityMessageHandler ProtocolScheme: "MTLS_POP"
사용자 지정 API 간단하고 구성 가능 IDownstreamApi
사용자 지정 API HttpClient + 위임 처리기 사용 MicrosoftIdentityMessageHandler
사용자 지정 API HttpClient 사용하기 IAuthorizationHeaderProvider

복잡성 및 유연성별 접근 방식 비교

다음 표에는 의도한 사용 사례, 복잡성 수준 및 유연성별로 각 접근 방식이 요약되어 있습니다.

접근법 적합한 대상 복잡성 Configuration 유연성
GraphServiceClient Microsoft Graph API Low Simple 중간
MicrosoftIdentityTokenCredential Azure SDK 클라이언트 Low Simple Low
IDownstreamApi 표준 패턴이 있는 REST API Low JSON + 코드 중간
MicrosoftIdentityMessageHandler 인증 파이프라인이 있는 HttpClient 중간 코드 높음
IAuthorizationHeaderProvider 사용자 지정 인증 논리 높음 코드 매우 높음

토큰 획득 패턴

Microsoft. Identity.Web은 세 가지 기본 토큰 획득 패턴을 지원합니다.

graph LR
    A[Token Acquisition] --> B[Delegated<br/>On behalf of user]
    A --> C[App-Only<br/>Application permissions in all apps]
    A --> D[On-Behalf-Of OBO<br/>in web API]

    B --> B1[Web Apps]
    B --> B2[Daemon acting as user / user agent]
    C --> C1[Daemon Apps]
    C --> C2[Web APIs with app permissions]
    D --> D1[Web APIs calling other APIs]

    style B fill:#cfe2ff
    style C fill:#fff3cd
    style D fill:#f8d7da

위임된 권한(사용자 토큰)

애플리케이션이 로그인한 사용자를 대신하여 작동할 때 위임된 권한을 사용합니다.

  • 시나리오: 웹앱은 로그인한 사용자 및 자율 에이전트 사용자 ID를 대신하여 API를 호출합니다.
  • 토큰 유형: 위임된 권한이 있는 액세스 토큰
  • 메서드: CreateAuthorizationHeaderForUserAsync()GetForUserAsync()

애플리케이션 권한(앱 전용 토큰)

사용자가 없고 앱이 자체 인증하는 경우 애플리케이션 권한을 사용합니다.

  • 시나리오: 디먼 앱 또는 백그라운드 서비스가 API를 호출합니다. 자율 에이전트 신원
  • 토큰 유형: 애플리케이션 권한이 있는 액세스 토큰
  • 메서드: CreateAuthorizationHeaderForAppAsync()GetForAppAsync()

OBO(On-Behalf-Of) 흐름

사용자의 ID를 유지하면서 웹 API가 다른 다운스트림 API를 호출해야 하는 경우 OBO 흐름을 사용합니다.

  • 시나리오: Web API는 사용자 토큰을 수신하고 해당 사용자 및 대화형 에이전트를 대신하여 다른 API를 호출합니다.
  • 토큰 유형: OBO 흐름을 통한 새 액세스 토큰
  • 메서드: CreateAuthorizationHeaderForUserAsync() 웹 API 컨텍스트에서

토큰 바인딩(mTLS PoP)

토큰 바인딩은 X.509 인증서에 액세스 토큰을 암호화하여 추가 보안 계층을 추가합니다.

  • 시나리오: RFC 8705에 따라 토큰이 인증서에 암호화적으로 바인딩되는 보안 강화
  • 토큰 유형: 인증서 바인딩을 사용하여 액세스 토큰(cnf 클레임)
  • 메서드: GetForAppAsync()ProtocolScheme: "MTLS_POP"와 함께
  • 보안: 특정 인증서에 토큰을 바인딩하여 토큰 도난 방지

mTLS PoP를 사용하여 토큰 바인딩에 대해 자세히 알아보기

빠른 시작 코드 예제

다음 예제에서는 애플리케이션에 적응할 수 있는 엔드 투 엔드 코드를 사용하여 각 방법을 보여 줍니다.

다음 예제에서는 GraphServiceClient 등록하고 로그인한 사용자를 대신하여 앱 전용 호출로 Microsoft Graph 호출하는 데 사용합니다.

// Installation
// dotnet add package Microsoft.Identity.Web.GraphServiceClient

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftGraph();

// Usage in controller
public class HomeController : Controller
{
    private readonly GraphServiceClient _graphClient;

    public HomeController(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<IActionResult> Profile()
    {
        // Delegated - calls on behalf of signed-in user
        var user = await _graphClient.Me.GetAsync();

        // App-only - requires app permissions
        var users = await _graphClient.Users
            .GetAsync(r => r.Options.WithAppOnly());

        return View(user);
    }
}

Microsoft Graph 통합에 대해 자세히 알아보세요

GraphServiceClient 마이그레이션 및 자세한 사용

다음 예제에서는 MicrosoftIdentityTokenCredential 등록하고 Azure Blob Storage 클라이언트에 전달합니다.

// Installation
// dotnet add package Microsoft.Identity.Web.Azure
// dotnet add package Azure.Storage.Blobs

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftIdentityAzureTokenCredential();

// Usage
public class StorageService
{
    private readonly MicrosoftIdentityTokenCredential _credential;

    public StorageService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }

    public async Task<List<string>> ListBlobsAsync()
    {
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);

        var container = blobClient.GetBlobContainerClient("mycontainer");
        var blobs = new List<string>();

        await foreach (var blob in container.GetBlobsAsync())
        {
            blobs.Add(blob.Name);
        }

        return blobs;
    }
}

Azure SDK 통합에 대해 자세히 알아보세요

다음 예제에서는 명명된 다운스트림 API를 appsettings.json 구성하고 위임된 토큰과 앱 전용 토큰을 모두 사용하여 호출합니다.

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "DownstreamApis": {
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read", "api://myapi/write"]
    }
  }
}

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddDownstreamApis(
    builder.Configuration.GetSection("DownstreamApis"));

// Usage
public class ApiService
{
    private readonly IDownstreamApi _api;

    public ApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<Product> GetProductAsync(int id)
    {
        // Delegated - on behalf of user
        return await _api.GetForUserAsync<Product>(
            "MyApi",
            $"api/products/{id}"
        );
    }

    public async Task<List<Product>> GetAllProductsAsync()
    {
        // App-only - using app permissions
        return await _api.GetForAppAsync<List<Product>>(
            "MyApi",
            "api/products");
    }
}

IDownstreamApi에 대해 자세히 알아보기

mTLS PoP를 사용하여 토큰 바인딩(보안 강화)

토큰 바인딩은 X.509 인증서에 액세스 토큰을 암호화적으로 바인딩하여 향상된 보안을 제공합니다. 토큰이 가로채더라도 해당 인증서 없이는 사용할 수 없습니다.

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "StoreWithDistinguishedName",
        "CertificateStorePath": "CurrentUser/My",
        "CertificateDistinguishedName": "CN=YourCertificate"
      }
    ],
    "SendX5c": true
  },
  "SecureApi": {
    "BaseUrl": "https://api.contoso.com/",
    "RelativePath": "api/data",
    "ProtocolScheme": "MTLS_POP",
    "RequestAppToken": true,
    "Scopes": [ "api://your-api/.default" ]
  }
}

// Startup configuration
builder.Services.AddDownstreamApi(
    "SecureApi",
    builder.Configuration.GetSection("SecureApi"));

// Usage
public class SecureApiService
{
    private readonly IDownstreamApi _api;

    public SecureApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<SecureData> GetSecureDataAsync()
    {
        // Token is bound to certificate - enhanced security
        return await _api.GetForAppAsync<SecureData>("SecureApi");
    }
}

주요 이점:

  • 토큰 도난 방지: 도난당한 토큰은 인증서 없이는 쓸모가 없습니다.
  • 재생 공격 방지: 다른 클라이언트에서 토큰을 재생할 수 없습니다.
  • 제로 트러스트 정렬: 클라이언트와 토큰 간의 강력한 암호화된 결합

토큰 바인딩에 대한 자세한 정보(mTLS PoP)

MicrosoftIdentityMessageHandler(HttpClient 통합용)

다음 예제에서는 보내는 모든 요청에 권한 부여 헤더가 자동으로 포함되도록 위임 처리기를 HttpClient 추가합니다. 처리기는 시작 시 범위를 등록하고 개별 요청은 토큰 옵션을 재정의할 수 있습니다.

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddHttpClient("MyApiClient", client =>
{
    client.BaseAddress = new Uri("https://myapi.example.com");
})
.AddHttpMessageHandler(sp => new MicrosoftIdentityMessageHandler(
    sp.GetRequiredService<IAuthorizationHeaderProvider>(),
    new MicrosoftIdentityMessageHandlerOptions
    {
        Scopes = new[] { "api://myapi/.default" }
    }));

// Usage
public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("MyApiClient");
    }

    public async Task<Product> GetProductAsync(int id)
    {
        var request = new HttpRequestMessage(HttpMethod.Get, $"api/products/{id}")
            .WithAuthenticationOptions(options =>
            {
                options.RequestAppToken = false; // Use delegated token
                options.scopes = [ "myApi.scopes" ];
            });

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<Product>();
    }
}

MicrosoftIdentityMessageHandler에 대해 자세히 알아보기

IAuthorizationHeaderProvider(최대 유연성)

다음 예제에서는 사용자 지정 헤더와 함께 HTTP 요청에 연결할 수 있도록 권한 부여 헤더를 직접 검색합니다.

// Direct usage for custom scenarios
public class CustomAuthService
{
    private readonly IAuthorizationHeaderProvider _headerProvider;

    public CustomAuthService(IAuthorizationHeaderProvider headerProvider)
    {
        _headerProvider = headerProvider;
    }

    public async Task<string> CallApiAsync()
    {
        // Get auth header (includes "Bearer " + token)
        string authHeader = await _headerProvider
            .CreateAuthorizationHeaderForUserAsync(
                scopes: new[] { "api://myapi/.default" });

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", authHeader);
        client.DefaultRequestHeaders.Add("X-Custom-Header", "MyValue");

        var response = await client.GetStringAsync("https://myapi.example.com/data");
        return response;
    }
}

IAuthorizationHeaderProvider에 대해 자세히 알아보기

구성 패턴

Microsoft. Identity.Web은 JSON 구성과 코드 기반 구성을 모두 지원합니다.

appsettings.json 구성

다음 JSON은 Microsoft Entra ID 자격 증명과 두 개의 다운스트림 API를 등록하는 일반적인 구성을 보여 줍니다.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity"
      }
    ]
  },
  "DownstreamApis": {
    "MicrosoftGraph": {
      "BaseUrl": "https://graph.microsoft.com/v1.0",
      "Scopes": ["User.Read", "Mail.Read"]
    },
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read"]
    }
  }
}

Note

디먼/콘솔 앱의 경우 속성을 설정합니다 appsettings.json . "출력 디렉터리에 복사" = "최신인 경우 복사"

자격 증명 구성에 대해 자세히 알아보기

코드 기반 구성

다음 예제와 같이 완전히 코드에서 자격 증명 및 다운스트림 API를 구성할 수도 있습니다.

// Explicit configuration in code
builder.Services.Configure<MicrosoftIdentityApplicationOptions>(options =>
{
    options.Instance = "https://login.microsoftonline.com/";
    options.TenantId = "your-tenant-id";
    options.ClientId = "your-client-id";
    options.ClientCredentials = new[]
    {
        CertificateDescription.FromKeyVault(
            "https://myvault.vault.azure.net",
            "MyCertificate")
    };
});

builder.Services.AddDownstreamApi("MyApi", options =>
{
    options.BaseUrl = "https://myapi.example.com";
    options.Scopes = new[] { "api://myapi/read" };
});

시나리오별 가이드

가장 좋은 방법은 API를 호출하는 위치에 따라 달라집니다.

웹앱 통합

웹앱은 일반적으로 로그인한 사용자를 대신하여 다운스트림 API를 호출합니다.

  • 기본 패턴: 위임된 권한(사용자 대신)
  • 토큰 획득: 로그인하는 동안 자동으로 발생합니다.
  • 특별 고려 사항: 증분 동의, 동의 실패 처리

Web Apps 가이드를 읽습니다

Web API 통합

Web API는 On-Behalf-Of 흐름을 사용하여 들어오는 사용자 토큰을 다운스트림 API로 범위가 설정된 새 토큰으로 교환합니다.

  • 기본 패턴: OBO(on-Behalf-Of) 흐름
  • 토큰 획득: 들어오는 토큰을 다운스트림 토큰으로 교환
  • 특별 고려 사항: 장기 실행 프로세스, 토큰 캐싱, 에이전트 ID.

Web API 가이드 읽기

디먼 앱 통합

디먼 앱은 로그인한 사용자 없이 스스로 인증합니다.

  • 기본 패턴: 애플리케이션 권한(앱 전용)
  • 토큰 획득: 클라이언트 자격 증명 흐름
  • 특별 고려 사항: 사용자 컨텍스트 없음, 관리자 동의 필요
  • 고급: 자율 에이전트, 에이전트 사용자 ID

디먼 애플리케이션 가이드 읽기

토큰 획득에 대한 오류 처리

모든 토큰 획득 메서드는 애플리케이션에서 처리해야 하는 예외를 발생시킬 수 있습니다. 웹앱에서 [AuthorizeForScope(scopes)] 속성은 사용자 점진적 동의 또는 다시 인증을 처리합니다.

다음 예제에서는 일반적인 토큰 획득 예외를 catch하고 처리하는 방법을 보여 줍니다.

using Microsoft.Identity.Abstractions;

try
{
    var result = await _api.GetForUserAsync<Data>("MyApi", "api/data");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
    // User needs to sign in or consent to additional scopes
    // In web apps, this triggers a redirect to Microsoft Entra ID
    throw;
}
catch (HttpRequestException ex)
{
    // Downstream API returned error
    _logger.LogError(ex, "API call failed");
}

일반적인 오류 시나리오

다음 표에서는 가장 일반적인 예외 및 해결 방법을 나열합니다.

예외 Meaning 해결 방법
MicrosoftIdentityWebChallengeUserException 사용자 동의 필요 Microsoft Entra ID로 동의를 위한 리디렉션하십시오. AuthorizeForScopes 특성 또는 ConsentHandler 클래스 사용
MsalUiRequiredException 대화형 인증 필요 웹앱에서 챌린지를 처리하기
MsalServiceException Microsoft Entra ID 서비스 오류 구성 확인, 다시 시도
HttpRequestException 다운스트림 API 오류 API 관련 오류 처리

필요한 NuGet 패키지

시나리오와 일치하는 패키지를 선택합니다. 다음 표에는 각 패키지와 사용 시기가 나열되어 있습니다.

Package Purpose 사용 시기
Microsoft. Identity.Web.TokenAcquisition 토큰 획득 서비스 핵심 패키지
Microsoft. Identity.Web.DownstreamApi IDownstreamApi 추상화 REST API 호출
Microsoft. Identity.Web.GraphServiceClient Microsoft Graph 통합 Microsoft Graph 호출(마이그레이션 가이드)
Microsoft. Identity.Web. Azure Azure SDK 통합 Azure 서비스 호출
Microsoft. Identity.Web 웹앱 및 웹 API ASP.NET Core ASP.NET Core
Microsoft. Identity.Web.OWIN OWIN 웹앱 및 웹 API ASP.NET OWIN

자세한 연습 및 고급 시나리오에 대한 가이드를 살펴보세요.