如何使用安全声明代表 AAD 用户调用 Web API?

How do I call a web API on behalf of an AAD user using security claims?

所以,为了让您大致了解我要实现的目标,我有一个 Web 应用程序,它 使用 AAD 身份验证,因此用户需要登录到 Microsoft 组织帐户 为了使用 Web 应用程序中实现的大多数控制器(以 .NET Core 为目标)。 Visual Studio 提供了用于此类 Web 应用程序设置的模板。这个 template project 好像获取用户的身份是一个"ClaimsIdentity"(System.Security.Claims.ClaimsIdentity),目前是可以的,只要 因为用户已通过 AAD 身份验证。 我还有一个 .NET Core Web API 解决方案,Web 应用程序需要代表 登录用户。所以,我有一个网络应用程序,它让用户登录到 AAD,然后是一个网络 API( Web 应用程序调用),它具有期望 AAD 身份验证请求的控制器端点。 为此,我的理解是网络应用程序需要包含已登录的身份 Microsoft,(在本例中是安全提供商)在 header 的 它向 API 发出的请求。然后 API 将能够查看用户声明并采取相应行动。

问题就在这里。作为 header,我认为我需要提供 Microsoft 发送的访问令牌 到网络应用程序..但是我找不到这个令牌。我能从 User 或 User.Identity 中提取的只是声明。如何 我可以代表这些声明单独调用 API 吗?我需要完全无视模板吗 Microsoft 提供并调用 /token 端点?我只想以正确的方式做到这一点:)

这是 Web 应用启动中的 ConfigureServices 方法 class:

public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => Configuration.Bind("AzureAd", options));

        services.AddMvc(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

这是我想代表登录的 AAD 调用外部 Web API 以获取 所需数据:

public IActionResult Index()
    {
        var user = User.Identity as ClaimsIdentity;

        var request = (HttpWebRequest)WebRequest.Create("http://localhost:4110/data");
        request.Headers["Authorization"] = "bearer " + getAccessToken_using_user;

        var response = (HttpWebResponse)request.GetResponse();

        var dataString = new StreamReader(response.GetResponseStream()).ReadToEnd();

        return View();
}

当然,我的意图是将 "getAccessToken_using_user" 替换为 Microsoft 应该为 Web 应用程序提供的访问令牌,如他们的 diagram 所示。

您可以使用 MSAL 获取下游的访问令牌 API。

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/on-behalf-of#practical-usage-of-obo-in-an-aspnet--aspnet-core-application

这是代表流程的完整示例:

https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/2.%20Web%20API%20now%20calls%20Microsoft%20Graph

public static IServiceCollection AddProtectedApiCallsWebApis(this IServiceCollection services, IConfiguration configuration, IEnumerable<string> scopes)
{
 ...
 services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
 {
  options.Events.OnTokenValidated = async context =>
  {
   var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
   context.Success();

   // Adds the token to the cache, and also handles the incremental consent and claim challenges
   tokenAcquisition.AddAccountToCacheFromJwt(context, scopes);
   await Task.FromResult(0);
  };
 });
 return services;
}
private async Task GetTodoList(bool isAppStarting)
{
 ...
 //
 // Get an access token to call the To Do service.
 //
 AuthenticationResult result = null;
 try
 {
  result = await _app.AcquireTokenSilent(Scopes, accounts.FirstOrDefault())
                     .ExecuteAsync()
                     .ConfigureAwait(false);
 }
...

// Once the token has been returned by MSAL, add it to the http authorization header, before making the call to access the To Do list service.
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

// Call the To Do list service.
HttpResponseMessage response = await _httpClient.GetAsync(TodoListBaseAddress + "/api/todolist");
...
}